Initial commit with linaro-swg sources 26/148026/2
authoregukim <egukim@dignsys.com>
Tue, 22 Aug 2017 14:00:34 +0000 (23:00 +0900)
committereunggu kim <egukim@dignsys.com>
Wed, 6 Sep 2017 10:22:50 +0000 (10:22 +0000)
Change-Id: I7b74307298c1c6f5798c0c5cd448c308db7f4931
Signed-off-by: egukim <egukim@dignsys.com>
338 files changed:
Makefile [new file with mode: 0644]
acknowledgements.md [new file with mode: 0644]
bl1/aarch64/bl1_arch_setup.c [new file with mode: 0644]
bl1/aarch64/bl1_entrypoint.S [new file with mode: 0644]
bl1/aarch64/bl1_exceptions.S [new file with mode: 0644]
bl1/bl1.ld.S [new file with mode: 0644]
bl1/bl1.mk [new file with mode: 0644]
bl1/bl1_main.c [new file with mode: 0644]
bl1/bl1_private.h [new file with mode: 0644]
bl2/aarch64/bl2_arch_setup.c [new file with mode: 0644]
bl2/aarch64/bl2_entrypoint.S [new file with mode: 0644]
bl2/bl2.ld.S [new file with mode: 0644]
bl2/bl2.mk [new file with mode: 0644]
bl2/bl2_main.c [new file with mode: 0644]
bl2/bl2_private.h [new file with mode: 0644]
bl31/aarch64/bl31_arch_setup.c [new file with mode: 0644]
bl31/aarch64/bl31_entrypoint.S [new file with mode: 0644]
bl31/aarch64/context.S [new file with mode: 0644]
bl31/aarch64/cpu_data.S [new file with mode: 0644]
bl31/aarch64/crash_reporting.S [new file with mode: 0644]
bl31/aarch64/runtime_exceptions.S [new file with mode: 0644]
bl31/bl31.ld.S [new file with mode: 0644]
bl31/bl31.mk [new file with mode: 0644]
bl31/bl31_main.c [new file with mode: 0644]
bl31/context_mgmt.c [new file with mode: 0644]
bl31/cpu_data_array.c [new file with mode: 0644]
bl31/interrupt_mgmt.c [new file with mode: 0644]
bl31/runtime_svc.c [new file with mode: 0644]
bl32/tsp/aarch64/tsp_entrypoint.S [new file with mode: 0644]
bl32/tsp/aarch64/tsp_exceptions.S [new file with mode: 0644]
bl32/tsp/aarch64/tsp_request.S [new file with mode: 0644]
bl32/tsp/tsp.ld.S [new file with mode: 0644]
bl32/tsp/tsp.mk [new file with mode: 0644]
bl32/tsp/tsp_interrupt.c [new file with mode: 0644]
bl32/tsp/tsp_main.c [new file with mode: 0644]
bl32/tsp/tsp_private.h [new file with mode: 0644]
bl32/tsp/tsp_timer.c [new file with mode: 0644]
common/aarch64/debug.S [new file with mode: 0644]
common/aarch64/early_exceptions.S [new file with mode: 0644]
common/auth.c [new file with mode: 0644]
common/auth/polarssl/polarssl.c [new file with mode: 0644]
common/auth/polarssl/polarssl.mk [new file with mode: 0644]
common/auth/polarssl/polarssl_config.h [new file with mode: 0644]
common/bl_common.c [new file with mode: 0644]
common/tf_printf.c [new file with mode: 0644]
contributing.md [new file with mode: 0644]
docs/change-log.md [new file with mode: 0644]
docs/cpu-specific-build-macros.md [new file with mode: 0644]
docs/diagrams/non-sec-int-handling.png [new file with mode: 0644]
docs/diagrams/rt-svc-descs-layout.png [new file with mode: 0644]
docs/diagrams/sec-int-handling.png [new file with mode: 0644]
docs/firmware-design.md [new file with mode: 0644]
docs/interrupt-framework-design.md [new file with mode: 0644]
docs/optee-dispatcher.md [new file with mode: 0644]
docs/porting-guide.md [new file with mode: 0644]
docs/rt-svc-writers-guide.md [new file with mode: 0644]
docs/trusted-board-boot.md [new file with mode: 0644]
docs/user-guide.md [new file with mode: 0644]
drivers/arm/cci400/cci400.c [new file with mode: 0644]
drivers/arm/gic/arm_gic.c [new file with mode: 0644]
drivers/arm/gic/gic_v2.c [new file with mode: 0644]
drivers/arm/gic/gic_v3.c [new file with mode: 0644]
drivers/arm/gpio/gpio.c [new file with mode: 0644]
drivers/arm/pl011/pl011_console.S [new file with mode: 0644]
drivers/arm/tzc400/tzc400.c [new file with mode: 0644]
drivers/io/io_block.c [new file with mode: 0644]
drivers/io/io_fip.c [new file with mode: 0644]
drivers/io/io_memmap.c [new file with mode: 0644]
drivers/io/io_semihosting.c [new file with mode: 0644]
drivers/io/io_storage.c [new file with mode: 0644]
fdts/fvp-base-gicv2-psci.dtb [new file with mode: 0644]
fdts/fvp-base-gicv2-psci.dts [new file with mode: 0644]
fdts/fvp-base-gicv2legacy-psci.dtb [new file with mode: 0644]
fdts/fvp-base-gicv2legacy-psci.dts [new file with mode: 0644]
fdts/fvp-base-gicv3-psci.dtb [new file with mode: 0644]
fdts/fvp-base-gicv3-psci.dts [new file with mode: 0644]
fdts/fvp-foundation-gicv2-psci.dtb [new file with mode: 0644]
fdts/fvp-foundation-gicv2-psci.dts [new file with mode: 0644]
fdts/fvp-foundation-gicv2legacy-psci.dtb [new file with mode: 0644]
fdts/fvp-foundation-gicv2legacy-psci.dts [new file with mode: 0644]
fdts/fvp-foundation-gicv3-psci.dtb [new file with mode: 0644]
fdts/fvp-foundation-gicv3-psci.dts [new file with mode: 0644]
fdts/fvp-foundation-motherboard-no_psci.dtsi [new file with mode: 0644]
fdts/fvp-foundation-motherboard.dtsi [new file with mode: 0644]
fdts/rtsm_ve-motherboard-no_psci.dtsi [new file with mode: 0644]
fdts/rtsm_ve-motherboard.dtsi [new file with mode: 0644]
include/bl31/bl31.h [new file with mode: 0644]
include/bl31/context.h [new file with mode: 0644]
include/bl31/context_mgmt.h [new file with mode: 0644]
include/bl31/cpu_data.h [new file with mode: 0644]
include/bl31/interrupt_mgmt.h [new file with mode: 0644]
include/bl31/runtime_svc.h [new file with mode: 0644]
include/bl31/services/psci.h [new file with mode: 0644]
include/bl31/services/std_svc.h [new file with mode: 0644]
include/bl32/tsp/platform_tsp.h [new file with mode: 0644]
include/bl32/tsp/tsp.h [new file with mode: 0644]
include/common/asm_macros.S [new file with mode: 0644]
include/common/assert_macros.S [new file with mode: 0644]
include/common/auth.h [new file with mode: 0644]
include/common/bl_common.h [new file with mode: 0644]
include/common/debug.h [new file with mode: 0644]
include/common/firmware_image_package.h [new file with mode: 0644]
include/drivers/arm/arm_gic.h [new file with mode: 0644]
include/drivers/arm/cci400.h [new file with mode: 0644]
include/drivers/arm/gic_v2.h [new file with mode: 0644]
include/drivers/arm/gic_v3.h [new file with mode: 0644]
include/drivers/arm/gpio.h [new file with mode: 0644]
include/drivers/arm/pl011.h [new file with mode: 0644]
include/drivers/arm/tzc400.h [new file with mode: 0644]
include/drivers/console.h [new file with mode: 0644]
include/drivers/fastboot.h [new file with mode: 0644]
include/drivers/io/io_block.h [new file with mode: 0644]
include/drivers/io/io_driver.h [new file with mode: 0644]
include/drivers/io/io_fip.h [new file with mode: 0644]
include/drivers/io/io_memmap.h [new file with mode: 0644]
include/drivers/io/io_semihosting.h [new file with mode: 0644]
include/drivers/io/io_storage.h [new file with mode: 0644]
include/lib/aarch64/arch.h [new file with mode: 0644]
include/lib/aarch64/arch_helpers.h [new file with mode: 0644]
include/lib/aarch64/xlat_tables.h [new file with mode: 0644]
include/lib/bakery_lock.h [new file with mode: 0644]
include/lib/cassert.h [new file with mode: 0644]
include/lib/cpus/aarch64/aem_generic.h [new file with mode: 0644]
include/lib/cpus/aarch64/cortex_a53.h [new file with mode: 0644]
include/lib/cpus/aarch64/cortex_a57.h [new file with mode: 0644]
include/lib/cpus/aarch64/cpu_macros.S [new file with mode: 0644]
include/lib/mmio.h [new file with mode: 0644]
include/lib/semihosting.h [new file with mode: 0644]
include/lib/spinlock.h [new file with mode: 0644]
include/lib/utils.h [new file with mode: 0644]
include/plat/common/plat_config.h [new file with mode: 0644]
include/plat/common/platform.h [new file with mode: 0644]
include/stdlib/assert.h [new file with mode: 0644]
include/stdlib/inttypes.h [new file with mode: 0644]
include/stdlib/machine/_inttypes.h [new file with mode: 0644]
include/stdlib/machine/_limits.h [new file with mode: 0644]
include/stdlib/machine/_stdint.h [new file with mode: 0644]
include/stdlib/machine/_types.h [new file with mode: 0644]
include/stdlib/stddef.h [new file with mode: 0644]
include/stdlib/stdio.h [new file with mode: 0644]
include/stdlib/stdlib.h [new file with mode: 0644]
include/stdlib/string.h [new file with mode: 0644]
include/stdlib/strings.h [new file with mode: 0644]
include/stdlib/sys/_null.h [new file with mode: 0644]
include/stdlib/sys/_stdint.h [new file with mode: 0644]
include/stdlib/sys/_timespec.h [new file with mode: 0644]
include/stdlib/sys/_types.h [new file with mode: 0644]
include/stdlib/sys/cdefs.h [new file with mode: 0644]
include/stdlib/sys/ctype.h [new file with mode: 0644]
include/stdlib/sys/errno.h [new file with mode: 0644]
include/stdlib/sys/limits.h [new file with mode: 0644]
include/stdlib/sys/stdarg.h [new file with mode: 0644]
include/stdlib/sys/stdint.h [new file with mode: 0644]
include/stdlib/sys/timespec.h [new file with mode: 0644]
include/stdlib/sys/types.h [new file with mode: 0644]
include/stdlib/sys/uuid.h [new file with mode: 0644]
include/stdlib/time.h [new file with mode: 0644]
include/stdlib/xlocale/_strings.h [new file with mode: 0644]
include/stdlib/xlocale/_time.h [new file with mode: 0644]
lib/aarch64/cache_helpers.S [new file with mode: 0644]
lib/aarch64/misc_helpers.S [new file with mode: 0644]
lib/aarch64/xlat_helpers.c [new file with mode: 0644]
lib/aarch64/xlat_tables.c [new file with mode: 0644]
lib/cpus/aarch64/aem_generic.S [new file with mode: 0644]
lib/cpus/aarch64/cortex_a53.S [new file with mode: 0644]
lib/cpus/aarch64/cortex_a57.S [new file with mode: 0644]
lib/cpus/aarch64/cpu_helpers.S [new file with mode: 0644]
lib/cpus/cpu-ops.mk [new file with mode: 0644]
lib/locks/bakery/bakery_lock_coherent.c [new file with mode: 0644]
lib/locks/bakery/bakery_lock_normal.c [new file with mode: 0644]
lib/locks/exclusive/spinlock.S [new file with mode: 0644]
lib/semihosting/aarch64/semihosting_call.S [new file with mode: 0644]
lib/semihosting/semihosting.c [new file with mode: 0644]
lib/stdlib/abort.c [new file with mode: 0644]
lib/stdlib/assert.c [new file with mode: 0644]
lib/stdlib/exit.c [new file with mode: 0644]
lib/stdlib/mem.c [new file with mode: 0644]
lib/stdlib/printf.c [new file with mode: 0644]
lib/stdlib/putchar.c [new file with mode: 0644]
lib/stdlib/puts.c [new file with mode: 0644]
lib/stdlib/sscanf.c [new file with mode: 0644]
lib/stdlib/std.c [new file with mode: 0644]
lib/stdlib/strchr.c [new file with mode: 0644]
lib/stdlib/strcmp.c [new file with mode: 0644]
lib/stdlib/strlen.c [new file with mode: 0644]
lib/stdlib/strncmp.c [new file with mode: 0644]
lib/stdlib/subr_prf.c [new file with mode: 0644]
license.md [new file with mode: 0644]
plat/common/aarch64/plat_common.c [new file with mode: 0644]
plat/common/aarch64/platform_helpers.S [new file with mode: 0644]
plat/common/aarch64/platform_mp_stack.S [new file with mode: 0644]
plat/common/aarch64/platform_up_stack.S [new file with mode: 0644]
plat/common/plat_gic.c [new file with mode: 0644]
plat/fvp/aarch64/fvp_common.c [new file with mode: 0644]
plat/fvp/aarch64/fvp_helpers.S [new file with mode: 0644]
plat/fvp/bl1_fvp_setup.c [new file with mode: 0644]
plat/fvp/bl2_fvp_setup.c [new file with mode: 0644]
plat/fvp/bl31_fvp_setup.c [new file with mode: 0644]
plat/fvp/drivers/pwrc/fvp_pwrc.c [new file with mode: 0644]
plat/fvp/drivers/pwrc/fvp_pwrc.h [new file with mode: 0644]
plat/fvp/fvp_def.h [new file with mode: 0644]
plat/fvp/fvp_io_storage.c [new file with mode: 0644]
plat/fvp/fvp_pm.c [new file with mode: 0644]
plat/fvp/fvp_private.h [new file with mode: 0644]
plat/fvp/fvp_security.c [new file with mode: 0644]
plat/fvp/fvp_topology.c [new file with mode: 0644]
plat/fvp/fvp_trusted_boot.c [new file with mode: 0644]
plat/fvp/include/plat_macros.S [new file with mode: 0644]
plat/fvp/include/platform_def.h [new file with mode: 0644]
plat/fvp/include/platform_oid.h [new file with mode: 0644]
plat/fvp/platform.mk [new file with mode: 0644]
plat/fvp/tsp/tsp-fvp.mk [new file with mode: 0644]
plat/fvp/tsp/tsp_fvp_setup.c [new file with mode: 0644]
plat/hikey/aarch64/bl1_plat_helpers.S [new file with mode: 0644]
plat/hikey/aarch64/hikey_common.c [new file with mode: 0644]
plat/hikey/aarch64/plat_helpers.S [new file with mode: 0644]
plat/hikey/bl1_plat_setup.c [new file with mode: 0644]
plat/hikey/bl2_plat_setup.c [new file with mode: 0644]
plat/hikey/bl31_plat_setup.c [new file with mode: 0644]
plat/hikey/drivers/dw_mmc.c [new file with mode: 0644]
plat/hikey/drivers/hi6553.c [new file with mode: 0644]
plat/hikey/drivers/hisi_dvfs.c [new file with mode: 0644]
plat/hikey/drivers/hisi_ipc.c [new file with mode: 0644]
plat/hikey/drivers/hisi_mcu.c [new file with mode: 0644]
plat/hikey/drivers/hisi_pwrc.c [new file with mode: 0644]
plat/hikey/drivers/hisi_pwrc_sram.S [new file with mode: 0644]
plat/hikey/drivers/sp804_timer.c [new file with mode: 0644]
plat/hikey/hikey_def.h [new file with mode: 0644]
plat/hikey/hikey_private.h [new file with mode: 0644]
plat/hikey/include/dw_mmc.h [new file with mode: 0644]
plat/hikey/include/hi6220.h [new file with mode: 0644]
plat/hikey/include/hi6220_regs_acpu.h [new file with mode: 0644]
plat/hikey/include/hi6220_regs_ao.h [new file with mode: 0644]
plat/hikey/include/hi6220_regs_peri.h [new file with mode: 0644]
plat/hikey/include/hi6220_regs_pmctrl.h [new file with mode: 0644]
plat/hikey/include/hi6553.h [new file with mode: 0644]
plat/hikey/include/hisi_ipc.h [new file with mode: 0644]
plat/hikey/include/hisi_mcu.h [new file with mode: 0644]
plat/hikey/include/hisi_pwrc.h [new file with mode: 0644]
plat/hikey/include/hisi_sram_map.h [new file with mode: 0644]
plat/hikey/include/partitions.h [new file with mode: 0644]
plat/hikey/include/plat_macros.S [new file with mode: 0644]
plat/hikey/include/platform_def.h [new file with mode: 0644]
plat/hikey/include/sp804_timer.h [new file with mode: 0644]
plat/hikey/include/usb.h [new file with mode: 0644]
plat/hikey/partitions.c [new file with mode: 0644]
plat/hikey/plat_io_storage.c [new file with mode: 0644]
plat/hikey/plat_pm.c [new file with mode: 0644]
plat/hikey/plat_security.c [new file with mode: 0644]
plat/hikey/plat_topology.c [new file with mode: 0644]
plat/hikey/platform.mk [new file with mode: 0644]
plat/hikey/pll.c [new file with mode: 0644]
plat/hikey/usb.c [new file with mode: 0644]
plat/juno/aarch64/bl1_plat_helpers.S [new file with mode: 0644]
plat/juno/aarch64/juno_common.c [new file with mode: 0644]
plat/juno/aarch64/plat_helpers.S [new file with mode: 0644]
plat/juno/bl1_plat_setup.c [new file with mode: 0644]
plat/juno/bl2_plat_setup.c [new file with mode: 0644]
plat/juno/bl31_plat_setup.c [new file with mode: 0644]
plat/juno/include/plat_macros.S [new file with mode: 0644]
plat/juno/include/platform_def.h [new file with mode: 0644]
plat/juno/include/platform_oid.h [new file with mode: 0644]
plat/juno/juno_def.h [new file with mode: 0644]
plat/juno/juno_private.h [new file with mode: 0644]
plat/juno/juno_trusted_boot.c [new file with mode: 0644]
plat/juno/mhu.c [new file with mode: 0644]
plat/juno/mhu.h [new file with mode: 0644]
plat/juno/plat-tsp.ld.S [new file with mode: 0644]
plat/juno/plat_io_storage.c [new file with mode: 0644]
plat/juno/plat_pm.c [new file with mode: 0644]
plat/juno/plat_security.c [new file with mode: 0644]
plat/juno/plat_topology.c [new file with mode: 0644]
plat/juno/platform.mk [new file with mode: 0644]
plat/juno/scp_bootloader.c [new file with mode: 0644]
plat/juno/scp_bootloader.h [new file with mode: 0644]
plat/juno/scpi.c [new file with mode: 0644]
plat/juno/scpi.h [new file with mode: 0644]
plat/juno/tsp/tsp-juno.mk [new file with mode: 0644]
plat/juno/tsp/tsp_plat_setup.c [new file with mode: 0644]
plat/rpi3/aarch64/plat_helpers.S [new file with mode: 0644]
plat/rpi3/aarch64/rpi3_common.c [new file with mode: 0644]
plat/rpi3/bl31_plat_setup.c [new file with mode: 0644]
plat/rpi3/console.c [new file with mode: 0644]
plat/rpi3/include/plat_macros.S [new file with mode: 0644]
plat/rpi3/include/platform_def.h [new file with mode: 0644]
plat/rpi3/plat_pm.c [new file with mode: 0644]
plat/rpi3/plat_topology.c [new file with mode: 0644]
plat/rpi3/platform.mk [new file with mode: 0644]
plat/rpi3/rpi3_def.h [new file with mode: 0644]
plat/rpi3/rpi3_private.h [new file with mode: 0644]
readme.md [new file with mode: 0644]
services/spd/opteed/opteed.mk [new file with mode: 0644]
services/spd/opteed/opteed_common.c [new file with mode: 0644]
services/spd/opteed/opteed_helpers.S [new file with mode: 0644]
services/spd/opteed/opteed_main.c [new file with mode: 0644]
services/spd/opteed/opteed_pm.c [new file with mode: 0644]
services/spd/opteed/opteed_private.h [new file with mode: 0644]
services/spd/opteed/teesmc_opteed.h [new file with mode: 0644]
services/spd/opteed/teesmc_opteed_macros.h [new file with mode: 0644]
services/spd/tspd/tspd.mk [new file with mode: 0644]
services/spd/tspd/tspd_common.c [new file with mode: 0644]
services/spd/tspd/tspd_helpers.S [new file with mode: 0644]
services/spd/tspd/tspd_main.c [new file with mode: 0644]
services/spd/tspd/tspd_pm.c [new file with mode: 0644]
services/spd/tspd/tspd_private.h [new file with mode: 0644]
services/std_svc/psci/psci_afflvl_off.c [new file with mode: 0644]
services/std_svc/psci/psci_afflvl_on.c [new file with mode: 0644]
services/std_svc/psci/psci_afflvl_suspend.c [new file with mode: 0644]
services/std_svc/psci/psci_common.c [new file with mode: 0644]
services/std_svc/psci/psci_entry.S [new file with mode: 0644]
services/std_svc/psci/psci_helpers.S [new file with mode: 0644]
services/std_svc/psci/psci_main.c [new file with mode: 0644]
services/std_svc/psci/psci_private.h [new file with mode: 0644]
services/std_svc/psci/psci_setup.c [new file with mode: 0644]
services/std_svc/psci/psci_system_off.c [new file with mode: 0644]
services/std_svc/std_svc_setup.c [new file with mode: 0644]
tools/cert_create/Makefile [new file with mode: 0644]
tools/cert_create/include/cert.h [new file with mode: 0644]
tools/cert_create/include/debug.h [new file with mode: 0644]
tools/cert_create/include/ext.h [new file with mode: 0644]
tools/cert_create/include/key.h [new file with mode: 0644]
tools/cert_create/include/sha.h [new file with mode: 0644]
tools/cert_create/include/tbb_cert.h [new file with mode: 0644]
tools/cert_create/include/tbb_ext.h [new file with mode: 0644]
tools/cert_create/include/tbb_key.h [new file with mode: 0644]
tools/cert_create/src/cert.c [new file with mode: 0644]
tools/cert_create/src/ext.c [new file with mode: 0644]
tools/cert_create/src/key.c [new file with mode: 0644]
tools/cert_create/src/main.c [new file with mode: 0644]
tools/cert_create/src/sha.c [new file with mode: 0644]
tools/cert_create/src/tbb_cert.c [new file with mode: 0644]
tools/cert_create/src/tbb_ext.c [new file with mode: 0644]
tools/cert_create/src/tbb_key.c [new file with mode: 0644]
tools/fip_create/Makefile [new file with mode: 0644]
tools/fip_create/fip_create.c [new file with mode: 0644]
tools/fip_create/fip_create.h [new file with mode: 0644]
tools/fip_create/firmware_image_package.h [new symlink]
tools/fip_create/uuid.h [new symlink]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..6fb10b7
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,649 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+#
+# Trusted Firmware Version
+#
+VERSION_MAJOR          := 1
+VERSION_MINOR          := 1
+
+#
+# Default values for build configurations
+#
+
+# Build verbosity
+V                      := 0
+# Debug build
+DEBUG                  := 0
+# Build architecture
+ARCH                   := aarch64
+# Build platform
+DEFAULT_PLAT           := fvp
+PLAT                   := ${DEFAULT_PLAT}
+# SPD choice
+SPD                    := none
+# Base commit to perform code check on
+BASE_COMMIT            := origin/master
+# NS timer register save and restore
+NS_TIMER_SWITCH                := 0
+# By default, Bl1 acts as the reset handler, not BL31
+RESET_TO_BL31          := 0
+# Include FP registers in cpu context
+CTX_INCLUDE_FPREGS             := 0
+# Determine the version of ARM GIC architecture to use for interrupt management
+# in EL3. The platform port can change this value if needed.
+ARM_GIC_ARCH           :=      2
+# Flag used to indicate if ASM_ASSERTION should be enabled for the build.
+# This defaults to being present in DEBUG builds only.
+ASM_ASSERTION          :=      ${DEBUG}
+# Build option to choose whether Trusted firmware uses Coherent memory or not.
+USE_COHERENT_MEM       :=      1
+# Default FIP file name
+FIP_NAME               := fip.bin
+# By default, use the -pedantic option in the gcc command line
+DISABLE_PEDANTIC       := 0
+# Flags to generate the Chain of Trust
+GENERATE_COT           := 0
+CREATE_KEYS            := 1
+# Flags to build TF with Trusted Boot support
+TRUSTED_BOARD_BOOT     := 0
+AUTH_MOD               := none
+
+# Checkpatch ignores
+CHECK_IGNORE           =       --ignore COMPLEX_MACRO
+
+CHECKPATCH_ARGS                =       --no-tree --no-signoff ${CHECK_IGNORE}
+CHECKCODE_ARGS         =       --no-patch --no-tree --no-signoff ${CHECK_IGNORE}
+
+ifeq (${V},0)
+       Q=@
+       CHECKCODE_ARGS  +=      --no-summary --terse
+else
+       Q=
+endif
+export Q
+
+ifneq (${DEBUG}, 0)
+       BUILD_TYPE      :=      debug
+       # 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 log -n 1 --pretty=format:"%h")
+endif
+
+VERSION_STRING         :=      v${VERSION_MAJOR}.${VERSION_MINOR}(${BUILD_TYPE}):${BUILD_STRING}
+
+BL_COMMON_SOURCES      :=      common/bl_common.c                      \
+                               common/tf_printf.c                      \
+                               common/aarch64/debug.S                  \
+                               lib/aarch64/cache_helpers.S             \
+                               lib/aarch64/misc_helpers.S              \
+                               lib/aarch64/xlat_helpers.c              \
+                               lib/stdlib/std.c                        \
+                               plat/common/aarch64/platform_helpers.S
+
+BUILD_BASE             :=      ./build
+BUILD_PLAT             :=      ${BUILD_BASE}/${PLAT}/${BUILD_TYPE}
+
+PLATFORMS              :=      $(shell ls -I common plat/)
+SPDS                   :=      $(shell ls -I none services/spd)
+HELP_PLATFORMS         :=      $(shell echo ${PLATFORMS} | sed 's/ /|/g')
+
+# Convenience function for adding build definitions
+# $(eval $(call add_define,FOO)) will have:
+# -DFOO if $(FOO) is empty; -DFOO=$(FOO) otherwise
+define add_define
+DEFINES                        +=      -D$(1)$(if $(value $(1)),=$(value $(1)),)
+endef
+
+# Convenience function for verifying option has a boolean value
+# $(eval $(call assert_boolean,FOO)) will assert FOO is 0 or 1
+define assert_boolean
+$(and $(patsubst 0,,$(value $(1))),$(patsubst 1,,$(value $(1))),$(error $(1) must be boolean))
+endef
+
+ifeq (${PLAT},)
+  $(error "Error: Unknown platform. Please use PLAT=<platform name> to specify the platform.")
+endif
+ifeq ($(findstring ${PLAT},${PLATFORMS}),)
+  $(error "Error: Invalid platform. The following platforms are available: ${PLATFORMS}")
+endif
+
+all: msg_start
+
+msg_start:
+       @echo "Building ${PLAT}"
+
+include plat/${PLAT}/platform.mk
+
+# Include the CPU specific operations makefile. By default all CPU errata
+# workarounds and CPU specifc optimisations are disabled. This can be
+# overridden by the platform.
+include lib/cpus/cpu-ops.mk
+
+ifdef BL1_SOURCES
+NEED_BL1 := yes
+include bl1/bl1.mk
+endif
+
+ifdef BL2_SOURCES
+NEED_BL2 := yes
+include bl2/bl2.mk
+# Using the ARM Trusted Firmware BL2 implies that a BL3-3 image also need to be supplied for the FIP.
+# This flag can be overridden by the platform.
+NEED_BL33 ?= yes
+endif
+
+ifdef BL31_SOURCES
+NEED_BL31 := yes
+include bl31/bl31.mk
+endif
+
+# Include SPD Makefile if one has been specified
+ifneq (${SPD},none)
+  # We expect to locate an spd.mk under the specified SPD directory
+  SPD_MAKE             :=      $(shell m="services/spd/${SPD}/${SPD}.mk"; [ -f "$$m" ] && echo "$$m")
+
+  ifeq (${SPD_MAKE},)
+    $(error Error: No services/spd/${SPD}/${SPD}.mk located)
+  endif
+  $(info Including ${SPD_MAKE})
+  include ${SPD_MAKE}
+
+  # If there's BL3-2 companion for the chosen SPD, and the SPD wants to build the
+  # BL3-2 from source, we expect that the SPD's Makefile would set NEED_BL32
+  # variable to "yes". In case the BL3-2 is a binary which needs to be included in
+  # fip, then the NEED_BL32 needs to be set and BL3-2 would need to point to the bin.
+endif
+
+.PHONY:                        all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip certtool
+.SUFFIXES:
+
+INCLUDES               +=      -Iinclude/bl31                  \
+                               -Iinclude/bl31/services         \
+                               -Iinclude/common                \
+                               -Iinclude/drivers               \
+                               -Iinclude/drivers/arm           \
+                               -Iinclude/drivers/io            \
+                               -Iinclude/lib                   \
+                               -Iinclude/lib/aarch64           \
+                               -Iinclude/lib/cpus/aarch64      \
+                               -Iinclude/plat/common           \
+                               -Iinclude/stdlib                \
+                               -Iinclude/stdlib/sys            \
+                               ${PLAT_INCLUDES}                \
+                               ${SPD_INCLUDES}
+
+# Process DEBUG flag
+$(eval $(call assert_boolean,DEBUG))
+$(eval $(call add_define,DEBUG))
+ifeq (${DEBUG},0)
+  $(eval $(call add_define,NDEBUG))
+else
+CFLAGS                 +=      -g
+ASFLAGS                        +=      -g -Wa,--gdwarf-2
+endif
+
+# Process NS_TIMER_SWITCH flag
+$(eval $(call assert_boolean,NS_TIMER_SWITCH))
+$(eval $(call add_define,NS_TIMER_SWITCH))
+
+# Process RESET_TO_BL31 flag
+$(eval $(call assert_boolean,RESET_TO_BL31))
+$(eval $(call add_define,RESET_TO_BL31))
+
+# Process CTX_INCLUDE_FPREGS flag
+$(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
+$(eval $(call add_define,CTX_INCLUDE_FPREGS))
+
+# Process ARM_GIC_ARCH flag
+$(eval $(call add_define,ARM_GIC_ARCH))
+
+# Process ASM_ASSERTION flag
+$(eval $(call assert_boolean,ASM_ASSERTION))
+$(eval $(call add_define,ASM_ASSERTION))
+
+# Process LOG_LEVEL flag
+$(eval $(call add_define,LOG_LEVEL))
+
+# Process USE_COHERENT_MEM flag
+$(eval $(call assert_boolean,USE_COHERENT_MEM))
+$(eval $(call add_define,USE_COHERENT_MEM))
+
+# Process Generate CoT flags
+$(eval $(call assert_boolean,GENERATE_COT))
+$(eval $(call assert_boolean,CREATE_KEYS))
+
+# Process TRUSTED_BOARD_BOOT flag
+$(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
+$(eval $(call add_define,TRUSTED_BOARD_BOOT))
+
+ASFLAGS                        +=      -nostdinc -ffreestanding -Wa,--fatal-warnings   \
+                               -Werror -Wmissing-include-dirs                  \
+                               -mgeneral-regs-only -D__ASSEMBLY__              \
+                               ${DEFINES} ${INCLUDES}
+CFLAGS                 +=      -nostdinc -ffreestanding -Wall                  \
+                               -Werror -Wmissing-include-dirs                  \
+                               -mgeneral-regs-only -mstrict-align              \
+                               -std=c99 -c -Os ${DEFINES} ${INCLUDES} -fno-pic
+CFLAGS                 +=      -ffunction-sections -fdata-sections             \
+                               -fno-delete-null-pointer-checks
+
+LDFLAGS                        +=      --fatal-warnings -O1
+LDFLAGS                        +=      --gc-sections
+
+
+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 ${CFLAGS}
+
+# Variables for use with Firmware Image Package
+FIPTOOLPATH            ?=      tools/fip_create
+FIPTOOL                        ?=      ${FIPTOOLPATH}/fip_create
+fiptool:               ${FIPTOOL}
+fip:                   ${BUILD_PLAT}/${FIP_NAME}
+
+# Variables for use with Certificate Generation Tool
+CRTTOOLPATH            ?=      tools/cert_create
+CRTTOOL                        ?=      ${CRTTOOLPATH}/cert_create
+certtool:              ${CRTTOOL}
+
+# CoT generation tool default parameters
+TRUSTED_KEY_CERT       :=      ${BUILD_PLAT}/trusted_key.crt
+
+# Pass the private keys to the CoT generation tool in the command line
+# If CREATE_KEYS is set, the '-n' option will be added, indicating the tool to create new keys
+ifneq (${GENERATE_COT},0)
+    $(eval CERTS := yes)
+
+    $(eval FIP_DEPS += certificates)
+    $(eval FIP_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT})
+
+    ifneq (${CREATE_KEYS},0)
+        $(eval CRT_ARGS += -n)
+    endif
+    $(eval CRT_ARGS += $(if ${ROT_KEY}, --rot-key ${ROT_KEY}))
+    $(eval CRT_ARGS += $(if ${TRUSTED_WORLD_KEY}, --trusted-world-key ${TRUSTED_WORLD_KEY}))
+    $(eval CRT_ARGS += $(if ${NON_TRUSTED_WORLD_KEY}, --non-trusted-world-key ${NON_TRUSTED_WORLD_KEY}))
+    $(eval CRT_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT})
+endif
+
+# Check Trusted Board Boot options
+ifneq (${TRUSTED_BOARD_BOOT},0)
+    ifeq (${AUTH_MOD},none)
+        $(error Error: When TRUSTED_BOARD_BOOT=1, AUTH_MOD has to be the name of a valid authentication module)
+    else
+        # We expect to locate an *.mk file under the specified AUTH_MOD directory
+        AUTH_MAKE := $(shell m="common/auth/${AUTH_MOD}/${AUTH_MOD}.mk"; [ -f "$$m" ] && echo "$$m")
+        ifeq (${AUTH_MAKE},)
+            $(error Error: No common/auth/${AUTH_MOD}/${AUTH_MOD}.mk located)
+        endif
+        $(info Including ${AUTH_MAKE})
+        include ${AUTH_MAKE}
+    endif
+
+    BL_COMMON_SOURCES  +=      common/auth.c
+endif
+
+# Check if -pedantic option should be used
+ifeq (${DISABLE_PEDANTIC},0)
+    CFLAGS             +=      -pedantic
+endif
+
+locate-checkpatch:
+ifndef CHECKPATCH
+       $(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/script/checkpatch.pl")
+else
+ifeq (,$(wildcard ${CHECKPATCH}))
+       $(error "The file CHECKPATCH points to cannot be found, use eg: CHECKPATCH=../linux/script/checkpatch.pl")
+endif
+endif
+
+clean:
+                       @echo "  CLEAN"
+                       ${Q}rm -rf ${BUILD_PLAT}
+                       ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
+                       ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
+
+realclean distclean:
+                       @echo "  REALCLEAN"
+                       ${Q}rm -rf ${BUILD_BASE}
+                       ${Q}rm -f ${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 -v stdlib | while read GIT_FILE ; do ${CHECKPATCH} ${CHECKCODE_ARGS} -f $$GIT_FILE ; done ; \
+                        else                   \
+                                find . -type f -not -iwholename "*.git*" -not -iwholename "*build*" -not -iwholename "*stdlib*" -exec ${CHECKPATCH} ${CHECKCODE_ARGS} -f {} \; ;       \
+                        fi
+
+checkpatch:            locate-checkpatch
+                       @echo "  CHECKING STYLE"
+                       @git format-patch --stdout ${BASE_COMMIT} | ${CHECKPATCH} ${CHECKPATCH_ARGS} - || true
+
+.PHONY: ${CRTTOOL}
+${CRTTOOL}:
+                       ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH}
+                       @echo
+                       @echo "Built $@ successfully"
+                       @echo
+
+.PHONY: ${FIPTOOL}
+${FIPTOOL}:
+                       ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH}
+
+define match_goals
+$(strip $(foreach goal,$(1),$(filter $(goal),$(MAKECMDGOALS))))
+endef
+
+# List of rules that involve building things
+BUILD_TARGETS := all bl1 bl2 bl31 bl32 fip
+
+# Does the list of goals specified on the command line include a build target?
+ifneq ($(call match_goals,${BUILD_TARGETS}),)
+IS_ANYTHING_TO_BUILD := 1
+endif
+
+define MAKE_C
+
+$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2))))
+$(eval PREREQUISITES := $(patsubst %.o,%.d,$(OBJ)))
+
+$(OBJ) : $(2)
+       @echo "  CC      $$<"
+       $$(Q)$$(CC) $$(CFLAGS) -DIMAGE_BL$(3) -c $$< -o $$@
+
+
+$(PREREQUISITES) : $(2)
+       @echo "  DEPS    $$@"
+       @mkdir -p $(1)
+       $$(Q)$$(CC) $$(CFLAGS) -M -MT $(OBJ) -MF $$@ $$<
+
+ifdef IS_ANYTHING_TO_BUILD
+-include $(PREREQUISITES)
+endif
+
+endef
+
+
+define MAKE_S
+
+$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
+$(eval PREREQUISITES := $(patsubst %.o,%.d,$(OBJ)))
+
+$(OBJ) : $(2)
+       @echo "  AS      $$<"
+       $$(Q)$$(AS) $$(ASFLAGS) -DIMAGE_BL$(3) -c $$< -o $$@
+
+$(PREREQUISITES) : $(2)
+       @echo "  DEPS    $$@"
+       @mkdir -p $(1)
+       $$(Q)$$(AS) $$(ASFLAGS) -M -MT $(OBJ) -MF $$@ $$<
+
+ifdef IS_ANYTHING_TO_BUILD
+-include $(PREREQUISITES)
+endif
+
+endef
+
+
+define MAKE_LD
+
+$(eval PREREQUISITES := $(1).d)
+
+$(1) : $(2)
+       @echo "  PP      $$<"
+       $$(Q)$$(AS) $$(ASFLAGS) -P -E -D__LINKER__ -o $$@ $$<
+
+$(PREREQUISITES) : $(2)
+       @echo "  DEPS    $$@"
+       @mkdir -p $$(dir $$@)
+       $$(Q)$$(AS) $$(ASFLAGS) -M -MT $(1) -MF $$@ $$<
+
+ifdef IS_ANYTHING_TO_BUILD
+-include $(PREREQUISITES)
+endif
+
+endef
+
+
+define MAKE_OBJS
+       $(eval C_OBJS := $(filter %.c,$(2)))
+       $(eval REMAIN := $(filter-out %.c,$(2)))
+       $(eval $(foreach obj,$(C_OBJS),$(call MAKE_C,$(1),$(obj),$(3))))
+
+       $(eval S_OBJS := $(filter %.S,$(REMAIN)))
+       $(eval REMAIN := $(filter-out %.S,$(REMAIN)))
+       $(eval $(foreach obj,$(S_OBJS),$(call MAKE_S,$(1),$(obj),$(3))))
+
+       $(and $(REMAIN),$(error Unexpected source files present: $(REMAIN)))
+endef
+
+
+# NOTE: The line continuation '\' is required in the next define otherwise we
+# end up with a line-feed characer at the end of the last c filename.
+# Also bare this issue in mind if extending the list of supported filetypes.
+define SOURCES_TO_OBJS
+       $(notdir $(patsubst %.c,%.o,$(filter %.c,$(1)))) \
+       $(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
+endef
+
+
+# MAKE_TOOL_ARGS macro defines the command line arguments for the FIP and CRT
+# tools at each BL stage. Arguments:
+#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(2) = Binary file
+#   $(3) = In FIP (false if empty)
+#   $(4) = Create certificates (false if empty)
+#   $(5) = Create key certificate (false if empty)
+#   $(6) = Private key (optional)
+define MAKE_TOOL_ARGS
+
+$(eval FIP_DEPS += $(if $3,$(2),))
+$(eval FIP_ARGS += $(if $3,--bl$(1) $(2),))
+$(eval FIP_ARGS += $(if $4,--bl$(1)-cert $(BUILD_PLAT)/bl$(1).crt))
+$(eval FIP_ARGS += $(if $4,$(if $5,--bl$(1)-key-cert $(BUILD_PLAT)/bl$(1)_key.crt)))
+
+$(eval CRT_DEPS += $(if $4,$(2),))
+$(eval CRT_DEPS += $(if $4,$(if $6,$(6),)))
+$(eval CRT_ARGS += $(if $4,--bl$(1) $(2)))
+$(eval CRT_ARGS += $(if $4,$(if $6,--bl$(1)-key $(6))))
+$(eval CRT_ARGS += $(if $4,--bl$(1)-cert $(BUILD_PLAT)/bl$(1).crt))
+$(eval CRT_ARGS += $(if $4,$(if $5,--bl$(1)-key-cert $(BUILD_PLAT)/bl$(1)_key.crt)))
+
+endef
+
+
+# MAKE_BL macro defines the targets and options to build each BL image.
+# Arguments:
+#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(2) = In FIP (false if empty)
+#   $(3) = Create certificates (false if empty)
+#   $(4) = Create key certificate (false if empty)
+#   $(5) = Private key (optional)
+define MAKE_BL
+       $(eval BUILD_DIR  := ${BUILD_PLAT}/bl$(1))
+       $(eval SOURCES    := $(BL$(1)_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES))
+       $(eval OBJS       := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
+       $(eval LINKERFILE := $(BUILD_DIR)/bl$(1).ld)
+       $(eval MAPFILE    := $(BUILD_DIR)/bl$(1).map)
+       $(eval ELF        := $(BUILD_DIR)/bl$(1).elf)
+       $(eval DUMP       := $(BUILD_DIR)/bl$(1).dump)
+       $(eval BIN        := $(BUILD_PLAT)/bl$(1).bin)
+
+       $(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
+       $(eval $(call MAKE_LD,$(LINKERFILE),$(BL$(1)_LINKERFILE)))
+
+$(BUILD_DIR) :
+       $$(Q)mkdir -p "$$@"
+
+$(ELF) : $(OBJS) $(LINKERFILE)
+       @echo "  LD      $$@"
+       @echo 'const char build_message[] = "Built : "__TIME__", "__DATE__; \
+              const char version_string[] = "${VERSION_STRING}";' | \
+               $$(CC) $$(CFLAGS) -xc - -o $(BUILD_DIR)/build_message.o
+       $$(Q)$$(LD) -o $$@ $$(LDFLAGS) -Map=$(MAPFILE) --script $(LINKERFILE) \
+                                       $(BUILD_DIR)/build_message.o $(OBJS)
+
+$(DUMP) : $(ELF)
+       @echo "  OD      $$@"
+       $${Q}$${OD} -dx $$< > $$@
+
+$(BIN) : $(ELF)
+       @echo "  BIN     $$@"
+       $$(Q)$$(OC) -O binary $$< $$@
+       @echo
+       @echo "Built $$@ successfully"
+       @echo
+
+.PHONY : bl$(1)
+bl$(1) : $(BUILD_DIR) $(BIN) $(DUMP)
+
+all : bl$(1)
+
+$(eval $(call MAKE_TOOL_ARGS,$(1),$(BIN),$(2),$(3),$(4),$(5)))
+
+endef
+
+
+ifeq (${NEED_BL1},yes)
+$(eval $(call MAKE_BL,1))
+endif
+
+ifeq (${NEED_BL2},yes)
+$(if ${BL2}, $(eval $(call MAKE_TOOL_ARGS,2,${BL2},in_fip,${CERTS})),\
+       $(eval $(call MAKE_BL,2,in_fip,${CERTS})))
+endif
+
+ifeq (${NEED_BL31},yes)
+BL31_SOURCES += ${SPD_SOURCES}
+$(if ${BL31}, $(eval $(call MAKE_TOOL_ARGS,31,${BL31},in_fip,${CERTS},${CERTS},${BL31_KEY})),\
+       $(eval $(call MAKE_BL,31,in_fip,${CERTS},${CERTS},${BL31_KEY})))
+endif
+
+ifeq (${NEED_BL32},yes)
+$(if ${BL32}, $(eval $(call MAKE_TOOL_ARGS,32,${BL32},in_fip,${CERTS},${CERTS},${BL32_KEY})),\
+       $(eval $(call MAKE_BL,32,in_fip,${CERTS},${CERTS},${BL32_KEY})))
+endif
+
+ifeq (${NEED_BL30},yes)
+$(if ${BL30}, $(eval $(call MAKE_TOOL_ARGS,30,${BL30},in_fip,${CERTS},${CERTS},${BL30_KEY})))
+
+# If BL3-0 is needed by the platform then 'BL30' variable must be defined.
+check_bl30:
+       $(if ${BL30},,$(error "To build a FIP for platform ${PLAT}, please set BL30 to point to the SCP firmware"))
+else
+
+# If BL3-0 is not needed by the platform but the user still specified the path
+# to a BL3-0 image then warn him that it will be ignored.
+check_bl30:
+       $(if ${BL30},$(warning "BL3-0 is not supported on platform ${PLAT}, it will just be ignored"),)
+endif
+
+ifeq (${NEED_BL33},yes)
+$(if ${BL33}, $(eval $(call MAKE_TOOL_ARGS,33,${BL33},in_fip,${CERTS},${CERTS},${BL33_KEY})))
+
+# If BL3-3 is needed by the platform then 'BL33' variable must be defined.
+check_bl33:
+       $(if ${BL33},,$(error "To build a FIP, please set BL33 to point to the Normal World binary, eg: BL33=../uefi/FVP_AARCH64_EFI.fd"))
+else
+
+# If BL3-3 is not needed by the platform but the user still specified the path
+# to a BL3-3 image then warn him that it will be ignored.
+check_bl33:
+       $(if ${BL33},$(warning "BL3-3 is not supported on platform ${PLAT}, it will just be ignored"),)
+endif
+
+# Add the dependency on the certificates
+ifneq (${GENERATE_COT},0)
+    all: certificates
+endif
+
+certificates: ${CRT_DEPS} ${CRTTOOL} check_bl30 check_bl33
+                       ${Q}${CRTTOOL} ${CRT_ARGS}
+                       @echo
+                       @echo "Built $@ successfully"
+                       @echo "Certificates can be found in ${BUILD_PLAT}"
+                       @echo
+
+${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL} check_bl30 check_bl33
+                       ${Q}${FIPTOOL} --dump \
+                               ${FIP_ARGS} \
+                               $@
+                       @echo
+                       @echo "Built $@ successfully"
+                       @echo
+
+
+cscope:
+       @echo "  CSCOPE"
+       ${Q}find ${CURDIR} -name "*.[chsS]" > cscope.files
+       ${Q}cscope -b -q -k
+
+help:
+       @echo "usage: ${MAKE} PLAT=<${HELP_PLATFORMS}> <all|bl1|bl2|bl31|distclean|clean|checkcodebase|checkpatch>"
+       @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 "Supported Targets:"
+       @echo "  all            Build the BL1, BL2 and BL31 binaries"
+       @echo "  bl1            Build the BL1 binary"
+       @echo "  bl2            Build the BL2 binary"
+       @echo "  bl31           Build the BL31 binary"
+       @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 ""
+       @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"
diff --git a/acknowledgements.md b/acknowledgements.md
new file mode 100644 (file)
index 0000000..a428f2f
--- /dev/null
@@ -0,0 +1,9 @@
+Contributor Acknowledgements
+============================
+
+Companies
+---------
+Linaro Limited
+
+Individuals
+-----------
diff --git a/bl1/aarch64/bl1_arch_setup.c b/bl1/aarch64/bl1_arch_setup.c
new file mode 100644 (file)
index 0000000..6a3f062
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+
+/*******************************************************************************
+ * 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(SCR_RES1_BITS | 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);
+}
diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S
new file mode 100644 (file)
index 0000000..cfc6292
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+       .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
+       /* ---------------------------------------------
+        * Set the CPU endianness before doing anything
+        * that might involve memory reads or writes.
+        * ---------------------------------------------
+        */
+       mrs     x0, sctlr_el3
+       bic     x0, x0, #SCTLR_EE_BIT
+       msr     sctlr_el3, x0
+       isb
+
+       /* ---------------------------------------------
+        * Perform any processor specific actions upon
+        * reset e.g. cache, tlb invalidations etc.
+        * ---------------------------------------------
+        */
+       bl      reset_handler
+
+       /* ---------------------------------------------
+        * 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_el3
+       orr     x0, x0, x1
+       msr     sctlr_el3, x0
+       isb
+
+       /* ---------------------------------------------
+        * Set the exception vector to something sane.
+        * ---------------------------------------------
+        */
+       adr     x0, bl1_exceptions
+       msr     vbar_el3, x0
+       isb
+
+       /* ---------------------------------------------
+        * Enable the SError interrupt now that the
+        * exception vectors have been setup.
+        * ---------------------------------------------
+        */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       /* ---------------------------------------------------------------------
+        * The initial state of the Architectural feature trap register
+        * (CPTR_EL3) is unknown and it must be set to a known state. All
+        * feature traps are disabled. Some bits in this register are marked as
+        * Reserved and should not be modified.
+        *
+        * CPTR_EL3.TCPAC: This causes a direct access to the CPACR_EL1 from EL1
+        *  or the CPTR_EL2 from EL2 to trap to EL3 unless it is trapped at EL2.
+        * CPTR_EL3.TTA: This causes access to the Trace functionality to trap
+        *  to EL3 when executed from EL0, EL1, EL2, or EL3. If system register
+        *  access to trace functionality is not supported, this bit is RES0.
+        * CPTR_EL3.TFP: This causes instructions that access the registers
+        *  associated with Floating Point and Advanced SIMD execution to trap
+        *  to EL3 when executed from any exception level, unless trapped to EL1
+        *  or EL2.
+        * ---------------------------------------------------------------------
+        */
+       mrs     x0, cptr_el3
+       bic     w0, w0, #TCPAC_BIT
+       bic     w0, w0, #TTA_BIT
+       bic     w0, w0, #TFP_BIT
+       msr     cptr_el3, x0
+
+       /* -------------------------------------------------------
+        * Will not return from this macro if it is a warm boot.
+        * -------------------------------------------------------
+        */
+       wait_for_entrypoint
+
+       bl      platform_mem_init
+
+       /* ---------------------------------------------
+        * Init C runtime environment.
+        *   - Zero-initialise the NOBITS sections.
+        *     There are 2 of them:
+        *       - the .bss section;
+        *       - the coherent memory section.
+        *   - Copy the data section from BL1 image
+        *     (stored in ROM) to the correct location
+        *     in RAM.
+        * ---------------------------------------------
+        */
+       ldr     x0, =__BSS_START__
+       ldr     x1, =__BSS_SIZE__
+       bl      zeromem16
+
+#if USE_COHERENT_MEM
+       ldr     x0, =__COHERENT_RAM_START__
+       ldr     x1, =__COHERENT_RAM_UNALIGNED_SIZE__
+       bl      zeromem16
+#endif
+
+       ldr     x0, =__DATA_RAM_START__
+       ldr     x1, =__DATA_ROM_START__
+       ldr     x2, =__DATA_SIZE__
+       bl      memcpy16
+
+       /* --------------------------------------------
+        * 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.
+        * --------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_set_stack
+
+       /* ---------------------------------------------
+        * 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. Panic if it returns
+        * --------------------------------------------------
+        */
+       bl      bl1_main
+panic:
+       b       panic
diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S
new file mode 100644 (file)
index 0000000..1ca3a6c
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <runtime_svc.h>
+
+       .globl  bl1_exceptions
+
+       .section        .vectors, "ax"; .align 11
+
+       /* -----------------------------------------------------
+        * Very simple stackless exception handlers used by BL1.
+        * -----------------------------------------------------
+        */
+       .align  7
+bl1_exceptions:
+       /* -----------------------------------------------------
+        * Current EL with SP0 : 0x0 - 0x200
+        * -----------------------------------------------------
+        */
+SynchronousExceptionSP0:
+       mov     x0, #SYNC_EXCEPTION_SP_EL0
+       bl      plat_report_exception
+       b       SynchronousExceptionSP0
+       check_vector_size SynchronousExceptionSP0
+
+       .align  7
+IrqSP0:
+       mov     x0, #IRQ_SP_EL0
+       bl      plat_report_exception
+       b       IrqSP0
+       check_vector_size IrqSP0
+
+       .align  7
+FiqSP0:
+       mov     x0, #FIQ_SP_EL0
+       bl      plat_report_exception
+       b       FiqSP0
+       check_vector_size FiqSP0
+
+       .align  7
+SErrorSP0:
+       mov     x0, #SERROR_SP_EL0
+       bl      plat_report_exception
+       b       SErrorSP0
+       check_vector_size SErrorSP0
+
+       /* -----------------------------------------------------
+        * Current EL with SPx: 0x200 - 0x400
+        * -----------------------------------------------------
+        */
+       .align  7
+SynchronousExceptionSPx:
+       mov     x0, #SYNC_EXCEPTION_SP_ELX
+       bl      plat_report_exception
+       b       SynchronousExceptionSPx
+       check_vector_size SynchronousExceptionSPx
+
+       .align  7
+IrqSPx:
+       mov     x0, #IRQ_SP_ELX
+       bl      plat_report_exception
+       b       IrqSPx
+       check_vector_size IrqSPx
+
+       .align  7
+FiqSPx:
+       mov     x0, #FIQ_SP_ELX
+       bl      plat_report_exception
+       b       FiqSPx
+       check_vector_size FiqSPx
+
+       .align  7
+SErrorSPx:
+       mov     x0, #SERROR_SP_ELX
+       bl      plat_report_exception
+       b       SErrorSPx
+       check_vector_size SErrorSPx
+
+       /* -----------------------------------------------------
+        * Lower EL using AArch64 : 0x400 - 0x600
+        * -----------------------------------------------------
+        */
+       .align  7
+SynchronousExceptionA64:
+       /* Enable the SError interrupt */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       /* ------------------------------------------------
+        * Only a single SMC exception from BL2 to ask
+        * BL1 to pass EL3 control to BL31 is expected
+        * here.
+        * It expects X0 with RUN_IMAGE SMC function id
+        * X1 with address of a entry_point_info_t structure
+        * describing the BL3-1 entrypoint
+        * ------------------------------------------------
+        */
+       mov     x19, x0
+       mov     x20, x1
+
+       mrs     x0, esr_el3
+       ubfx    x1, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH
+       cmp     x1, #EC_AARCH64_SMC
+       b.ne    panic
+
+       mov     x0, #RUN_IMAGE
+       cmp     x19, x0
+       b.ne    panic
+
+       mov     x0, x20
+       bl      display_boot_progress
+
+       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    panic
+
+       bl      disable_mmu_icache_el3
+       tlbi    alle3
+
+       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
+panic:
+       mov     x0, #SYNC_EXCEPTION_AARCH64
+       bl      plat_report_exception
+
+       wfi
+       b       panic
+       check_vector_size SynchronousExceptionA64
+
+       .align  7
+IrqA64:
+       mov     x0, #IRQ_AARCH64
+       bl      plat_report_exception
+       b       IrqA64
+       check_vector_size IrqA64
+
+       .align  7
+FiqA64:
+       mov     x0, #FIQ_AARCH64
+       bl      plat_report_exception
+       b       FiqA64
+       check_vector_size FiqA64
+
+       .align  7
+SErrorA64:
+       mov     x0, #SERROR_AARCH64
+       bl      plat_report_exception
+       b       SErrorA64
+       check_vector_size SErrorA64
+
+       /* -----------------------------------------------------
+        * Lower EL using AArch32 : 0x600 - 0x800
+        * -----------------------------------------------------
+        */
+       .align  7
+SynchronousExceptionA32:
+       mov     x0, #SYNC_EXCEPTION_AARCH32
+       bl      plat_report_exception
+       b       SynchronousExceptionA32
+       check_vector_size SynchronousExceptionA32
+
+       .align  7
+IrqA32:
+       mov     x0, #IRQ_AARCH32
+       bl      plat_report_exception
+       b       IrqA32
+       check_vector_size IrqA32
+
+       .align  7
+FiqA32:
+       mov     x0, #FIQ_AARCH32
+       bl      plat_report_exception
+       b       FiqA32
+       check_vector_size FiqA32
+
+       .align  7
+SErrorA32:
+       mov     x0, #SERROR_AARCH32
+       bl      plat_report_exception
+       b       SErrorA32
+       check_vector_size SErrorA32
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
new file mode 100644 (file)
index 0000000..d682384
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.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(4096),
+           "BL1_RO_BASE address is not aligned on a page boundary.")
+
+    ro . : {
+        __RO_START__ = .;
+        *bl1_entrypoint.o(.text*)
+        *(.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__ = .;
+
+        *(.vectors)
+        __RO_END__ = .;
+    } >ROM
+
+    ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
+           "cpu_ops not defined for this platform.")
+
+    /*
+     * The .data section gets copied from ROM to RAM at runtime.
+     * Its LMA must be 16-byte aligned.
+     * Its VMA must be page-aligned as it marks the first read/write page.
+     */
+    . = BL1_RW_BASE;
+    ASSERT(. == ALIGN(4096),
+           "BL1_RW_BASE address is not aligned on a page boundary.")
+    .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 must be 16-byte aligned.
+     */
+    .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 and eliminates the unecessary zero init
+     */
+    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(4096) {
+        __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(4096);
+        __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 the read-only part of BL1's binary.
+     */
+    ASSERT(__DATA_ROM_START__ + __DATA_SIZE__ <= BL1_RO_LIMIT,
+           "BL1's RO section 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.")
+}
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
new file mode 100644 (file)
index 0000000..8e73bef
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+BL1_SOURCES            +=      bl1/bl1_main.c                          \
+                               bl1/aarch64/bl1_arch_setup.c            \
+                               bl1/aarch64/bl1_entrypoint.S            \
+                               bl1/aarch64/bl1_exceptions.S            \
+                               lib/cpus/aarch64/cpu_helpers.S
+
+BL1_LINKERFILE         :=      bl1/bl1.ld.S
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
new file mode 100644 (file)
index 0000000..491fd5c
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <auth.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include "bl1_private.h"
+
+/*******************************************************************************
+ * Runs BL2 from the given entry point. It results in dropping the
+ * exception level
+ ******************************************************************************/
+static void __dead2 bl1_run_bl2(entry_point_info_t *bl2_ep)
+{
+       bl1_arch_next_el_setup();
+
+       /* Tell next EL what we want done */
+       bl2_ep->args.arg0 = RUN_IMAGE;
+
+       if (GET_SECURITY_STATE(bl2_ep->h.attr) == NON_SECURE)
+               change_security_state(GET_SECURITY_STATE(bl2_ep->h.attr));
+
+       write_spsr_el3(bl2_ep->spsr);
+       write_elr_el3(bl2_ep->pc);
+
+       eret(bl2_ep->args.arg0,
+               bl2_ep->args.arg1,
+               bl2_ep->args.arg2,
+               bl2_ep->args.arg3,
+               bl2_ep->args.arg4,
+               bl2_ep->args.arg5,
+               bl2_ep->args.arg6,
+               bl2_ep->args.arg7);
+}
+
+/*******************************************************************************
+ * The next function 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)
+{
+       const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
+
+       assert(bl1_mem_layout != NULL);
+       assert(bl2_mem_layout != NULL);
+
+       /* Check that BL1's memory is lying outside of the free memory */
+       assert((BL1_RAM_LIMIT <= bl1_mem_layout->free_base) ||
+              (BL1_RAM_BASE >= bl1_mem_layout->free_base + bl1_mem_layout->free_size));
+
+       /* Remove BL1 RW data from the scope of memory visible to BL2 */
+       *bl2_mem_layout = *bl1_mem_layout;
+       reserve_mem(&bl2_mem_layout->total_base,
+                   &bl2_mem_layout->total_size,
+                   BL1_RAM_BASE,
+                   bl1_size);
+
+       flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t));
+}
+
+/*******************************************************************************
+ * Function to perform late architectural and platform specific initialization.
+ * It also locates and loads the BL2 raw binary image in the trusted DRAM. Only
+ * called by the primary cpu after a cold boot.
+ * TODO: Add support for alternative image load mechanism e.g using virtio/elf
+ * loader etc.
+  ******************************************************************************/
+void bl1_main(void)
+{
+       /* Announce our arrival */
+       NOTICE(FIRMWARE_WELCOME_STR);
+       NOTICE("BL1: %s\n", version_string);
+       NOTICE("BL1: %s\n", build_message);
+
+       INFO("BL1: RAM 0x%lx - 0x%lx\n", BL1_RAM_BASE, BL1_RAM_LIMIT);
+
+#if DEBUG
+       unsigned long sctlr_el3 = read_sctlr_el3();
+#endif
+       image_info_t bl2_image_info = { {0} };
+       entry_point_info_t bl2_ep = { {0} };
+       meminfo_t *bl1_tzram_layout;
+       meminfo_t *bl2_tzram_layout = 0x0;
+       int err;
+
+       /*
+        * Ensure that MMU/Caches and coherency are turned on
+        */
+       assert(sctlr_el3 | SCTLR_M_BIT);
+       assert(sctlr_el3 | SCTLR_C_BIT);
+       assert(sctlr_el3 | SCTLR_I_BIT);
+
+       /* Perform remaining generic architectural setup from EL3 */
+       bl1_arch_setup();
+
+       /* Perform platform setup in BL1. */
+       bl1_platform_setup();
+
+       SET_PARAM_HEAD(&bl2_image_info, PARAM_IMAGE_BINARY, VERSION_1, 0);
+       SET_PARAM_HEAD(&bl2_ep, PARAM_EP, VERSION_1, 0);
+
+       /* Find out how much free trusted ram remains after BL1 load */
+       bl1_tzram_layout = bl1_plat_sec_mem_layout();
+
+#if TRUSTED_BOARD_BOOT
+       /* Initialize authentication module */
+       auth_init();
+
+       /*
+        * Load the BL2 certificate into the BL2 region. This region will be
+        * overwritten by the image, so the authentication module is responsible
+        * for storing the relevant data from the certificate (keys, hashes,
+        * etc.) so it can be used later.
+        */
+       err = load_image(bl1_tzram_layout,
+                        BL2_CERT_NAME,
+                        BL2_BASE,
+                        &bl2_image_info,
+                        NULL);
+       if (err) {
+               ERROR("Failed to load BL2 certificate.\n");
+               panic();
+       }
+
+       err = auth_verify_obj(AUTH_BL2_IMG_CERT, bl2_image_info.image_base,
+                       bl2_image_info.image_size);
+       if (err) {
+               ERROR("Failed to validate BL2 certificate.\n");
+               panic();
+       }
+#endif /* TRUSTED_BOARD_BOOT */
+
+       /* Load the BL2 image */
+       err = load_image(bl1_tzram_layout,
+                        BL2_IMAGE_NAME,
+                        BL2_BASE,
+                        &bl2_image_info,
+                        &bl2_ep);
+       if (err) {
+               /*
+                * TODO: print failure to load BL2 but also add a tzwdog timer
+                * which will reset the system eventually.
+                */
+               ERROR("Failed to load BL2 firmware.\n");
+               panic();
+       }
+
+#if TRUSTED_BOARD_BOOT
+       err = auth_verify_obj(AUTH_BL2_IMG, bl2_image_info.image_base,
+                               bl2_image_info.image_size);
+       if (err) {
+               ERROR("Failed to validate BL2 image.\n");
+               panic();
+       }
+
+       /* After working with data, invalidate the data cache */
+       inv_dcache_range(bl2_image_info.image_base,
+                       (size_t)bl2_image_info.image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
+       /*
+        * Create a new layout of memory for BL2 as seen by BL1 i.e.
+        * tell it the amount of total and free memory available.
+        * This layout is created at the first free address visible
+        * to BL2. BL2 will read the memory layout before using its
+        * memory for other purposes.
+        */
+       bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->free_base;
+       bl1_init_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout);
+
+       bl1_plat_set_bl2_ep_info(&bl2_image_info, &bl2_ep);
+       bl2_ep.args.arg1 = (unsigned long)bl2_tzram_layout;
+       NOTICE("BL1: Booting BL2\n");
+       INFO("BL1: BL2 address = 0x%llx\n",
+               (unsigned long long) bl2_ep.pc);
+       INFO("BL1: BL2 spsr = 0x%x\n", bl2_ep.spsr);
+       VERBOSE("BL1: BL2 memory layout address = 0x%llx\n",
+               (unsigned long long) bl2_tzram_layout);
+
+       bl1_run_bl2(&bl2_ep);
+
+       return;
+}
+
+/*******************************************************************************
+ * Temporary function to print the fact that BL2 has done its job and BL31 is
+ * about to be loaded. This is needed as long as printfs cannot be used
+ ******************************************************************************/
+void display_boot_progress(entry_point_info_t *bl31_ep_info)
+{
+       NOTICE("BL1: Booting BL3-1\n");
+       INFO("BL1: BL3-1 address = 0x%llx\n",
+               (unsigned long long)bl31_ep_info->pc);
+       INFO("BL1: BL3-1 spsr = 0x%llx\n",
+               (unsigned long long)bl31_ep_info->spsr);
+       INFO("BL1: BL3-1 params address = 0x%llx\n",
+               (unsigned long long)bl31_ep_info->args.arg0);
+       INFO("BL1: BL3-1 plat params address = 0x%llx\n",
+               (unsigned long long)bl31_ep_info->args.arg1);
+}
diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h
new file mode 100644 (file)
index 0000000..0a8fc45
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BL1_PRIVATE_H__
+#define __BL1_PRIVATE_H__
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will tell us where BL1 lives
+ * in Trusted RAM
+ ******************************************************************************/
+extern uint64_t __BL1_RAM_START__;
+extern uint64_t __BL1_RAM_END__;
+#define BL1_RAM_BASE (uint64_t)(&__BL1_RAM_START__)
+#define BL1_RAM_LIMIT (uint64_t)(&__BL1_RAM_END__)
+
+/******************************************
+ * Function prototypes
+ *****************************************/
+void bl1_arch_setup(void);
+void bl1_arch_next_el_setup(void);
+
+#endif /* __BL1_PRIVATE_H__ */
diff --git a/bl2/aarch64/bl2_arch_setup.c b/bl2/aarch64/bl2_arch_setup.c
new file mode 100644 (file)
index 0000000..0eafd15
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+
+/*******************************************************************************
+ * 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));
+}
diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S
new file mode 100644 (file)
index 0000000..499dc37
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+
+
+       .globl  bl2_entrypoint
+
+
+
+func bl2_entrypoint
+       /*---------------------------------------------
+        * Store the extents of the tzram available to
+        * BL2 for future use. Use the opcode param to
+        * allow implement other functions if needed.
+        * ---------------------------------------------
+        */
+       mov     x20, x0
+       mov     x21, x1
+
+       /* ---------------------------------------------
+        * 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
+
+       /* ---------------------------------------------
+        * Check the opcodes out of paranoia.
+        * ---------------------------------------------
+        */
+       mov     x0, #RUN_IMAGE
+       cmp     x0, x20
+       b.ne    _panic
+
+       /* ---------------------------------------------
+        * 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      zeromem16
+
+#if USE_COHERENT_MEM
+       ldr     x0, =__COHERENT_RAM_START__
+       ldr     x1, =__COHERENT_RAM_UNALIGNED_SIZE__
+       bl      zeromem16
+#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.
+        * --------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_set_stack
+
+       /* ---------------------------------------------
+        * Perform early platform setup & platform
+        * specific early arch. setup e.g. mmu setup
+        * ---------------------------------------------
+        */
+       mov     x0, x21
+       bl      bl2_early_platform_setup
+       bl      bl2_plat_arch_setup
+
+       /* ---------------------------------------------
+        * Jump to main function.
+        * ---------------------------------------------
+        */
+       bl      bl2_main
+_panic:
+       b       _panic
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
new file mode 100644 (file)
index 0000000..9933339
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.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(4096),
+           "BL2_BASE address is not aligned on a page boundary.")
+
+    ro . : {
+        __RO_START__ = .;
+        *bl2_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(4096);
+        __RO_END__ = .;
+    } >RAM
+
+    .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 must be 16-byte aligned.
+     */
+    .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 and eliminates the unecessary zero init
+     */
+    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(4096) {
+        __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(4096);
+        __COHERENT_RAM_END__ = .;
+    } >RAM
+#endif
+
+    __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.")
+}
diff --git a/bl2/bl2.mk b/bl2/bl2.mk
new file mode 100644 (file)
index 0000000..1e82078
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+BL2_SOURCES            +=      bl2/bl2_main.c                          \
+                               bl2/aarch64/bl2_entrypoint.S            \
+                               bl2/aarch64/bl2_arch_setup.c            \
+                               common/aarch64/early_exceptions.S       \
+                               lib/locks/exclusive/spinlock.S
+
+BL2_LINKERFILE         :=      bl2/bl2.ld.S
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
new file mode 100644 (file)
index 0000000..5b1e69c
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <auth.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include "bl2_private.h"
+
+#if TRUSTED_BOARD_BOOT
+
+#ifdef BL32_BASE
+static int bl32_cert_error;
+#endif
+
+/*
+ * Load and authenticate the key and content certificates for a BL3-x image
+ *
+ * Parameters:
+ *   key_cert_blob: key certificate blob id (see auth.h)
+ *   key_cert_name: key certificate filename
+ *   cont_cert_blob: content certificate blob id (see auth.h)
+ *   cont_cert_name: content certificate filename
+ *   mem_layout: Trusted SRAM memory layout
+ *   load_addr: load the certificates at this address
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int load_cert_bl3x(int key_cert_blob, const char *key_cert_name,
+                         int cont_cert_blob, const char *cont_cert_name,
+                         meminfo_t *mem_layout, uint64_t load_addr)
+{
+       image_info_t image_info;
+       int err;
+
+       /* Load Key certificate */
+       image_info.h.version = VERSION_1;
+       err = load_image(mem_layout, key_cert_name, load_addr, &image_info, NULL);
+       if (err) {
+               ERROR("Cannot load %s.\n", key_cert_name);
+               return err;
+       }
+
+       err = auth_verify_obj(key_cert_blob, image_info.image_base,
+                       image_info.image_size);
+       if (err) {
+               ERROR("Invalid key certificate %s.\n", key_cert_name);
+               return err;
+       }
+
+       /* Load Content certificate */
+       image_info.h.version = VERSION_1;
+       err = load_image(mem_layout, cont_cert_name, load_addr, &image_info, NULL);
+       if (err) {
+               ERROR("Cannot load %s.\n", cont_cert_name);
+               return err;
+       }
+
+       err = auth_verify_obj(cont_cert_blob, image_info.image_base,
+                       image_info.image_size);
+       if (err) {
+               ERROR("Invalid content certificate %s.\n", cont_cert_name);
+               return err;
+       }
+
+       return 0;
+}
+
+/*
+ * Load and authenticate the Trusted Key certificate the key and content
+ * certificates for each of the BL3-x images.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int load_certs(void)
+{
+       const uint64_t load_addr = BL31_BASE;
+       image_info_t image_info;
+       meminfo_t *mem_layout;
+       int err;
+
+       /* Find out how much free trusted ram remains after BL2 load */
+       mem_layout = bl2_plat_sec_mem_layout();
+
+       /* Load the Trusted Key certificate in the BL31 region */
+       image_info.h.version = VERSION_1;
+       err = load_image(mem_layout, TRUSTED_KEY_CERT_NAME, load_addr,
+                        &image_info, NULL);
+       if (err) {
+               ERROR("Failed to load Trusted Key certificate.\n");
+               return err;
+       }
+
+       /* Validate the certificate */
+       err = auth_verify_obj(AUTH_TRUSTED_KEY_CERT, image_info.image_base,
+                       image_info.image_size);
+       if (err) {
+               ERROR("Invalid Trusted Key certificate.\n");
+               return err;
+       }
+
+       /* Load and validate Key and Content certificates for BL3-x images */
+#ifdef BL30_BASE
+       err = load_cert_bl3x(AUTH_BL30_KEY_CERT, BL30_KEY_CERT_NAME,
+                            AUTH_BL30_IMG_CERT, BL30_CERT_NAME,
+                            mem_layout, load_addr);
+       if (err) {
+               ERROR("Failed to verify BL3-0 authenticity\n");
+               return err;
+       }
+#endif /* BL30_BASE */
+
+       err = load_cert_bl3x(AUTH_BL31_KEY_CERT, BL31_KEY_CERT_NAME,
+                            AUTH_BL31_IMG_CERT, BL31_CERT_NAME,
+                            mem_layout, load_addr);
+       if (err) {
+               ERROR("Failed to verify BL3-1 authenticity\n");
+               return err;
+       }
+
+#ifdef BL32_BASE
+       /* BL3-2 image is optional, but keep the return value in case the
+        * image is present but the certificate is missing */
+       err = load_cert_bl3x(AUTH_BL32_KEY_CERT, BL32_KEY_CERT_NAME,
+                            AUTH_BL32_IMG_CERT, BL32_CERT_NAME,
+                            mem_layout, load_addr);
+       if (err) {
+               WARN("Failed to verify BL3-2 authenticity\n");
+       }
+       bl32_cert_error = err;
+#endif /* BL32_BASE */
+
+       err = load_cert_bl3x(AUTH_BL33_KEY_CERT, BL33_KEY_CERT_NAME,
+                            AUTH_BL33_IMG_CERT, BL33_CERT_NAME,
+                            mem_layout, load_addr);
+       if (err) {
+               ERROR("Failed to verify BL3-3 authenticity\n");
+               return err;
+       }
+
+       return 0;
+}
+
+#endif /* TRUSTED_BOARD_BOOT */
+
+/*******************************************************************************
+ * Load the BL3-0 image if there's one.
+ * If a platform does not want to attempt to load BL3-0 image it must leave
+ * BL30_BASE undefined.
+ * Return 0 on success or if there's no BL3-0 image to load, a negative error
+ * code otherwise.
+ ******************************************************************************/
+static int load_bl30(void)
+{
+       int e = 0;
+#ifdef BL30_BASE
+       meminfo_t bl30_mem_info;
+       image_info_t bl30_image_info;
+
+       /*
+        * It is up to the platform to specify where BL3-0 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 BL3-0 image.
+        */
+       INFO("BL2: Loading BL3-0\n");
+       bl2_plat_get_bl30_meminfo(&bl30_mem_info);
+       bl30_image_info.h.version = VERSION_1;
+       e = load_image(&bl30_mem_info,
+                      BL30_IMAGE_NAME,
+                      BL30_BASE,
+                      &bl30_image_info,
+                      NULL);
+
+       if (e == 0) {
+#if TRUSTED_BOARD_BOOT
+               e = auth_verify_obj(AUTH_BL30_IMG,
+                               bl30_image_info.image_base,
+                               bl30_image_info.image_size);
+               if (e) {
+                       ERROR("Failed to authenticate BL3-0 image.\n");
+                       panic();
+               }
+
+               /* After working with data, invalidate the data cache */
+               inv_dcache_range(bl30_image_info.image_base,
+                                (size_t)bl30_image_info.image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
+               /* The subsequent handling of BL3-0 is platform specific */
+               bl2_plat_handle_bl30(&bl30_image_info);
+       }
+#endif /* BL30_BASE */
+
+       return e;
+}
+
+/*******************************************************************************
+ * Load the BL3-1 image.
+ * The bl2_to_bl31_params and bl31_ep_info params will be updated with the
+ * relevant BL3-1 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 BL3-1\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 BL3-1 */
+       bl31_ep_info->args.arg0 = (unsigned long)bl2_to_bl31_params;
+
+       /* Load the BL3-1 image */
+       e = load_image(bl2_tzram_layout,
+                      BL31_IMAGE_NAME,
+                      BL31_BASE,
+                      bl2_to_bl31_params->bl31_image_info,
+                      bl31_ep_info);
+
+       if (e == 0) {
+#if TRUSTED_BOARD_BOOT
+               e = auth_verify_obj(AUTH_BL31_IMG,
+                       bl2_to_bl31_params->bl31_image_info->image_base,
+                       bl2_to_bl31_params->bl31_image_info->image_size);
+               if (e) {
+                       ERROR("Failed to authenticate BL3-1 image.\n");
+                       panic();
+               }
+
+               /* After working with data, invalidate the data cache */
+               inv_dcache_range(bl2_to_bl31_params->bl31_image_info->image_base,
+                       (size_t)bl2_to_bl31_params->bl31_image_info->image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
+               bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info,
+                                         bl31_ep_info);
+       }
+
+       return e;
+}
+
+/*******************************************************************************
+ * Load the BL3-2 image if there's one.
+ * The bl2_to_bl31_params param will be updated with the relevant BL3-2
+ * information.
+ * If a platform does not want to attempt to load BL3-2 image it must leave
+ * BL32_BASE undefined.
+ * Return 0 on success or if there's no BL3-2 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 BL3-2\n");
+       assert(bl2_to_bl31_params != NULL);
+
+       /*
+        * It is up to the platform to specify where BL3-2 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_image(&bl32_mem_info,
+                      BL32_IMAGE_NAME,
+                      BL32_BASE,
+                      bl2_to_bl31_params->bl32_image_info,
+                      bl2_to_bl31_params->bl32_ep_info);
+
+       if (e == 0) {
+#if TRUSTED_BOARD_BOOT
+               /* Image is present. Check if there is a valid certificate */
+               if (bl32_cert_error) {
+                       ERROR("Failed to authenticate BL3-2 certificates.\n");
+                       panic();
+               }
+
+               e = auth_verify_obj(AUTH_BL32_IMG,
+                       bl2_to_bl31_params->bl32_image_info->image_base,
+                       bl2_to_bl31_params->bl32_image_info->image_size);
+               if (e) {
+                       ERROR("Failed to authenticate BL3-2 image.\n");
+                       panic();
+               }
+               /* After working with data, invalidate the data cache */
+               inv_dcache_range(bl2_to_bl31_params->bl32_image_info->image_base,
+                       (size_t)bl2_to_bl31_params->bl32_image_info->image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
+               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;
+}
+
+/*******************************************************************************
+ * Load the BL3-3 image.
+ * The bl2_to_bl31_params param will be updated with the relevant BL3-3
+ * 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 BL3-3\n");
+       assert(bl2_to_bl31_params != NULL);
+
+       bl2_plat_get_bl33_meminfo(&bl33_mem_info);
+
+       /* Load the BL3-3 image in non-secure memory provided by the platform */
+       e = load_image(&bl33_mem_info,
+                      BL33_IMAGE_NAME,
+                      plat_get_ns_image_entrypoint(),
+                      bl2_to_bl31_params->bl33_image_info,
+                      bl2_to_bl31_params->bl33_ep_info);
+
+       if (e == 0) {
+#if TRUSTED_BOARD_BOOT
+               e = auth_verify_obj(AUTH_BL33_IMG,
+                               bl2_to_bl31_params->bl33_image_info->image_base,
+                               bl2_to_bl31_params->bl33_image_info->image_size);
+               if (e) {
+                       ERROR("Failed to authenticate BL3-3 image.\n");
+                       panic();
+               }
+               /* After working with data, invalidate the data cache */
+               inv_dcache_range(bl2_to_bl31_params->bl33_image_info->image_base,
+                       (size_t)bl2_to_bl31_params->bl33_image_info->image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
+               bl2_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info,
+                                         bl2_to_bl31_params->bl33_ep_info);
+       }
+
+       return e;
+}
+
+/*******************************************************************************
+ * The only thing to do in BL2 is to load further images and pass control to
+ * BL3-1. The memory occupied by BL2 will be reclaimed by BL3-x stages. BL2 runs
+ * entirely in S-EL1.
+ ******************************************************************************/
+void bl2_main(void)
+{
+       bl31_params_t *bl2_to_bl31_params;
+       entry_point_info_t *bl31_ep_info;
+       int e;
+
+       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_init();
+
+       /* Validate the certificates involved in the Chain of Trust */
+       e = load_certs();
+       if (e) {
+               ERROR("Chain of Trust invalid. Aborting...\n");
+               panic();
+       }
+#endif /* TRUSTED_BOARD_BOOT */
+
+       /*
+        * Load the subsequent bootloader images
+        */
+       e = load_bl30();
+       if (e) {
+               ERROR("Failed to load BL3-0 (%i)\n", e);
+               ERROR("Please burn mcu image:\n");
+               ERROR("  sudo fastboot flash mcuimage mcuimage.bin\n");
+       }
+
+       /* Perform platform setup in BL2 after loading BL3-0 */
+       bl2_platform_setup();
+
+       /*
+        * Get a pointer to the memory the platform has set aside to pass
+        * information to BL3-1.
+        */
+       bl2_to_bl31_params = bl2_plat_get_bl31_params();
+       bl31_ep_info = bl2_plat_get_bl31_ep_info();
+
+       e = load_bl31(bl2_to_bl31_params, bl31_ep_info);
+       if (e) {
+               ERROR("Failed to load BL3-1 (%i)\n", e);
+               panic();
+       }
+
+       e = load_bl32(bl2_to_bl31_params);
+       if (e)
+               WARN("Failed to load BL3-2 (%i)\n", e);
+
+       e = load_bl33(bl2_to_bl31_params);
+       if (e) {
+               ERROR("Failed to load BL3-3 (%i)\n", e);
+               panic();
+       }
+
+       /* Flush the params to be passed to memory */
+       bl2_plat_flush_bl31_params();
+
+       /*
+        * Run BL3-1 via an SMC to BL1. Information on how to pass control to
+        * the BL3-2 (if present) and BL3-3 software images will be passed to
+        * BL3-1 as an argument.
+        */
+       smc(RUN_IMAGE, (unsigned long)bl31_ep_info, 0, 0, 0, 0, 0, 0);
+}
diff --git a/bl2/bl2_private.h b/bl2/bl2_private.h
new file mode 100644 (file)
index 0000000..022d1e9
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BL2_PRIVATE_H__
+#define __BL2_PRIVATE_H__
+
+/******************************************
+ * Function prototypes
+ *****************************************/
+void bl2_arch_setup(void);
+
+#endif /* __BL2_PRIVATE_H__ */
diff --git a/bl31/aarch64/bl31_arch_setup.c b/bl31/aarch64/bl31_arch_setup.c
new file mode 100644 (file)
index 0000000..a88b029
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <platform.h>
+
+/*******************************************************************************
+ * This duplicates what the primary cpu did after a cold boot in BL1. The same
+ * needs to be done when a cpu is hotplugged in. This function could also over-
+ * ride any EL3 setup done by BL1 as this code resides in rw memory.
+ ******************************************************************************/
+void bl31_arch_setup(void)
+{
+       /* Set the RES1 bits in the SCR_EL3 */
+       write_scr_el3(SCR_RES1_BITS);
+
+       /* Program the counter frequency */
+       write_cntfrq_el0(plat_get_syscnt_freq());
+}
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
new file mode 100644 (file)
index 0000000..c0ddeec
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+
+       .globl  bl31_entrypoint
+
+       .globl __getspin
+       .globl __set_entries
+       .globl __uboot_data
+
+       /* -----------------------------------------------------
+        * bl31_entrypoint() is the cold boot entrypoint,
+        * executed only by the primary cpu.
+        * -----------------------------------------------------
+        */
+
+func bl31_entrypoint
+       b __skipspin
+__getspin:
+       b bl31_getspin
+__set_entries:
+       b bl31_uboot_set_entries
+__uboot_data:
+       .quad 0
+       .quad 0
+       .quad 0
+__skipspin:
+       /* ---------------------------------------------------------------
+        * Preceding bootloader has populated x0 with a pointer to a
+        * 'bl31_params' structure & x1 with a pointer to platform
+        * specific structure
+        * ---------------------------------------------------------------
+        */
+#if !RESET_TO_BL31
+       mov     x20, x0
+       mov     x21, x1
+#else
+       /* ---------------------------------------------
+        * Set the CPU endianness before doing anything
+        * that might involve memory reads or writes.
+        * ---------------------------------------------
+        */
+       mrs     x0, sctlr_el3
+       bic     x0, x0, #SCTLR_EE_BIT
+       msr     sctlr_el3, x0
+       isb
+#endif
+
+       /* ---------------------------------------------
+        * When RESET_TO_BL31 is true, perform any
+        * processor specific actions upon reset e.g.
+        * cache, tlb invalidations, errata workarounds
+        * etc.
+        * When RESET_TO_BL31 is false, perform any
+        * processor specific actions which undo or are
+        * in addition to the actions performed by the
+        * reset handler in the Boot ROM (BL1).
+        * ---------------------------------------------
+        */
+       bl      reset_handler
+
+       /* ---------------------------------------------
+        * 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_el3
+       orr     x0, x0, x1
+       msr     sctlr_el3, x0
+       isb
+
+       /* ---------------------------------------------
+        * Initialise cpu_data early to enable crash
+        * reporting to have access to crash stack.
+        * Since crash reporting depends on cpu_data to
+        * report the unhandled exception, not
+        * doing so can lead to recursive exceptions due
+        * to a NULL TPIDR_EL3
+        * ---------------------------------------------
+        */
+       bl      init_cpu_data_ptr
+
+       /* ---------------------------------------------
+        * Set the exception vector.
+        * ---------------------------------------------
+        */
+       adr     x1, runtime_exceptions
+       msr     vbar_el3, x1
+       isb
+
+       /* ---------------------------------------------
+        * Enable the SError interrupt now that the
+        * exception vectors have been setup.
+        * ---------------------------------------------
+        */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       /* ---------------------------------------------------------------------
+        * The initial state of the Architectural feature trap register
+        * (CPTR_EL3) is unknown and it must be set to a known state. All
+        * feature traps are disabled. Some bits in this register are marked as
+        * Reserved and should not be modified.
+        *
+        * CPTR_EL3.TCPAC: This causes a direct access to the CPACR_EL1 from EL1
+        *  or the CPTR_EL2 from EL2 to trap to EL3 unless it is trapped at EL2.
+        * CPTR_EL3.TTA: This causes access to the Trace functionality to trap
+        *  to EL3 when executed from EL0, EL1, EL2, or EL3. If system register
+        *  access to trace functionality is not supported, this bit is RES0.
+        * CPTR_EL3.TFP: This causes instructions that access the registers
+        *  associated with Floating Point and Advanced SIMD execution to trap
+        *  to EL3 when executed from any exception level, unless trapped to EL1
+        *  or EL2.
+        * ---------------------------------------------------------------------
+        */
+       mrs     x1, cptr_el3
+       bic     w1, w1, #TCPAC_BIT
+       bic     w1, w1, #TTA_BIT
+       bic     w1, w1, #TFP_BIT
+       msr     cptr_el3, x1
+
+#if RESET_TO_BL31
+       /* -------------------------------------------------------
+        * Will not return from this macro if it is a warm boot.
+        * -------------------------------------------------------
+        */
+       wait_for_entrypoint
+       bl      platform_mem_init
+#endif
+
+       /* ---------------------------------------------
+        * 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      zeromem16
+
+#if USE_COHERENT_MEM
+       ldr     x0, =__COHERENT_RAM_START__
+       ldr     x1, =__COHERENT_RAM_UNALIGNED_SIZE__
+       bl      zeromem16
+#endif
+
+       /* ---------------------------------------------
+        * Initialize the cpu_ops pointer.
+        * ---------------------------------------------
+        */
+       bl      init_cpu_ops
+
+       /* ---------------------------------------------
+        * Use SP_EL0 for the C runtime stack.
+        * ---------------------------------------------
+        */
+       msr     spsel, #0
+
+       /* --------------------------------------------
+        * 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.
+        * --------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_set_stack
+
+       /* ---------------------------------------------
+        * Perform platform specific early arch. setup
+        * ---------------------------------------------
+        */
+#if RESET_TO_BL31
+       mov     x0, 0
+       mov     x1, 0
+#else
+       mov     x0, x20
+       mov     x1, x21
+#endif
+
+       bl      bl31_early_platform_setup
+       bl      bl31_plat_arch_setup
+
+       /* ---------------------------------------------
+        * Jump to main function.
+        * ---------------------------------------------
+        */
+       bl      bl31_main
+
+       b       el3_exit
diff --git a/bl31/aarch64/context.S b/bl31/aarch64/context.S
new file mode 100644 (file)
index 0000000..b127480
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <context.h>
+
+/* -----------------------------------------------------
+ * The following function strictly follows the AArch64
+ * PCS to use x9-x17 (temporary caller-saved registers)
+ * to save EL1 system register context. It assumes that
+ * 'x0' is pointing to a 'el1_sys_regs' structure where
+ * the register context will be saved.
+ * -----------------------------------------------------
+ */
+       .global el1_sysregs_context_save
+func el1_sysregs_context_save
+
+       mrs     x9, spsr_el1
+       mrs     x10, elr_el1
+       stp     x9, x10, [x0, #CTX_SPSR_EL1]
+
+       mrs     x11, spsr_abt
+       mrs     x12, spsr_und
+       stp     x11, x12, [x0, #CTX_SPSR_ABT]
+
+       mrs     x13, spsr_irq
+       mrs     x14, spsr_fiq
+       stp     x13, x14, [x0, #CTX_SPSR_IRQ]
+
+       mrs     x15, sctlr_el1
+       mrs     x16, actlr_el1
+       stp     x15, x16, [x0, #CTX_SCTLR_EL1]
+
+       mrs     x17, cpacr_el1
+       mrs     x9, csselr_el1
+       stp     x17, x9, [x0, #CTX_CPACR_EL1]
+
+       mrs     x10, sp_el1
+       mrs     x11, esr_el1
+       stp     x10, x11, [x0, #CTX_SP_EL1]
+
+       mrs     x12, ttbr0_el1
+       mrs     x13, ttbr1_el1
+       stp     x12, x13, [x0, #CTX_TTBR0_EL1]
+
+       mrs     x14, mair_el1
+       mrs     x15, amair_el1
+       stp     x14, x15, [x0, #CTX_MAIR_EL1]
+
+       mrs     x16, tcr_el1
+       mrs     x17, tpidr_el1
+       stp     x16, x17, [x0, #CTX_TCR_EL1]
+
+       mrs     x9, tpidr_el0
+       mrs     x10, tpidrro_el0
+       stp     x9, x10, [x0, #CTX_TPIDR_EL0]
+
+       mrs     x11, dacr32_el2
+       mrs     x12, ifsr32_el2
+       stp     x11, x12, [x0, #CTX_DACR32_EL2]
+
+       mrs     x13, par_el1
+       mrs     x14, far_el1
+       stp     x13, x14, [x0, #CTX_PAR_EL1]
+
+       mrs     x15, afsr0_el1
+       mrs     x16, afsr1_el1
+       stp     x15, x16, [x0, #CTX_AFSR0_EL1]
+
+       mrs     x17, contextidr_el1
+       mrs     x9, vbar_el1
+       stp     x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
+
+       /* Save NS timer registers if the build has instructed so */
+#if NS_TIMER_SWITCH
+       mrs     x10, cntp_ctl_el0
+       mrs     x11, cntp_cval_el0
+       stp     x10, x11, [x0, #CTX_CNTP_CTL_EL0]
+
+       mrs     x12, cntv_ctl_el0
+       mrs     x13, cntv_cval_el0
+       stp     x12, x13, [x0, #CTX_CNTV_CTL_EL0]
+
+       mrs     x14, cntkctl_el1
+       str     x14, [x0, #CTX_CNTKCTL_EL1]
+#endif
+
+       mrs     x15, fpexc32_el2
+       str     x15, [x0, #CTX_FP_FPEXC32_EL2]
+
+       ret
+
+/* -----------------------------------------------------
+ * The following function strictly follows the AArch64
+ * PCS to use x9-x17 (temporary caller-saved registers)
+ * to restore EL1 system register context.  It assumes
+ * that 'x0' is pointing to a 'el1_sys_regs' structure
+ * from where the register context will be restored
+ * -----------------------------------------------------
+ */
+       .global el1_sysregs_context_restore
+func el1_sysregs_context_restore
+
+       ldp     x9, x10, [x0, #CTX_SPSR_EL1]
+       msr     spsr_el1, x9
+       msr     elr_el1, x10
+
+       ldp     x11, x12, [x0, #CTX_SPSR_ABT]
+       msr     spsr_abt, x11
+       msr     spsr_und, x12
+
+       ldp     x13, x14, [x0, #CTX_SPSR_IRQ]
+       msr     spsr_irq, x13
+       msr     spsr_fiq, x14
+
+       ldp     x15, x16, [x0, #CTX_SCTLR_EL1]
+       msr     sctlr_el1, x15
+       msr     actlr_el1, x16
+
+       ldp     x17, x9, [x0, #CTX_CPACR_EL1]
+       msr     cpacr_el1, x17
+       msr     csselr_el1, x9
+
+       ldp     x10, x11, [x0, #CTX_SP_EL1]
+       msr     sp_el1, x10
+       msr     esr_el1, x11
+
+       ldp     x12, x13, [x0, #CTX_TTBR0_EL1]
+       msr     ttbr0_el1, x12
+       msr     ttbr1_el1, x13
+
+       ldp     x14, x15, [x0, #CTX_MAIR_EL1]
+       msr     mair_el1, x14
+       msr     amair_el1, x15
+
+       ldp     x16, x17, [x0, #CTX_TCR_EL1]
+       msr     tcr_el1, x16
+       msr     tpidr_el1, x17
+
+       ldp     x9, x10, [x0, #CTX_TPIDR_EL0]
+       msr     tpidr_el0, x9
+       msr     tpidrro_el0, x10
+
+       ldp     x11, x12, [x0, #CTX_DACR32_EL2]
+       msr     dacr32_el2, x11
+       msr     ifsr32_el2, x12
+
+       ldp     x13, x14, [x0, #CTX_PAR_EL1]
+       msr     par_el1, x13
+       msr     far_el1, x14
+
+       ldp     x15, x16, [x0, #CTX_AFSR0_EL1]
+       msr     afsr0_el1, x15
+       msr     afsr1_el1, x16
+
+       ldp     x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
+       msr     contextidr_el1, x17
+       msr     vbar_el1, x9
+
+       /* Restore NS timer registers if the build has instructed so */
+#if NS_TIMER_SWITCH
+       ldp     x10, x11, [x0, #CTX_CNTP_CTL_EL0]
+       msr     cntp_ctl_el0, x10
+       msr     cntp_cval_el0, x11
+
+       ldp     x12, x13, [x0, #CTX_CNTV_CTL_EL0]
+       msr     cntv_ctl_el0, x12
+       msr     cntv_cval_el0, x13
+
+       ldr     x14, [x0, #CTX_CNTKCTL_EL1]
+       msr     cntkctl_el1, x14
+#endif
+
+       ldr     x15, [x0, #CTX_FP_FPEXC32_EL2]
+       msr     fpexc32_el2, x15
+
+       /* No explict ISB required here as ERET covers it */
+
+       ret
+
+/* -----------------------------------------------------
+ * The following function follows the aapcs_64 strictly
+ * to use x9-x17 (temporary caller-saved registers
+ * according to AArch64 PCS) to save floating point
+ * register context. It assumes that 'x0' is pointing to
+ * a 'fp_regs' structure where the register context will
+ * be saved.
+ *
+ * Access to VFP registers will trap if CPTR_EL3.TFP is
+ * set.  However currently we don't use VFP registers
+ * nor set traps in Trusted Firmware, and assume it's
+ * cleared
+ *
+ * TODO: Revisit when VFP is used in secure world
+ * -----------------------------------------------------
+ */
+#if CTX_INCLUDE_FPREGS
+       .global fpregs_context_save
+func fpregs_context_save
+       stp     q0, q1, [x0, #CTX_FP_Q0]
+       stp     q2, q3, [x0, #CTX_FP_Q2]
+       stp     q4, q5, [x0, #CTX_FP_Q4]
+       stp     q6, q7, [x0, #CTX_FP_Q6]
+       stp     q8, q9, [x0, #CTX_FP_Q8]
+       stp     q10, q11, [x0, #CTX_FP_Q10]
+       stp     q12, q13, [x0, #CTX_FP_Q12]
+       stp     q14, q15, [x0, #CTX_FP_Q14]
+       stp     q16, q17, [x0, #CTX_FP_Q16]
+       stp     q18, q19, [x0, #CTX_FP_Q18]
+       stp     q20, q21, [x0, #CTX_FP_Q20]
+       stp     q22, q23, [x0, #CTX_FP_Q22]
+       stp     q24, q25, [x0, #CTX_FP_Q24]
+       stp     q26, q27, [x0, #CTX_FP_Q26]
+       stp     q28, q29, [x0, #CTX_FP_Q28]
+       stp     q30, q31, [x0, #CTX_FP_Q30]
+
+       mrs     x9, fpsr
+       str     x9, [x0, #CTX_FP_FPSR]
+
+       mrs     x10, fpcr
+       str     x10, [x0, #CTX_FP_FPCR]
+
+       ret
+
+/* -----------------------------------------------------
+ * The following function follows the aapcs_64 strictly
+ * to use x9-x17 (temporary caller-saved registers
+ * according to AArch64 PCS) to restore floating point
+ * register context. It assumes that 'x0' is pointing to
+ * a 'fp_regs' structure from where the register context
+ * will be restored.
+ *
+ * Access to VFP registers will trap if CPTR_EL3.TFP is
+ * set.  However currently we don't use VFP registers
+ * nor set traps in Trusted Firmware, and assume it's
+ * cleared
+ *
+ * TODO: Revisit when VFP is used in secure world
+ * -----------------------------------------------------
+ */
+       .global fpregs_context_restore
+func fpregs_context_restore
+       ldp     q0, q1, [x0, #CTX_FP_Q0]
+       ldp     q2, q3, [x0, #CTX_FP_Q2]
+       ldp     q4, q5, [x0, #CTX_FP_Q4]
+       ldp     q6, q7, [x0, #CTX_FP_Q6]
+       ldp     q8, q9, [x0, #CTX_FP_Q8]
+       ldp     q10, q11, [x0, #CTX_FP_Q10]
+       ldp     q12, q13, [x0, #CTX_FP_Q12]
+       ldp     q14, q15, [x0, #CTX_FP_Q14]
+       ldp     q16, q17, [x0, #CTX_FP_Q16]
+       ldp     q18, q19, [x0, #CTX_FP_Q18]
+       ldp     q20, q21, [x0, #CTX_FP_Q20]
+       ldp     q22, q23, [x0, #CTX_FP_Q22]
+       ldp     q24, q25, [x0, #CTX_FP_Q24]
+       ldp     q26, q27, [x0, #CTX_FP_Q26]
+       ldp     q28, q29, [x0, #CTX_FP_Q28]
+       ldp     q30, q31, [x0, #CTX_FP_Q30]
+
+       ldr     x9, [x0, #CTX_FP_FPSR]
+       msr     fpsr, x9
+
+       str     x10, [x0, #CTX_FP_FPCR]
+       msr     fpcr, x10
+
+       /*
+        * No explict ISB required here as ERET to
+        * swtich to secure EL1 or non-secure world
+        * covers it
+        */
+
+       ret
+#endif /* CTX_INCLUDE_FPREGS */
diff --git a/bl31/aarch64/cpu_data.S b/bl31/aarch64/cpu_data.S
new file mode 100644 (file)
index 0000000..feb51d6
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm_macros.S>
+#include <cpu_data.h>
+
+.globl init_cpu_data_ptr
+.globl _cpu_data_by_mpidr
+.globl _cpu_data_by_index
+
+/* -----------------------------------------------------------------
+ * void init_cpu_data_ptr(void)
+ *
+ * Initialise the TPIDR_EL3 register to refer to the cpu_data_t
+ * for the calling CPU. This must be called before cm_get_cpu_data()
+ *
+ * This can be called without a valid stack.
+ * clobbers: x0, x1, x9, x10
+ * -----------------------------------------------------------------
+ */
+func init_cpu_data_ptr
+       mov     x10, x30
+       mrs     x0, mpidr_el1
+       bl      _cpu_data_by_mpidr
+       msr     tpidr_el3, x0
+       ret     x10
+
+
+/* -----------------------------------------------------------------
+ * cpu_data_t *_cpu_data_by_mpidr(uint64_t mpidr)
+ *
+ * Return the cpu_data structure for the CPU with given MPIDR
+ *
+ * This can be called without a valid stack. It assumes that
+ * platform_get_core_pos() does not clobber register x9.
+ * clobbers: x0, x1, x9
+ * -----------------------------------------------------------------
+ */
+func _cpu_data_by_mpidr
+       mov     x9, x30
+       bl      platform_get_core_pos
+       mov     x30, x9
+       b       _cpu_data_by_index
+
+
+/* -----------------------------------------------------------------
+ * cpu_data_t *_cpu_data_by_index(uint32_t cpu_index)
+ *
+ * Return the cpu_data structure for the CPU with given linear index
+ *
+ * This can be called without a valid stack.
+ * clobbers: x0, x1
+ * -----------------------------------------------------------------
+ */
+func _cpu_data_by_index
+       adr     x1, percpu_data
+       add     x0, x1, x0, LSL #CPU_DATA_LOG2SIZE
+       ret
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
new file mode 100644 (file)
index 0000000..68fe256
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <context.h>
+#include <cpu_data.h>
+#include <plat_macros.S>
+#include <platform_def.h>
+
+       .globl  report_unhandled_exception
+       .globl  report_unhandled_interrupt
+       .globl  el3_panic
+
+#if CRASH_REPORTING
+#define REG_SIZE       0x8
+
+       /* ------------------------------------------------------
+        * 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", "fpexc32_el2", "sp_el0", ""
+
+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
+
+       /*
+        * 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], #REG_SIZE
+       bl      asm_print_hex
+       bl      print_newline
+       b       test_size_list
+exit_size_print:
+       mov     x30, sp
+       ret
+
+       /*
+        * 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, #REG_SIZE * 2]
+       stp     x12, x13, [x0, #REG_SIZE * 4]
+       stp     x14, x15, [x0, #REG_SIZE * 6]
+       b       size_controlled_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, #REG_SIZE]
+       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
+
+
+       /* -----------------------------------------------------
+        * 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
+
+       /* -----------------------------------------------------
+        * 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
+
+       /* ------------------------------------------------------------
+        * 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, #REG_SIZE * 2]
+       stp     x4, x5, [x0, #REG_SIZE * 4]
+       stp     x6, x30, [x0, #REG_SIZE * 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, #REG_SIZE * 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, #REG_SIZE * 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, #REG_SIZE * 2]
+       stp     x20, x21, [x0, #REG_SIZE * 4]
+       stp     x22, x23, [x0, #REG_SIZE * 6]
+       bl      size_controlled_print
+       /* Load the crash buf address */
+       mrs     x0, tpidr_el3
+       stp     x24, x25, [x0]
+       stp     x26, x27, [x0, #REG_SIZE * 2]
+       stp     x28, x29, [x0, #REG_SIZE * 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, fpexc32_el2
+       mrs     x10, sp_el0
+       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 the gic registers */
+       plat_print_gic_regs
+
+       /* Print the interconnect registers */
+       plat_print_interconnect_regs
+
+       /* Done reporting */
+       b       crash_panic
+
+#else  /* CRASH_REPORTING */
+func report_unhandled_exception
+report_unhandled_interrupt:
+       b       crash_panic
+#endif /* CRASH_REPORING */
+
+
+func crash_panic
+       b       crash_panic
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
new file mode 100644 (file)
index 0000000..0a0ea68
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <context.h>
+#include <interrupt_mgmt.h>
+#include <platform_def.h>
+#include <runtime_svc.h>
+
+       .globl  runtime_exceptions
+       .globl  el3_exit
+
+       /* -----------------------------------------------------
+        * Handle SMC exceptions separately from other sync.
+        * exceptions.
+        * -----------------------------------------------------
+        */
+       .macro  handle_sync_exception
+       /* Enable the SError interrupt */
+       msr     daifclr, #DAIF_ABT_BIT
+       msr     daifclr, #DAIF_DBG_BIT
+
+       str     x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+       mrs     x30, esr_el3
+       ubfx    x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
+
+       cmp     x30, #EC_AARCH32_SMC
+       b.eq    smc_handler32
+
+       cmp     x30, #EC_AARCH64_SMC
+       b.eq    smc_handler64
+
+
+       /* -----------------------------------------------------
+        * The following code handles any synchronous exception
+        * that is not an SMC.
+        * -----------------------------------------------------
+        */
+
+       bl      report_unhandled_exception
+       .endm
+
+
+       /* -----------------------------------------------------
+        * This macro handles FIQ or IRQ interrupts i.e. EL3,
+        * S-EL1 and NS interrupts.
+        * -----------------------------------------------------
+        */
+       .macro  handle_interrupt_exception label
+       /* Enable the SError interrupt */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       str     x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+       bl      save_gp_registers
+
+       /* 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 implies that an interrupt was generated
+        * for which there is no handler registered or the interrupt
+        * was routed incorrectly. This is a problem of the framework
+        * so report it as an error.
+        */
+       bl      get_interrupt_type_handler
+       cbz     x0, interrupt_error_\label
+       mov     x21, x0
+
+       mov     x0, #INTR_ID_UNAVAILABLE
+#if IMF_READ_INTERRUPT_ID
+       /*
+        * Read the id of the highest priority pending interrupt. If
+        * no interrupt is asserted then return to where we came from.
+        */
+       mov     x19,  #INTR_ID_UNAVAILABLE
+       bl      plat_ic_get_pending_interrupt_id
+       cmp     x19, x0
+       b.eq    interrupt_exit_\label
+#endif
+
+       /*
+        * Save the EL3 system registers needed to return from
+        * this exception.
+        */
+       mrs     x3, spsr_el3
+       mrs     x4, elr_el3
+       stp     x3, x4, [x20, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+
+       /* 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
+
+       /*
+        * This label signifies a problem with the interrupt management
+        * framework where it is not safe to go back to the instruction
+        * where the interrupt was generated.
+        */
+interrupt_error_\label:
+       bl      report_unhandled_interrupt
+       .endm
+
+
+       .macro save_x18_to_x29_sp_el0
+       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]
+       .endm
+
+       .section        .vectors, "ax"; .align 11
+       .align  7
+runtime_exceptions:
+       /* -----------------------------------------------------
+        * Current EL with _sp_el0 : 0x0 - 0x200
+        * -----------------------------------------------------
+        */
+sync_exception_sp_el0:
+       /* -----------------------------------------------------
+        * We don't expect any synchronous exceptions from EL3
+        * -----------------------------------------------------
+        */
+       bl      report_unhandled_exception
+       check_vector_size sync_exception_sp_el0
+
+       .align  7
+       /* -----------------------------------------------------
+        * EL3 code is non-reentrant. Any asynchronous exception
+        * is a serious error. Loop infinitely.
+        * -----------------------------------------------------
+        */
+irq_sp_el0:
+       bl      report_unhandled_interrupt
+       check_vector_size irq_sp_el0
+
+       .align  7
+fiq_sp_el0:
+       bl      report_unhandled_interrupt
+       check_vector_size fiq_sp_el0
+
+       .align  7
+serror_sp_el0:
+       bl      report_unhandled_exception
+       check_vector_size serror_sp_el0
+
+       /* -----------------------------------------------------
+        * Current EL with SPx: 0x200 - 0x400
+        * -----------------------------------------------------
+        */
+       .align  7
+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.
+        * -----------------------------------------------------
+        */
+       bl      report_unhandled_exception
+       check_vector_size sync_exception_sp_elx
+
+       .align  7
+irq_sp_elx:
+       bl      report_unhandled_interrupt
+       check_vector_size irq_sp_elx
+
+       .align  7
+fiq_sp_elx:
+       bl      report_unhandled_interrupt
+       check_vector_size fiq_sp_elx
+
+       .align  7
+serror_sp_elx:
+       bl      report_unhandled_exception
+       check_vector_size serror_sp_elx
+
+       /* -----------------------------------------------------
+        * Lower EL using AArch64 : 0x400 - 0x600
+        * -----------------------------------------------------
+        */
+       .align  7
+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.
+        * -----------------------------------------------------
+        */
+       handle_sync_exception
+       check_vector_size sync_exception_aarch64
+
+       .align  7
+       /* -----------------------------------------------------
+        * Asynchronous exceptions from lower ELs are not
+        * currently supported. Report their occurrence.
+        * -----------------------------------------------------
+        */
+irq_aarch64:
+       handle_interrupt_exception irq_aarch64
+       check_vector_size irq_aarch64
+
+       .align  7
+fiq_aarch64:
+       handle_interrupt_exception fiq_aarch64
+       check_vector_size fiq_aarch64
+
+       .align  7
+serror_aarch64:
+       bl      report_unhandled_exception
+       check_vector_size serror_aarch64
+
+       /* -----------------------------------------------------
+        * Lower EL using AArch32 : 0x600 - 0x800
+        * -----------------------------------------------------
+        */
+       .align  7
+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.
+        * -----------------------------------------------------
+        */
+       handle_sync_exception
+       check_vector_size sync_exception_aarch32
+
+       .align  7
+       /* -----------------------------------------------------
+        * Asynchronous exceptions from lower ELs are not
+        * currently supported. Report their occurrence.
+        * -----------------------------------------------------
+        */
+irq_aarch32:
+       handle_interrupt_exception irq_aarch32
+       check_vector_size irq_aarch32
+
+       .align  7
+fiq_aarch32:
+       handle_interrupt_exception fiq_aarch32
+       check_vector_size fiq_aarch32
+
+       .align  7
+serror_aarch32:
+       bl      report_unhandled_exception
+       check_vector_size serror_aarch32
+
+       .align  7
+
+       /* -----------------------------------------------------
+        * 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
+
+       /* -----------------------------------------------------
+        * Since we're are coming from aarch32, x8-x18 need to
+        * be saved as per SMC32 calling convention. If a lower
+        * EL in aarch64 is making an SMC32 call then it must
+        * have saved x8-x17 already therein.
+        * -----------------------------------------------------
+        */
+       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]
+
+       /* x4-x7, x18, sp_el0 are saved below */
+
+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 Hence save x5-x7. Note that x4
+        * only needs to be preserved for AArch32 callers but we
+        * do it for AArch64 callers as well for convenience
+        * -----------------------------------------------------
+        */
+       stp     x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
+       stp     x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
+
+       /* Save rest of the gpregs and sp_el0*/
+       save_x18_to_x29_sp_el0
+
+       mov     x5, xzr
+       mov     x6, sp
+
+       /* 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
+
+       adr     x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)
+
+       /* Load descriptor index from array of indices */
+       adr     x14, rt_svc_descs_indices
+       ldrb    w15, [x14, x16]
+
+       /* -----------------------------------------------------
+        * 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]
+
+       /*
+        * Any index greater than 127 is invalid. Check bit 7 for
+        * a valid index
+        */
+       tbnz    w15, 7, smc_unknown
+
+       /* Switch to SP_EL0 */
+       msr     spsel, #0
+
+       /* -----------------------------------------------------
+        * Get the descriptor using the index
+        * x11 = (base + off), x15 = index
+        *
+        * handler = (base + off) + (index << log2(size))
+        * -----------------------------------------------------
+        */
+       lsl     w10, w15, #RT_SVC_SIZE_LOG2
+       ldr     x15, [x11, w10, uxtw]
+
+       /* -----------------------------------------------------
+        * 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
+
+       /* -----------------------------------------------------
+        * This routine assumes that the SP_EL3 is pointing to
+        * a valid context structure from where the gp regs and
+        * other special registers can be retrieved.
+        *
+        * Keep it in the same section as smc_handler as this
+        * function uses a fall-through to el3_exit
+        * -----------------------------------------------------
+        */
+el3_exit: ; .type el3_exit, %function
+       /* -----------------------------------------------------
+        * Save the current SP_EL0 i.e. the EL3 runtime stack
+        * which will be used for handling the next SMC. Then
+        * switch to SP_EL3
+        * -----------------------------------------------------
+        */
+       mov     x17, sp
+       msr     spsel, #1
+       str     x17, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
+
+       /* -----------------------------------------------------
+        * Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET
+        * -----------------------------------------------------
+        */
+       ldr     x18, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+       ldp     x16, x17, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+       msr     scr_el3, x18
+       msr     spsr_el3, x16
+       msr     elr_el3, x17
+
+       /* Restore saved general purpose registers and return */
+       b       restore_gp_registers_eret
+
+smc_unknown:
+       /*
+        * Here we restore x4-x18 regardless of where we came from. AArch32
+        * callers will find the registers contents unchanged, but AArch64
+        * callers will find the registers modified (with stale earlier NS
+        * content). Either way, we aren't leaking any secure information
+        * through them
+        */
+       mov     w0, #SMC_UNK
+       b       restore_gp_registers_callee_eret
+
+smc_prohibited:
+       ldr     x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+       mov     w0, #SMC_UNK
+       eret
+
+rt_svc_fw_critical_error:
+       msr     spsel, #1 /* Switch to SP_ELx */
+       bl      report_unhandled_exception
+
+       /* -----------------------------------------------------
+        * The following functions are used to saved and restore
+        * all the general pupose registers. Ideally we would
+        * only save and restore the callee saved registers when
+        * a world switch occurs but that type of implementation
+        * is more complex. So currently we will always save and
+        * restore these registers on entry and exit of EL3.
+        * These are not macros to ensure their invocation fits
+        * within the 32 instructions per exception vector.
+        * -----------------------------------------------------
+        */
+func save_gp_registers
+       stp     x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+       stp     x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+       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]
+       save_x18_to_x29_sp_el0
+       ret
+
+func restore_gp_registers_eret
+       ldp     x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+       ldp     x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+
+restore_gp_registers_callee_eret:
+       ldp     x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
+       ldp     x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
+       ldp     x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
+       ldp     x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
+       ldp     x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
+       ldp     x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
+       ldp     x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
+       ldp     x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
+       ldp     x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
+       ldp     x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
+       ldp     x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
+       ldp     x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
+       ldp     x30, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+       msr     sp_el0, x17
+       ldp     x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
+       eret
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
new file mode 100644 (file)
index 0000000..3327f31
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.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
+}
+
+
+SECTIONS
+{
+    . = BL31_BASE;
+    ASSERT(. == ALIGN(4096),
+           "BL31_BASE address is not aligned on a page boundary.")
+
+    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__ = .;
+
+        /*
+         * 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_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(4096);
+        __RO_END__ = .;
+    } >RAM
+
+    ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
+           "cpu_ops not defined for this platform.")
+
+    .data . : {
+        __DATA_START__ = .;
+        *(.data*)
+        __DATA_END__ = .;
+    } >RAM
+
+#ifdef BL31_PROGBITS_LIMIT
+    ASSERT(. <= BL31_PROGBITS_LIMIT, "BL3-1 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 must be 16-byte aligned.
+     */
+    .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 and eliminates the unecessary zero init
+     */
+    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(4096) {
+        __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(4096);
+        __COHERENT_RAM_END__ = .;
+    } >RAM
+#endif
+
+    __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, "BL3-1 image has exceeded its limit.")
+}
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
new file mode 100644 (file)
index 0000000..4c25a60
--- /dev/null
@@ -0,0 +1,77 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+BL31_SOURCES           +=      bl31/bl31_main.c                                \
+                               bl31/context_mgmt.c                             \
+                               bl31/cpu_data_array.c                           \
+                               bl31/runtime_svc.c                              \
+                               bl31/interrupt_mgmt.c                           \
+                               bl31/aarch64/bl31_arch_setup.c                  \
+                               bl31/aarch64/bl31_entrypoint.S                  \
+                               bl31/aarch64/context.S                          \
+                               bl31/aarch64/cpu_data.S                         \
+                               bl31/aarch64/runtime_exceptions.S               \
+                               bl31/aarch64/crash_reporting.S                  \
+                               lib/cpus/aarch64/cpu_helpers.S                  \
+                               lib/locks/exclusive/spinlock.S                  \
+                               services/std_svc/std_svc_setup.c                \
+                               services/std_svc/psci/psci_afflvl_off.c         \
+                               services/std_svc/psci/psci_afflvl_on.c          \
+                               services/std_svc/psci/psci_afflvl_suspend.c     \
+                               services/std_svc/psci/psci_common.c             \
+                               services/std_svc/psci/psci_entry.S              \
+                               services/std_svc/psci/psci_helpers.S            \
+                               services/std_svc/psci/psci_main.c               \
+                               services/std_svc/psci/psci_setup.c              \
+                               services/std_svc/psci/psci_system_off.c
+
+ifeq (${USE_COHERENT_MEM}, 1)
+BL31_SOURCES           +=      lib/locks/bakery/bakery_lock_coherent.c
+else
+BL31_SOURCES           +=      lib/locks/bakery/bakery_lock_normal.c
+endif
+
+BL31_LINKERFILE                :=      bl31/bl31.ld.S
+
+# Flag used by the generic interrupt management framework to  determine if
+# upon the assertion of an interrupt, it should pass the interrupt id or not
+IMF_READ_INTERRUPT_ID  :=      0
+
+$(eval $(call assert_boolean,IMF_READ_INTERRUPT_ID))
+$(eval $(call add_define,IMF_READ_INTERRUPT_ID))
+
+# Flag used to inidicate if Crash reporting via console should be included
+# in BL3-1. This defaults to being present in DEBUG builds only
+ifndef CRASH_REPORTING
+CRASH_REPORTING                :=      $(DEBUG)
+endif
+
+$(eval $(call assert_boolean,CRASH_REPORTING))
+$(eval $(call add_define,CRASH_REPORTING))
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
new file mode 100644 (file)
index 0000000..19f3774
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <platform.h>
+#include <runtime_svc.h>
+#include <string.h>
+
+/*******************************************************************************
+ * 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;
+
+/*******************************************************************************
+ * 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("BL3-1: %s\n", version_string);
+       NOTICE("BL3-1: %s\n", build_message);
+
+       /* Perform remaining generic architectural setup from EL3 */
+       bl31_arch_setup();
+
+       /* Perform platform setup in BL1 */
+       bl31_platform_setup();
+
+       /* Initialise helper libraries */
+       bl31_lib_init();
+
+       /* Initialize the runtime services e.g. psci */
+       INFO("BL3-1: Initializing runtime services\n");
+       runtime_svc_init();
+
+       /* Clean caches before re-entering normal world */
+       dcsw_op_all(DCCSW);
+
+       /*
+        * 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("BL3-1: Initializing BL3-2\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();
+}
+
+/*******************************************************************************
+ * 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;
+
+       /* 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("BL3-1: Preparing for EL3 exit to %s world\n",
+               (image_type == SECURE) ? "secure" : "normal");
+       INFO("BL3-1: Next image address = 0x%llx\n",
+               (unsigned long long) next_image_info->pc);
+       INFO("BL3-1: Next image spsr = 0x%x\n", next_image_info->spsr);
+       cm_init_context(read_mpidr_el1(), 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;
+}
diff --git a/bl31/context_mgmt.c b/bl31/context_mgmt.c
new file mode 100644 (file)
index 0000000..6f27176
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <cpu_data.h>
+#include <interrupt_mgmt.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <runtime_svc.h>
+#include <string.h>
+
+
+/*******************************************************************************
+ * Context management library initialisation routine. This library is used by
+ * runtime services to share pointers to 'cpu_context' structures for the secure
+ * and non-secure states. Management of the structures and their associated
+ * memory is not done by the context management library e.g. the PSCI service
+ * manages the cpu context used for entry from and exit to the non-secure state.
+ * The Secure payload dispatcher service manages the context(s) corresponding to
+ * the secure state. It also uses this library to get access to the non-secure
+ * state cpu context pointers.
+ * Lastly, this library provides the api to make SP_EL3 point to the cpu context
+ * which will used for programming an entry into a lower EL. The same context
+ * will used to save state upon exception entry from that EL.
+ ******************************************************************************/
+void cm_init(void)
+{
+       /*
+        * The context management library has only global data to intialize, but
+        * that will be done when the BSS is zeroed out
+        */
+}
+
+/*******************************************************************************
+ * 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));
+
+       return get_cpu_data_by_mpidr(mpidr, 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 MPIDR
+ ******************************************************************************/
+void cm_set_context_by_mpidr(uint64_t mpidr, void *context, uint32_t security_state)
+{
+       assert(sec_state_is_valid(security_state));
+
+       set_cpu_data_by_mpidr(mpidr, cpu_context[security_state], context);
+}
+
+/*******************************************************************************
+ * This function is used to program the context that's used for exception
+ * return. This initializes the SP_EL3 to a pointer to a 'cpu_context' set for
+ * the required security state
+ ******************************************************************************/
+static inline void cm_set_next_context(void *context)
+{
+#if DEBUG
+       uint64_t sp_mode;
+
+       /*
+        * Check that this function is called with SP_EL0 as the stack
+        * pointer
+        */
+       __asm__ volatile("mrs   %0, SPSel\n"
+                        : "=r" (sp_mode));
+
+       assert(sp_mode == MODE_SP_EL0);
+#endif
+
+       __asm__ volatile("msr   spsel, #1\n"
+                        "mov   sp, %0\n"
+                        "msr   spsel, #0\n"
+                        : : "r" (context));
+}
+
+/*******************************************************************************
+ * The following function initializes a cpu_context for the current CPU for
+ * first use, and sets the initial entrypoint state as specified by the
+ * entry_point_info structure.
+ *
+ * The security state to initialize is determined by the SECURE attribute
+ * of the entry_point_info. The function returns a pointer to the initialized
+ * context and sets this as the next context to return to.
+ *
+ * The EE and ST attributes are used to configure the endianess and secure
+ * timer availability for the new excution context.
+ *
+ * To prepare the register state for entry call cm_prepare_el3_exit() and
+ * el3_exit(). For Secure-EL1 cm_prepare_el3_exit() is equivalent to
+ * cm_e1_sysreg_context_restore().
+ ******************************************************************************/
+void cm_init_context(uint64_t mpidr, const entry_point_info_t *ep)
+{
+       uint32_t security_state;
+       cpu_context_t *ctx;
+       uint32_t scr_el3;
+       el3_state_t *state;
+       gp_regs_t *gp_regs;
+       unsigned long sctlr_elx;
+
+       security_state = GET_SECURITY_STATE(ep->h.attr);
+       ctx = cm_get_context_by_mpidr(mpidr, security_state);
+       assert(ctx);
+
+       /* Clear any residual register values from the context */
+       memset(ctx, 0, sizeof(*ctx));
+
+       /*
+        * Base the context SCR on the current value, adjust for entry point
+        * specific requirements and set trap bits from the IMF
+        * TODO: provide the base/global SCR bits using another mechanism?
+        */
+       scr_el3 = read_scr();
+       scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT |
+                       SCR_ST_BIT | SCR_HCE_BIT);
+
+       if (security_state != SECURE)
+               scr_el3 |= SCR_NS_BIT;
+
+       if (GET_RW(ep->spsr) == MODE_RW_64)
+               scr_el3 |= SCR_RW_BIT;
+
+       if (EP_GET_ST(ep->h.attr))
+               scr_el3 |= SCR_ST_BIT;
+
+       scr_el3 |= get_scr_el3_from_routing_model(security_state);
+
+       /*
+        * Set up SCTLR_ELx for the target exception level:
+        * EE bit is taken from the entrpoint attributes
+        * M, C and I bits must be zero (as required by PSCI specification)
+        *
+        * The target exception level is based on the spsr mode requested.
+        * If execution is requested to EL2 or hyp mode, HVC is enabled
+        * via SCR_EL3.HCE.
+        *
+        * Always compute the SCTLR_EL1 value and save in the cpu_context
+        * - the EL2 registers are set up by cm_preapre_ns_entry() as they
+        * are not part of the stored cpu_context
+        *
+        * TODO: In debug builds the spsr should be validated and checked
+        * against the CPU support, security state, endianess and pc
+        */
+       sctlr_elx = EP_GET_EE(ep->h.attr) ? SCTLR_EE_BIT : 0;
+       if (GET_RW(ep->spsr) == MODE_RW_64)
+               sctlr_elx |= SCTLR_EL1_RES1;
+       else
+               sctlr_elx |= SCTLR_AARCH32_EL1_RES1;
+       write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
+
+       if ((GET_RW(ep->spsr) == MODE_RW_64
+            && GET_EL(ep->spsr) == MODE_EL2)
+           || (GET_RW(ep->spsr) != MODE_RW_64
+               && GET_M32(ep->spsr) == MODE32_hyp)) {
+               scr_el3 |= SCR_HCE_BIT;
+       }
+
+       /* Populate EL3 state so that we've the right context before doing ERET */
+       state = get_el3state_ctx(ctx);
+       write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
+       write_ctx_reg(state, CTX_ELR_EL3, ep->pc);
+       write_ctx_reg(state, CTX_SPSR_EL3, ep->spsr);
+
+       /*
+        * Store the X0-X7 value from the entrypoint into the context
+        * Use memcpy as we are in control of the layout of the structures
+        */
+       gp_regs = get_gpregs_ctx(ctx);
+       memcpy(gp_regs, (void *)&ep->args, sizeof(aapcs64_params_t));
+}
+
+/*******************************************************************************
+ * Prepare the CPU system registers for first entry into secure or normal world
+ *
+ * If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized
+ * If execution is requested to non-secure EL1 or svc mode, and the CPU supports
+ * EL2 then EL2 is disabled by configuring all necessary EL2 registers.
+ * For all entries, the EL1 registers are initialized from the cpu_context
+ ******************************************************************************/
+void cm_prepare_el3_exit(uint32_t security_state)
+{
+       uint32_t sctlr_elx, scr_el3, cptr_el2;
+       cpu_context_t *ctx = cm_get_context(security_state);
+
+       assert(ctx);
+
+       if (security_state == NON_SECURE) {
+               scr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3);
+               if (scr_el3 & SCR_HCE_BIT) {
+                       /* Use SCTLR_EL1.EE value to initialise sctlr_el2 */
+                       sctlr_elx = read_ctx_reg(get_sysregs_ctx(ctx),
+                                                CTX_SCTLR_EL1);
+                       sctlr_elx &= ~SCTLR_EE_BIT;
+                       sctlr_elx |= SCTLR_EL2_RES1;
+                       write_sctlr_el2(sctlr_elx);
+               } else if (read_id_aa64pfr0_el1() &
+                          (ID_AA64PFR0_ELX_MASK << ID_AA64PFR0_EL2_SHIFT)) {
+                       /* EL2 present but unused, need to disable safely */
+
+                       /* HCR_EL2 = 0, except RW bit set to match SCR_EL3 */
+                       write_hcr_el2((scr_el3 & SCR_RW_BIT) ? HCR_RW_BIT : 0);
+
+                       /* SCTLR_EL2 : can be ignored when bypassing */
+
+                       /* CPTR_EL2 : disable all traps TCPAC, TTA, TFP */
+                       cptr_el2 = read_cptr_el2();
+                       cptr_el2 &= ~(TCPAC_BIT | TTA_BIT | TFP_BIT);
+                       write_cptr_el2(cptr_el2);
+
+                       /* Enable EL1 access to timer */
+                       write_cnthctl_el2(EL1PCEN_BIT | EL1PCTEN_BIT);
+
+                       /* Reset CNTVOFF_EL2 */
+                       write_cntvoff_el2(0);
+
+                       /* Set VPIDR, VMPIDR to match MIDR, MPIDR */
+                       write_vpidr_el2(read_midr_el1());
+                       write_vmpidr_el2(read_mpidr_el1());
+               }
+       }
+
+       el1_sysregs_context_restore(get_sysregs_ctx(ctx));
+
+       cm_set_next_context(ctx);
+}
+
+/*******************************************************************************
+ * The next four functions are used by runtime services to save and restore
+ * EL1 context on the 'cpu_context' structure for the specified security
+ * state.
+ ******************************************************************************/
+void cm_el1_sysregs_context_save(uint32_t security_state)
+{
+       cpu_context_t *ctx;
+
+       ctx = cm_get_context(security_state);
+       assert(ctx);
+
+       el1_sysregs_context_save(get_sysregs_ctx(ctx));
+}
+
+void cm_el1_sysregs_context_restore(uint32_t security_state)
+{
+       cpu_context_t *ctx;
+
+       ctx = cm_get_context(security_state);
+       assert(ctx);
+
+       el1_sysregs_context_restore(get_sysregs_ctx(ctx));
+}
+
+/*******************************************************************************
+ * This function populates ELR_EL3 member of 'cpu_context' pertaining to the
+ * given security state with the given entrypoint
+ ******************************************************************************/
+void cm_set_elr_el3(uint32_t security_state, uint64_t entrypoint)
+{
+       cpu_context_t *ctx;
+       el3_state_t *state;
+
+       ctx = cm_get_context(security_state);
+       assert(ctx);
+
+       /* Populate EL3 state so that ERET jumps to the correct entry */
+       state = get_el3state_ctx(ctx);
+       write_ctx_reg(state, CTX_ELR_EL3, entrypoint);
+}
+
+/*******************************************************************************
+ * This function populates ELR_EL3 and SPSR_EL3 members of 'cpu_context'
+ * pertaining to the given security state
+ ******************************************************************************/
+void cm_set_elr_spsr_el3(uint32_t security_state,
+                        uint64_t entrypoint, uint32_t spsr)
+{
+       cpu_context_t *ctx;
+       el3_state_t *state;
+
+       ctx = cm_get_context(security_state);
+       assert(ctx);
+
+       /* Populate EL3 state so that ERET jumps to the correct entry */
+       state = get_el3state_ctx(ctx);
+       write_ctx_reg(state, CTX_ELR_EL3, entrypoint);
+       write_ctx_reg(state, CTX_SPSR_EL3, spsr);
+}
+
+/*******************************************************************************
+ * This function updates a single bit in the SCR_EL3 member of the 'cpu_context'
+ * pertaining to the given security state using the value and bit position
+ * specified in the parameters. It preserves all other bits.
+ ******************************************************************************/
+void cm_write_scr_el3_bit(uint32_t security_state,
+                         uint32_t bit_pos,
+                         uint32_t value)
+{
+       cpu_context_t *ctx;
+       el3_state_t *state;
+       uint32_t scr_el3;
+
+       ctx = cm_get_context(security_state);
+       assert(ctx);
+
+       /* Ensure that the bit position is a valid one */
+       assert((1 << bit_pos) & SCR_VALID_BIT_MASK);
+
+       /* Ensure that the 'value' is only a bit wide */
+       assert(value <= 1);
+
+       /*
+        * Get the SCR_EL3 value from the cpu context, clear the desired bit
+        * and set it to its new value.
+        */
+       state = get_el3state_ctx(ctx);
+       scr_el3 = read_ctx_reg(state, CTX_SCR_EL3);
+       scr_el3 &= ~(1 << bit_pos);
+       scr_el3 |= value << bit_pos;
+       write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
+}
+
+/*******************************************************************************
+ * This function retrieves SCR_EL3 member of 'cpu_context' pertaining to the
+ * given security state.
+ ******************************************************************************/
+uint32_t cm_get_scr_el3(uint32_t security_state)
+{
+       cpu_context_t *ctx;
+       el3_state_t *state;
+
+       ctx = cm_get_context(security_state);
+       assert(ctx);
+
+       /* Populate EL3 state so that ERET jumps to the correct entry */
+       state = get_el3state_ctx(ctx);
+       return read_ctx_reg(state, CTX_SCR_EL3);
+}
+
+/*******************************************************************************
+ * This function is used to program the context that's used for exception
+ * return. This initializes the SP_EL3 to a pointer to a 'cpu_context' set for
+ * the required security state
+ ******************************************************************************/
+void cm_set_next_eret_context(uint32_t security_state)
+{
+       cpu_context_t *ctx;
+
+       ctx = cm_get_context(security_state);
+       assert(ctx);
+
+       cm_set_next_context(ctx);
+}
diff --git a/bl31/cpu_data_array.c b/bl31/cpu_data_array.c
new file mode 100644 (file)
index 0000000..4cba118
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cassert.h>
+#include <cpu_data.h>
+#include <platform_def.h>
+
+/* The per_cpu_ptr_cache_t space allocation */
+cpu_data_t percpu_data[PLATFORM_CORE_COUNT];
diff --git a/bl31/interrupt_mgmt.c b/bl31/interrupt_mgmt.c
new file mode 100644 (file)
index 0000000..5478902
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <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. EL3 interrupts are currently not
+ * supported.
+ ******************************************************************************/
+static int32_t validate_interrupt_type(uint32_t type)
+{
+       if (type == INTR_TYPE_EL3)
+               return -ENOTSUP;
+
+       if (type != INTR_TYPE_S_EL1 && type != INTR_TYPE_NS)
+               return -EINVAL;
+
+       return 0;
+}
+
+/*******************************************************************************
+* 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);
+
+       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;
+       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;
+}
+
diff --git a/bl31/runtime_svc.c b/bl31/runtime_svc.c
new file mode 100644 (file)
index 0000000..c33748f
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <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.
+ ******************************************************************************/
+#define RT_SVC_DESCS_START     ((uint64_t) (&__RT_SVC_DESCS_START__))
+#define RT_SVC_DESCS_END       ((uint64_t) (&__RT_SVC_DESCS_END__))
+uint8_t rt_svc_descs_indices[MAX_RT_SVCS];
+static rt_svc_desc_t *rt_svc_descs;
+
+/*******************************************************************************
+ * Simple routine to sanity check a runtime service descriptor before using it
+ ******************************************************************************/
+static int32_t validate_rt_svc_desc(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 (desc->call_type != SMC_TYPE_FAST && desc->call_type != SMC_TYPE_STD)
+               return -EINVAL;
+
+       /* 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)
+{
+       int32_t rc = 0;
+       uint32_t index, start_idx, end_idx;
+       uint64_t rt_svc_descs_num;
+
+       /* If no runtime services are implemented then simply bail out */
+       rt_svc_descs_num = RT_SVC_DESCS_END - RT_SVC_DESCS_START;
+       rt_svc_descs_num /= sizeof(rt_svc_desc_t);
+       if (rt_svc_descs_num == 0)
+               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_descs_num; 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(&rt_svc_descs[index]);
+               if (rc) {
+                       ERROR("Invalid runtime service descriptor 0x%x (%s)\n",
+                                       &rt_svc_descs[index],
+                                       rt_svc_descs[index].name);
+                       goto error;
+               }
+
+               /*
+                * The runtime service may have seperate rt_svc_desc_t
+                * for its fast smc and standard 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 (rt_svc_descs[index].init) {
+                       rc = rt_svc_descs[index].init();
+                       if (rc) {
+                               ERROR("Error initializing runtime service %s\n",
+                                               rt_svc_descs[index].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.
+                */
+               start_idx = get_unique_oen(rt_svc_descs[index].start_oen,
+                               rt_svc_descs[index].call_type);
+               end_idx = get_unique_oen(rt_svc_descs[index].end_oen,
+                               rt_svc_descs[index].call_type);
+
+               for (; start_idx <= end_idx; start_idx++)
+                       rt_svc_descs_indices[start_idx] = index;
+       }
+
+       return;
+error:
+       panic();
+}
diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S
new file mode 100644 (file)
index 0000000..2714282
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <tsp.h>
+#include <xlat_tables.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
+
+       .section        .text, "ax"
+       .align 3
+
+func tsp_entrypoint
+
+       /* ---------------------------------------------
+        * 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
+
+       /* ---------------------------------------------
+        * 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      zeromem16
+
+#if USE_COHERENT_MEM
+       ldr     x0, =__COHERENT_RAM_START__
+       ldr     x1, =__COHERENT_RAM_UNALIGNED_SIZE__
+       bl      zeromem16
+#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.
+        * --------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_set_stack
+
+       /* ---------------------------------------------
+        * 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
+
+
+       /* -------------------------------------------
+        * Table of entrypoint vectors provided to the
+        * TSPD for the various entrypoints
+        * -------------------------------------------
+        */
+func tsp_vector_table
+       b       tsp_std_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_fiq_entry
+       b       tsp_system_off_entry
+       b       tsp_system_reset_entry
+
+       /*---------------------------------------------
+        * 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
+
+       /*---------------------------------------------
+        * 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
+
+       /*---------------------------------------------
+        * 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
+
+       /*---------------------------------------------
+        * 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.
+        * --------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_set_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
+
+       /*---------------------------------------------
+        * 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
+
+       /*---------------------------------------------
+        * This entrypoint is used by the TSPD to pass
+        * control for handling a pending S-EL1 FIQ.
+        * 'x0' contains a magic number which indicates
+        * this. TSPD expects control to be handed back
+        * at the end of FIQ 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_FIQ
+        * ---------------------------------------------
+        */
+func   tsp_fiq_entry
+#if DEBUG
+       mov     x2, #(TSP_HANDLE_FIQ_AND_RETURN & ~0xffff)
+       movk    x2, #(TSP_HANDLE_FIQ_AND_RETURN &  0xffff)
+       cmp     x0, x2
+       b.ne    tsp_fiq_entry_panic
+#endif
+       /*---------------------------------------------
+        * Save any previous context needed to perform
+        * an exception return from S-EL1 e.g. context
+        * from a previous IRQ. Update statistics and
+        * handle the FIQ 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. A non-zero return value from the
+        * fiq handler is an error.
+        * ---------------------------------------------
+        */
+       save_eret_context x2 x3
+       bl      tsp_update_sync_fiq_stats
+       bl      tsp_fiq_handler
+       cbnz    x0, tsp_fiq_entry_panic
+       restore_eret_context x2 x3
+       mov     x0, #(TSP_HANDLED_S_EL1_FIQ & ~0xffff)
+       movk    x0, #(TSP_HANDLED_S_EL1_FIQ &  0xffff)
+       smc     #0
+
+tsp_fiq_entry_panic:
+       b       tsp_fiq_entry_panic
+
+       /*---------------------------------------------
+        * 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
+tsp_cpu_resume_panic:
+       b       tsp_cpu_resume_panic
+
+       /*---------------------------------------------
+        * 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
+tsp_fast_smc_entry_panic:
+       b       tsp_fast_smc_entry_panic
+
+       /*---------------------------------------------
+        * This entrypoint is used by the TSPD to ask
+        * the TSP to service a std smc request.
+        * We will enable preemption during execution
+        * of tsp_smc_handler.
+        * ---------------------------------------------
+        */
+func tsp_std_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
+tsp_std_smc_entry_panic:
+       b       tsp_std_smc_entry_panic
diff --git a/bl32/tsp/aarch64/tsp_exceptions.S b/bl32/tsp/aarch64/tsp_exceptions.S
new file mode 100644 (file)
index 0000000..4c0d436
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <arch.h>
+#include <tsp.h>
+#include <asm_macros.S>
+
+
+       /* ----------------------------------------------------
+        * 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
+
+       .globl  tsp_exceptions
+
+       /* -----------------------------------------------------
+        * TSP exception handlers.
+        * -----------------------------------------------------
+        */
+       .section        .vectors, "ax"; .align 11
+
+       .align  7
+tsp_exceptions:
+       /* -----------------------------------------------------
+        * Current EL with _sp_el0 : 0x0 - 0x180. No exceptions
+        * are expected and treated as irrecoverable errors.
+        * -----------------------------------------------------
+        */
+sync_exception_sp_el0:
+       wfi
+       b       sync_exception_sp_el0
+       check_vector_size sync_exception_sp_el0
+
+       .align  7
+
+irq_sp_el0:
+       b       irq_sp_el0
+       check_vector_size irq_sp_el0
+
+       .align  7
+fiq_sp_el0:
+       b       fiq_sp_el0
+       check_vector_size fiq_sp_el0
+
+       .align  7
+serror_sp_el0:
+       b       serror_sp_el0
+       check_vector_size serror_sp_el0
+
+
+       /* -----------------------------------------------------
+        * Current EL with SPx: 0x200 - 0x380. Only IRQs/FIQs
+        * are expected and handled
+        * -----------------------------------------------------
+        */
+       .align  7
+sync_exception_sp_elx:
+       wfi
+       b       sync_exception_sp_elx
+       check_vector_size sync_exception_sp_elx
+
+       .align  7
+irq_sp_elx:
+       /* Enable the SError interrupt */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       save_caller_regs_and_lr
+       /* We just update some statistics in the handler */
+       bl      tsp_irq_received
+       /* Hand over control to the normal world to handle the IRQ */
+       smc     #0
+       /* The resume std smc starts from here */
+       restore_caller_regs_and_lr
+       eret
+       check_vector_size irq_sp_elx
+
+       .align  7
+fiq_sp_elx:
+       /* Enable the SError interrupt */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       save_caller_regs_and_lr
+       bl      tsp_fiq_handler
+       cbz     x0, fiq_sp_elx_done
+
+       /*
+        * This FIQ was not targetted to S-EL1 so send it to
+        * the monitor and wait for execution to resume.
+        */
+       smc     #0
+fiq_sp_elx_done:
+       restore_caller_regs_and_lr
+       eret
+       check_vector_size fiq_sp_elx
+
+       .align  7
+serror_sp_elx:
+       b       serror_sp_elx
+       check_vector_size serror_sp_elx
+
+
+       /* -----------------------------------------------------
+        * Lower EL using AArch64 : 0x400 - 0x580. No exceptions
+        * are handled since TSP does not implement a lower EL
+        * -----------------------------------------------------
+        */
+       .align  7
+sync_exception_aarch64:
+       wfi
+       b       sync_exception_aarch64
+       check_vector_size sync_exception_aarch64
+
+       .align  7
+irq_aarch64:
+       b       irq_aarch64
+       check_vector_size irq_aarch64
+
+       .align  7
+fiq_aarch64:
+       b       fiq_aarch64
+       check_vector_size fiq_aarch64
+
+       .align  7
+serror_aarch64:
+       b       serror_aarch64
+       check_vector_size serror_aarch64
+
+
+       /* -----------------------------------------------------
+        * Lower EL using AArch32 : 0x600 - 0x780. No exceptions
+        * handled since the TSP does not implement a lower EL.
+        * -----------------------------------------------------
+        */
+       .align  7
+sync_exception_aarch32:
+       wfi
+       b       sync_exception_aarch32
+       check_vector_size sync_exception_aarch32
+
+       .align  7
+irq_aarch32:
+       b       irq_aarch32
+       check_vector_size irq_aarch32
+
+       .align  7
+fiq_aarch32:
+       b       fiq_aarch32
+       check_vector_size fiq_aarch32
+
+       .align  7
+serror_aarch32:
+       b       serror_aarch32
+       check_vector_size serror_aarch32
+       .align  7
diff --git a/bl32/tsp/aarch64/tsp_request.S b/bl32/tsp/aarch64/tsp_request.S
new file mode 100644 (file)
index 0000000..6aa0873
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <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
+
+       .align 2
+_tsp_fid_get_magic:
+       .word   TSP_GET_ARGS
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
new file mode 100644 (file)
index 0000000..d411ad0
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.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(4096),
+           "BL32_BASE address is not aligned on a page boundary.")
+
+    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(4096);
+        __RO_END__ = .;
+    } >RAM
+
+    .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 must be 16-byte aligned.
+     */
+    .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 and eliminates the unecessary zero init
+     */
+    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(4096) {
+        __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(4096);
+        __COHERENT_RAM_END__ = .;
+    } >RAM
+#endif
+
+    __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, "BL3-2 image has exceeded its limit.")
+}
diff --git a/bl32/tsp/tsp.mk b/bl32/tsp/tsp.mk
new file mode 100644 (file)
index 0000000..f17ef1e
--- /dev/null
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+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/spinlock.S
+
+BL32_LINKERFILE                :=      bl32/tsp/tsp.ld.S
+
+# This flag determines if the TSPD initializes BL3-2 in tspd_init() (synchronous
+# method) or configures BL3-1 to pass control to BL3-2 instead of BL3-3
+# (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 := plat/${PLAT}/tsp/tsp-${PLAT}.mk
+ifeq (,$(wildcard ${TSP_PLAT_MAKEFILE}))
+  $(error TSP is not supported on platform ${PLAT})
+else
+  include ${TSP_PLAT_MAKEFILE}
+endif
diff --git a/bl32/tsp/tsp_interrupt.c b/bl32/tsp/tsp_interrupt.c
new file mode 100644 (file)
index 0000000..7163bad
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <gic_v2.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <tsp.h>
+#include "tsp_private.h"
+
+/*******************************************************************************
+ * This function updates the TSP statistics for FIQs 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 an FIQ.
+ * In the future it will be possible that the TSPD hands over an FIQ to the TSP
+ * but does not expect it to return execution. This statistic will be useful to
+ * distinguish between these two models of synchronous FIQ handling.
+ * The 'elr_el3' parameter contains the address of the instruction in normal
+ * world where this FIQ was generated.
+ ******************************************************************************/
+void tsp_update_sync_fiq_stats(uint32_t type, uint64_t elr_el3)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       tsp_stats[linear_id].sync_fiq_count++;
+       if (type == TSP_HANDLE_FIQ_AND_RETURN)
+               tsp_stats[linear_id].sync_fiq_ret_count++;
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+       spin_lock(&console_lock);
+       VERBOSE("TSP: cpu 0x%x sync fiq request from 0x%llx\n",
+               mpidr, elr_el3);
+       VERBOSE("TSP: cpu 0x%x: %d sync fiq requests, %d sync fiq returns\n",
+               mpidr,
+               tsp_stats[linear_id].sync_fiq_count,
+               tsp_stats[linear_id].sync_fiq_ret_count);
+       spin_unlock(&console_lock);
+#endif
+}
+
+/*******************************************************************************
+ * TSP FIQ handler called as a part of both synchronous and asynchronous
+ * handling of FIQ interrupts. It returns 0 upon successfully handling a S-EL1
+ * FIQ and treats all other FIQs as EL3 interrupts. It assumes that the GIC
+ * architecture version in v2.0 and the secure physical timer interrupt is the
+ * only S-EL1 interrupt that it needs to handle.
+ ******************************************************************************/
+int32_t tsp_fiq_handler(void)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr), 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.
+        */
+       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_EL3_FIQ;
+
+       /*
+        * Handle the interrupt. Also sanity check if it has been preempted by
+        * another secure 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].fiq_count++;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+       spin_lock(&console_lock);
+       VERBOSE("TSP: cpu 0x%x handled fiq %d\n",
+              mpidr, id);
+       VERBOSE("TSP: cpu 0x%x: %d fiq requests\n",
+            mpidr, tsp_stats[linear_id].fiq_count);
+       spin_unlock(&console_lock);
+#endif
+       return 0;
+}
+
+int32_t tsp_irq_received(void)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       tsp_stats[linear_id].irq_count++;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+       spin_lock(&console_lock);
+       VERBOSE("TSP: cpu 0x%x received irq\n", mpidr);
+       VERBOSE("TSP: cpu 0x%x: %d irq requests\n",
+               mpidr, tsp_stats[linear_id].irq_count);
+       spin_unlock(&console_lock);
+#endif
+       return TSP_PREEMPTED;
+}
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
new file mode 100644 (file)
index 0000000..c6000e1
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <platform_tsp.h>
+#include <spinlock.h>
+#include <tsp.h>
+#include "tsp_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __BL32_END__;
+
+/*******************************************************************************
+ * 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 BL32 memory footprint starts with an RO sections and ends
+ * with the linker symbol __BL32_END__. Use it to find the memory size
+ ******************************************************************************/
+#define BL32_TOTAL_BASE (unsigned long)(&__RO_START__)
+
+#define BL32_TOTAL_LIMIT (unsigned long)(&__BL32_END__)
+
+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)
+{
+       uint64_t mpidr = read_mpidr();
+       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 = platform_get_core_pos(mpidr);
+       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%x\n", (unsigned long)BL32_TOTAL_BASE);
+       INFO("TSP: Total memory size : 0x%x bytes\n",
+                        (unsigned long)(BL32_TOTAL_LIMIT - BL32_TOTAL_BASE));
+
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       /* 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%x: %d smcs, %d erets %d cpu on requests\n", 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)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       /* 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%x turned on\n", mpidr);
+       INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", 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)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       /*
+        * 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%x off request\n", mpidr);
+       INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu off requests\n", 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)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       /*
+        * 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%x: %d smcs, %d erets %d cpu suspend requests\n",
+               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 suspend_level,
+                             uint64_t arg1,
+                             uint64_t arg2,
+                             uint64_t arg3,
+                             uint64_t arg4,
+                             uint64_t arg5,
+                             uint64_t arg6,
+                             uint64_t arg7)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       /* 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%x resumed. suspend level %d\n",
+               mpidr, suspend_level);
+       INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n",
+               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)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       /* 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%x SYSTEM_OFF request\n", mpidr);
+       INFO("TSP: cpu 0x%x: %d smcs, %d erets requests\n", 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)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       /* 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%x SYSTEM_RESET request\n", mpidr);
+       INFO("TSP: cpu 0x%x: %d smcs, %d erets requests\n", 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];
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+
+       /* Update this cpu's statistics */
+       tsp_stats[linear_id].smc_count++;
+       tsp_stats[linear_id].eret_count++;
+
+       INFO("TSP: cpu 0x%x received %s smc 0x%x\n", read_mpidr(),
+               ((func >> 31) & 1) == 1 ? "fast" : "standard",
+               func);
+       INFO("TSP: cpu 0x%x: %d smcs, %d erets\n", 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);
+}
+
diff --git a/bl32/tsp/tsp_private.h b/bl32/tsp/tsp_private.h
new file mode 100644 (file)
index 0000000..39fb5f6
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __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 {
+       uint32_t fiq_count;             /* Number of FIQs on this cpu */
+       uint32_t irq_count;             /* Number of IRQs on this cpu */
+       uint32_t sync_fiq_count;        /* Number of sync. fiqs on this cpu */
+       uint32_t sync_fiq_ret_count;    /* Number of fiq returns on this cpu */
+       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 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_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);
+
+/* FIQ management functions */
+void tsp_update_sync_fiq_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;
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __TSP_PRIVATE_H__ */
+
diff --git a/bl32/tsp/tsp_timer.c b/bl32/tsp/tsp_timer.c
new file mode 100644 (file)
index 0000000..f196021
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch_helpers.h>
+#include <assert.h>
+#include <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 = platform_get_core_pos(read_mpidr());
+
+       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 = platform_get_core_pos(read_mpidr());
+
+       write_cntps_cval_el1(pcpu_timer_context[linear_id].cval);
+       write_cntps_ctl_el1(pcpu_timer_context[linear_id].ctl);
+}
diff --git a/common/aarch64/debug.S b/common/aarch64/debug.S
new file mode 100644 (file)
index 0000000..fcf5f26
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+       .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 ASM_ASSERTION
+.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
+       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
+_assert_loop:
+       b       _assert_loop
+#endif
+
+/*
+ * 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
+
+/*
+ * This function prints a hexadecimal number in x4.
+ * In: x4 = the hexadecimal to print.
+ * Clobber: x30, x0, x5, x1, x2, x3
+ */
+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
+
+       /***********************************************************
+        * 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_loop
+       /* 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
+_panic_loop:
+       b       _panic_loop
+
diff --git a/common/aarch64/early_exceptions.S b/common/aarch64/early_exceptions.S
new file mode 100644 (file)
index 0000000..90f5421
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm_macros.S>
+#include <runtime_svc.h>
+
+       .globl  early_exceptions
+
+       .section        .vectors, "ax"; .align 11
+
+       /* -----------------------------------------------------
+        * Very simple stackless exception handlers used by BL2
+        * and BL3-1 bootloader stages. BL3-1 uses them before
+        * stacks are setup. BL2 uses them throughout.
+        * -----------------------------------------------------
+        */
+       .align  7
+early_exceptions:
+       /* -----------------------------------------------------
+        * Current EL with SP0 : 0x0 - 0x180
+        * -----------------------------------------------------
+        */
+SynchronousExceptionSP0:
+       mov     x0, #SYNC_EXCEPTION_SP_EL0
+       bl      plat_report_exception
+       b       SynchronousExceptionSP0
+       check_vector_size SynchronousExceptionSP0
+
+       .align  7
+IrqSP0:
+       mov     x0, #IRQ_SP_EL0
+       bl      plat_report_exception
+       b       IrqSP0
+       check_vector_size IrqSP0
+
+       .align  7
+FiqSP0:
+       mov     x0, #FIQ_SP_EL0
+       bl      plat_report_exception
+       b       FiqSP0
+       check_vector_size FiqSP0
+
+       .align  7
+SErrorSP0:
+       mov     x0, #SERROR_SP_EL0
+       bl      plat_report_exception
+       b       SErrorSP0
+       check_vector_size SErrorSP0
+
+       /* -----------------------------------------------------
+        * Current EL with SPx: 0x200 - 0x380
+        * -----------------------------------------------------
+        */
+       .align  7
+SynchronousExceptionSPx:
+       mov     x0, #SYNC_EXCEPTION_SP_ELX
+       bl      plat_report_exception
+       b       SynchronousExceptionSPx
+       check_vector_size SynchronousExceptionSPx
+
+       .align  7
+IrqSPx:
+       mov     x0, #IRQ_SP_ELX
+       bl      plat_report_exception
+       b       IrqSPx
+       check_vector_size IrqSPx
+
+       .align  7
+FiqSPx:
+       mov     x0, #FIQ_SP_ELX
+       bl      plat_report_exception
+       b       FiqSPx
+       check_vector_size FiqSPx
+
+       .align  7
+SErrorSPx:
+       mov     x0, #SERROR_SP_ELX
+       bl      plat_report_exception
+       b       SErrorSPx
+       check_vector_size SErrorSPx
+
+       /* -----------------------------------------------------
+        * Lower EL using AArch64 : 0x400 - 0x580
+        * -----------------------------------------------------
+        */
+       .align  7
+SynchronousExceptionA64:
+       mov     x0, #SYNC_EXCEPTION_AARCH64
+       bl      plat_report_exception
+       b       SynchronousExceptionA64
+       check_vector_size SynchronousExceptionA64
+
+       .align  7
+IrqA64:
+       mov     x0, #IRQ_AARCH64
+       bl      plat_report_exception
+       b       IrqA64
+       check_vector_size IrqA64
+
+       .align  7
+FiqA64:
+       mov     x0, #FIQ_AARCH64
+       bl      plat_report_exception
+       b       FiqA64
+       check_vector_size FiqA64
+
+       .align  7
+SErrorA64:
+       mov     x0, #SERROR_AARCH64
+       bl      plat_report_exception
+       b       SErrorA64
+       check_vector_size SErrorA64
+
+       /* -----------------------------------------------------
+        * Lower EL using AArch32 : 0x0 - 0x180
+        * -----------------------------------------------------
+        */
+       .align  7
+SynchronousExceptionA32:
+       mov     x0, #SYNC_EXCEPTION_AARCH32
+       bl      plat_report_exception
+       b       SynchronousExceptionA32
+       check_vector_size SynchronousExceptionA32
+
+       .align  7
+IrqA32:
+       mov     x0, #IRQ_AARCH32
+       bl      plat_report_exception
+       b       IrqA32
+       check_vector_size IrqA32
+
+       .align  7
+FiqA32:
+       mov     x0, #FIQ_AARCH32
+       bl      plat_report_exception
+       b       FiqA32
+       check_vector_size FiqA32
+
+       .align  7
+SErrorA32:
+       mov     x0, #SERROR_AARCH32
+       bl      plat_report_exception
+       b       SErrorA32
+       check_vector_size SErrorA32
diff --git a/common/auth.c b/common/auth.c
new file mode 100644 (file)
index 0000000..37234b8
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <auth.h>
+#include <debug.h>
+
+/*
+ * Initialize the authentication module
+ */
+void auth_init(void)
+{
+       assert(auth_mod.name);
+       assert(auth_mod.init);
+       assert(auth_mod.verify);
+
+       INFO("Using authentication module '%s'\n", auth_mod.name);
+       if (auth_mod.init() != 0)
+               assert(0);
+}
+
+/*
+ * Authenticate a certificate/image
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len)
+{
+       assert(obj_id < AUTH_NUM_OBJ);
+       assert(obj_buf != 0);
+       assert(auth_mod.verify);
+
+       return auth_mod.verify(obj_id, obj_buf, len);
+}
diff --git a/common/auth/polarssl/polarssl.c b/common/auth/polarssl/polarssl.c
new file mode 100644 (file)
index 0000000..e099f50
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Authentication module based on PolarSSL */
+
+#include <stddef.h>
+
+#include <assert.h>
+#include <auth.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <platform_oid.h>
+
+#include <polarssl/memory_buffer_alloc.h>
+#include <polarssl/oid.h>
+#include <polarssl/platform.h>
+#include <polarssl/sha256.h>
+#include <polarssl/x509_crt.h>
+
+/*
+ * At each authentication stage, the module is responsible for extracting and
+ * storing those elements (keys, hashes, etc.) that will be needed later on
+ * during the Trusted Boot process.
+ */
+
+/* SHA256 algorithm */
+#define SHA_BYTES                      32
+
+/*
+ * An 8 KB stack has been proven to be enough for the current Trusted Boot
+ * process
+ */
+#define POLARSSL_HEAP_SIZE             (8*1024)
+static unsigned char heap[POLARSSL_HEAP_SIZE];
+
+/*
+ * RSA public keys:
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
+ *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
+ *                                                + 1 + 1 + 9 (rsa oid)
+ *                                                + 1 + 1 (params null)
+ *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
+ *  RSAPublicKey ::= SEQUENCE {                     1 + 3
+ *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
+ *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
+ *  }
+ *
+ * POLARSSL_MPI_MAX_SIZE is set to 256 bytes (RSA-2048 bit keys) in the
+ * configuration file
+ */
+#define RSA_PUB_DER_MAX_BYTES   38 + 2 * POLARSSL_MPI_MAX_SIZE
+
+/*
+ * Buffer for storing public keys extracted from certificates while they are
+ * verified
+ */
+static unsigned char pk_buf[RSA_PUB_DER_MAX_BYTES];
+
+/* We use this variable to parse and authenticate the certificates */
+static x509_crt cert;
+
+/* BL specific variables */
+#if IMAGE_BL1
+static unsigned char sha_bl2[SHA_BYTES];
+#elif IMAGE_BL2
+/* Buffers to store the hash of BL3-x images */
+static unsigned char sha_bl30[SHA_BYTES];
+static unsigned char sha_bl31[SHA_BYTES];
+static unsigned char sha_bl32[SHA_BYTES];
+static unsigned char sha_bl33[SHA_BYTES];
+/* Buffers to store the Trusted and Non-Trusted world public keys */
+static unsigned char tz_world_pk[RSA_PUB_DER_MAX_BYTES];
+static unsigned char ntz_world_pk[RSA_PUB_DER_MAX_BYTES];
+static size_t tz_world_pk_len, ntz_world_pk_len;
+/* Buffer to store the BL3-x public keys */
+static unsigned char content_pk[RSA_PUB_DER_MAX_BYTES];
+static size_t content_pk_len;
+#endif
+
+
+static int x509_get_crt_ext_data(const unsigned char **ext_data,
+                                size_t *ext_len,
+                                x509_crt *crt,
+                                const char *oid)
+{
+       int ret;
+       size_t len;
+       unsigned char *end_ext_data, *end_ext_octet;
+       unsigned char *p;
+       const unsigned char *end;
+       char oid_str[64];
+
+       p = crt->v3_ext.p;
+       end = crt->v3_ext.p + crt->v3_ext.len;
+
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0)
+               return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+       if (end != p + len)
+               return POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                               POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+       while (p < end) {
+               /*
+                * Extension  ::=  SEQUENCE  {
+                *      extnID      OBJECT IDENTIFIER,
+                *      critical    BOOLEAN DEFAULT FALSE,
+                *      extnValue   OCTET STRING  }
+                */
+               x509_buf extn_oid = {0, 0, NULL};
+               int is_critical = 0; /* DEFAULT FALSE */
+
+               ret = asn1_get_tag(&p, end, &len,
+                               ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+               if (ret != 0)
+                       return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+               end_ext_data = p + len;
+
+               /* Get extension ID */
+               extn_oid.tag = *p;
+
+               ret = asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID);
+               if (ret != 0)
+                       return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+               extn_oid.p = p;
+               p += extn_oid.len;
+
+               if ((end - p) < 1)
+                       return POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                                       POLARSSL_ERR_ASN1_OUT_OF_DATA;
+
+               /* Get optional critical */
+               ret = asn1_get_bool(&p, end_ext_data, &is_critical);
+               if (ret != 0 && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG))
+                       return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+               /* Data should be octet string type */
+               ret = asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING);
+               if (ret != 0)
+                       return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+               end_ext_octet = p + len;
+
+               if (end_ext_octet != end_ext_data)
+                       return POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                                       POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+               /* Detect requested extension */
+               oid_get_numeric_string(oid_str, 64, &extn_oid);
+               if (memcmp(oid, oid_str, sizeof(oid)) == 0) {
+                       *ext_data = p;
+                       *ext_len = len;
+                       return 0;
+               }
+
+               /* Next */
+               p = end_ext_octet;
+       }
+
+       if (p != end)
+               return POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                               POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+       return POLARSSL_ERR_X509_UNKNOWN_OID;
+}
+
+#if IMAGE_BL1
+/*
+ * Parse and verify the BL2 certificate
+ *
+ * This function verifies the integrity of the BL2 certificate, checks that it
+ * has been signed with the ROT key and extracts the BL2 hash stored in the
+ * certificate so it can be matched later against the calculated hash.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int check_bl2_cert(unsigned char *buf, size_t len)
+{
+       const unsigned char *p;
+       size_t sz;
+       int err, flags;
+
+       x509_crt_init(&cert);
+
+       /* Parse the BL2 certificate */
+       err = x509_crt_parse(&cert, buf, len);
+       if (err) {
+               ERROR("BL2 certificate parse error %d.\n", err);
+               goto error;
+       }
+
+       /* Check that it has been signed with the ROT key */
+       err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf));
+       if (err < 0) {
+               ERROR("Error loading ROT key in DER format %d.\n", err);
+               goto error;
+       }
+
+       sz = (size_t)err;
+       p = pk_buf + sizeof(pk_buf) - sz;
+
+       err = plat_match_rotpk(p, sz);
+       if (err) {
+               ERROR("ROT and BL2 certificate key mismatch\n");
+               goto error;
+       }
+
+       /* Verify certificate */
+       err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
+       if (err) {
+               ERROR("BL2 certificate verification error %d. Flags: 0x%x.\n",
+                               err, flags);
+               goto error;
+       }
+
+       /* Extract BL2 image hash from certificate */
+       err = x509_get_crt_ext_data(&p, &sz, &cert, BL2_HASH_OID);
+       if (err) {
+               ERROR("Cannot read BL2 hash from certificate\n");
+               goto error;
+       }
+
+       assert(sz == SHA_BYTES + 2);
+
+       /* Skip the tag and length bytes and copy the hash */
+       p += 2;
+       memcpy(sha_bl2, p, SHA_BYTES);
+
+error:
+       x509_crt_free(&cert);
+
+       return err;
+}
+#endif /* IMAGE_BL1 */
+
+#if IMAGE_BL2
+static int check_trusted_key_cert(unsigned char *buf, size_t len)
+{
+       const unsigned char *p;
+       size_t sz;
+       int err, flags;
+
+       x509_crt_init(&cert);
+
+       /* Parse the Trusted Key certificate */
+       err = x509_crt_parse(&cert, buf, len);
+       if (err) {
+               ERROR("Trusted Key certificate parse error %d.\n", err);
+               goto error;
+       }
+
+       /* Verify Trusted Key certificate */
+       err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
+       if (err) {
+               ERROR("Trusted Key certificate verification error %d. Flags: "
+                               "0x%x.\n", err, flags);
+               goto error;
+       }
+
+       /* Check that it has been signed with the ROT key */
+       err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf));
+       if (err < 0) {
+               ERROR("Error loading ROT key in DER format %d.\n", err);
+               goto error;
+       }
+
+       sz = (size_t)err;
+       p = pk_buf + sizeof(pk_buf) - sz;
+
+       if (plat_match_rotpk(p, sz)) {
+               ERROR("ROT and Trusted Key certificate key mismatch\n");
+               goto error;
+       }
+
+       /* Extract Trusted World key from extensions */
+       err = x509_get_crt_ext_data(&p, &tz_world_pk_len,
+                       &cert, TZ_WORLD_PK_OID);
+       if (err) {
+               ERROR("Cannot read Trusted World key\n");
+               goto error;
+       }
+
+       assert(tz_world_pk_len <= RSA_PUB_DER_MAX_BYTES);
+       memcpy(tz_world_pk, p, tz_world_pk_len);
+
+       /* Extract Non-Trusted World key from extensions */
+       err = x509_get_crt_ext_data(&p, &ntz_world_pk_len,
+                       &cert, NTZ_WORLD_PK_OID);
+       if (err) {
+               ERROR("Cannot read Non-Trusted World key\n");
+               goto error;
+       }
+
+       assert(tz_world_pk_len <= RSA_PUB_DER_MAX_BYTES);
+       memcpy(ntz_world_pk, p, ntz_world_pk_len);
+
+error:
+       x509_crt_free(&cert);
+
+       return err;
+}
+
+static int check_bl3x_key_cert(const unsigned char *buf, size_t len,
+                              const unsigned char *i_key, size_t i_key_len,
+                              unsigned char *s_key, size_t *s_key_len,
+                              const char *key_oid)
+{
+       const unsigned char *p;
+       size_t sz;
+       int err, flags;
+
+       x509_crt_init(&cert);
+
+       /* Parse key certificate */
+       err = x509_crt_parse(&cert, buf, len);
+       if (err) {
+               ERROR("Key certificate parse error %d.\n", err);
+               goto error;
+       }
+
+       /* Verify certificate */
+       err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
+       if (err) {
+               ERROR("Key certificate verification error %d. Flags: "
+                               "0x%x.\n", err, flags);
+               goto error;
+       }
+
+       /* Check that the certificate has been signed by the issuer */
+       err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf));
+       if (err < 0) {
+               ERROR("Error loading key in DER format %d.\n", err);
+               goto error;
+       }
+
+       sz = (size_t)err;
+       p = pk_buf + sizeof(pk_buf) - sz;
+       if ((sz != i_key_len) || memcmp(p, i_key, sz)) {
+               ERROR("Key certificate not signed with issuer key\n");
+               err = 1;
+               goto error;
+       }
+
+       /* Get the content certificate key */
+       err = x509_get_crt_ext_data(&p, &sz, &cert, key_oid);
+       if (err) {
+               ERROR("Extension %s not found in Key certificate\n", key_oid);
+               goto error;
+       }
+
+       assert(sz <= RSA_PUB_DER_MAX_BYTES);
+       memcpy(s_key, p, sz);
+       *s_key_len = sz;
+
+error:
+       x509_crt_free(&cert);
+
+       return err;
+}
+
+static int check_bl3x_cert(unsigned char *buf, size_t len,
+                      const unsigned char *i_key, size_t i_key_len,
+                      const char *hash_oid, unsigned char *sha)
+{
+       const unsigned char *p;
+       size_t sz;
+       int err, flags;
+
+       x509_crt_init(&cert);
+
+       /* Parse BL31 content certificate */
+       err = x509_crt_parse(&cert, buf, len);
+       if (err) {
+               ERROR("Content certificate parse error %d.\n", err);
+               goto error;
+       }
+
+       /* Verify certificate */
+       err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
+       if (err) {
+               ERROR("Content certificate verification error %d. Flags: "
+                               "0x%x.\n", err, flags);
+               goto error;
+       }
+
+       /* Check that content certificate has been signed with the content
+        * certificate key corresponding to this image */
+       sz = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf));
+       p = pk_buf + sizeof(pk_buf) - sz;
+
+       if ((sz != i_key_len) || memcmp(p, i_key, sz)) {
+               ERROR("Content certificate not signed with content "
+                               "certificate key\n");
+               err = 1;
+               goto error;
+       }
+
+       /* Extract image hash from certificate */
+       err = x509_get_crt_ext_data(&p, &sz, &cert, hash_oid);
+       if (err) {
+               ERROR("Cannot read hash from certificate\n");
+               goto error;
+       }
+
+       assert(sz == SHA_BYTES + 2);
+
+       /* Skip the tag and length bytes and copy the hash */
+       p += 2;
+       memcpy(sha, p, SHA_BYTES);
+
+error:
+       x509_crt_free(&cert);
+
+       return err;
+}
+#endif /* IMAGE_BL2 */
+
+/*
+ * Calculate the hash of the image and check it against the hash extracted
+ * previously from the certificate
+ *
+ * Parameters:
+ *   buf: buffer where image is loaded
+ *   len: size of the image
+ *   sha: matching hash (extracted from the image certificate)
+ *
+ * Return: 0 = match, Otherwise = mismatch
+ */
+static int check_bl_img(unsigned char *buf, size_t len,
+                       const unsigned char *sha)
+{
+       unsigned char img_sha[SHA_BYTES];
+
+       /* Calculate the hash of the image */
+       sha256(buf, len, img_sha, 0);
+
+       /* Match the hash with the one extracted from the certificate */
+       if (memcmp(img_sha, sha, SHA_BYTES)) {
+               ERROR("Image hash mismatch\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * Object verification function
+ *
+ * The id parameter will indicate the expected format of the object
+ * (certificate, image, etc).
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int polarssl_mod_verify(unsigned int id, uintptr_t obj, size_t len)
+{
+       int ret;
+
+       switch (id) {
+#if IMAGE_BL1
+       case AUTH_BL2_IMG_CERT:
+               ret = check_bl2_cert((unsigned char *)obj, len);
+               break;
+       case AUTH_BL2_IMG:
+               ret = check_bl_img((unsigned char *)obj, len, sha_bl2);
+               break;
+#endif /* IMAGE_BL1 */
+
+#if IMAGE_BL2
+       case AUTH_TRUSTED_KEY_CERT:
+               ret = check_trusted_key_cert((unsigned char *)obj, len);
+               break;
+       case AUTH_BL30_KEY_CERT:
+               ret = check_bl3x_key_cert((unsigned char *)obj, len,
+                               tz_world_pk, tz_world_pk_len,
+                               content_pk, &content_pk_len,
+                               BL30_CONTENT_CERT_PK_OID);
+               break;
+       case AUTH_BL31_KEY_CERT:
+               ret = check_bl3x_key_cert((unsigned char *)obj, len,
+                               tz_world_pk, tz_world_pk_len,
+                               content_pk, &content_pk_len,
+                               BL31_CONTENT_CERT_PK_OID);
+               break;
+       case AUTH_BL32_KEY_CERT:
+               ret = check_bl3x_key_cert((unsigned char *)obj, len,
+                               tz_world_pk, tz_world_pk_len,
+                               content_pk, &content_pk_len,
+                               BL32_CONTENT_CERT_PK_OID);
+               break;
+       case AUTH_BL33_KEY_CERT:
+               ret = check_bl3x_key_cert((unsigned char *)obj, len,
+                               ntz_world_pk, ntz_world_pk_len,
+                               content_pk, &content_pk_len,
+                               BL33_CONTENT_CERT_PK_OID);
+               break;
+       case AUTH_BL30_IMG_CERT:
+               ret = check_bl3x_cert((unsigned char *)obj, len,
+                               content_pk, content_pk_len,
+                               BL30_HASH_OID, sha_bl30);
+               break;
+       case AUTH_BL31_IMG_CERT:
+               ret = check_bl3x_cert((unsigned char *)obj, len,
+                               content_pk, content_pk_len,
+                               BL31_HASH_OID, sha_bl31);
+               break;
+       case AUTH_BL32_IMG_CERT:
+               ret = check_bl3x_cert((unsigned char *)obj, len,
+                               content_pk, content_pk_len,
+                               BL32_HASH_OID, sha_bl32);
+               break;
+       case AUTH_BL33_IMG_CERT:
+               ret = check_bl3x_cert((unsigned char *)obj, len,
+                               content_pk, content_pk_len,
+                               BL33_HASH_OID, sha_bl33);
+               break;
+       case AUTH_BL30_IMG:
+               ret = check_bl_img((unsigned char *)obj, len, sha_bl30);
+               break;
+       case AUTH_BL31_IMG:
+               ret = check_bl_img((unsigned char *)obj, len, sha_bl31);
+               break;
+       case AUTH_BL32_IMG:
+               ret = check_bl_img((unsigned char *)obj, len, sha_bl32);
+               break;
+       case AUTH_BL33_IMG:
+               ret = check_bl_img((unsigned char *)obj, len, sha_bl33);
+               break;
+#endif /* IMAGE_BL2 */
+       default:
+               ret = -1;
+               break;
+       }
+
+       return ret;
+}
+
+/*
+ * Module initialization function
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int polarssl_mod_init(void)
+{
+       /* Initialize the PolarSSL heap */
+       return memory_buffer_alloc_init(heap, POLARSSL_HEAP_SIZE);
+}
+
+const auth_mod_t auth_mod = {
+       .name = "PolarSSL",
+       .init = polarssl_mod_init,
+       .verify = polarssl_mod_verify
+};
diff --git a/common/auth/polarssl/polarssl.mk b/common/auth/polarssl/polarssl.mk
new file mode 100644 (file)
index 0000000..f7d92ea
--- /dev/null
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# POLARSSL_DIR must be set to the PolarSSL main directory (it must contain
+# the 'include' and 'library' subdirectories).
+ifeq (${POLARSSL_DIR},)
+  $(error Error: POLARSSL_DIR not set)
+endif
+
+INCLUDES               +=      -I${POLARSSL_DIR}/include               \
+                               -Icommon/auth/polarssl
+
+POLARSSL_CONFIG_FILE   :=      "<polarssl_config.h>"
+$(eval $(call add_define,POLARSSL_CONFIG_FILE))
+
+POLARSSL_SOURCES       :=      $(addprefix ${POLARSSL_DIR}/library/,   \
+                               asn1parse.c                             \
+                               asn1write.c                             \
+                               bignum.c                                \
+                               md.c                                    \
+                               md_wrap.c                               \
+                               memory_buffer_alloc.c                   \
+                               oid.c                                   \
+                               pk.c                                    \
+                               pk_wrap.c                               \
+                               pkparse.c                               \
+                               pkwrite.c                               \
+                               platform.c                              \
+                               rsa.c                                   \
+                               sha1.c                                  \
+                               sha256.c                                \
+                               x509.c                                  \
+                               x509_crt.c                              \
+                               )
+
+BL1_SOURCES            +=      ${POLARSSL_SOURCES}                     \
+                               common/auth/polarssl/polarssl.c
+
+BL2_SOURCES            +=      ${POLARSSL_SOURCES}                     \
+                               common/auth/polarssl/polarssl.c
+
+DISABLE_PEDANTIC       :=      1
diff --git a/common/auth/polarssl/polarssl_config.h b/common/auth/polarssl/polarssl_config.h
new file mode 100644 (file)
index 0000000..531e084
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __POLARSSL_CONFIG_H__
+#define __POLARSSL_CONFIG_H__
+
+
+/*
+ * Configuration file to build PolarSSL with the required features for
+ * Trusted Boot
+ */
+
+#define POLARSSL_PLATFORM_MEMORY
+#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS
+
+#define POLARSSL_PKCS1_V15
+#define POLARSSL_PKCS1_V21
+
+#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+#define POLARSSL_X509_CHECK_KEY_USAGE
+#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE
+
+#define POLARSSL_ASN1_PARSE_C
+#define POLARSSL_ASN1_WRITE_C
+
+#define POLARSSL_BASE64_C
+#define POLARSSL_BIGNUM_C
+
+#define POLARSSL_ERROR_C
+#define POLARSSL_MD_C
+
+#define POLARSSL_MEMORY_BUFFER_ALLOC_C
+#define POLARSSL_OID_C
+
+#define POLARSSL_PK_C
+#define POLARSSL_PK_PARSE_C
+#define POLARSSL_PK_WRITE_C
+
+#define POLARSSL_PLATFORM_C
+
+#define POLARSSL_RSA_C
+#define POLARSSL_SHA1_C
+#define POLARSSL_SHA256_C
+
+#define POLARSSL_VERSION_C
+
+#define POLARSSL_X509_USE_C
+#define POLARSSL_X509_CRT_PARSE_C
+
+/* MPI / BIGNUM options */
+#define POLARSSL_MPI_WINDOW_SIZE              2
+#define POLARSSL_MPI_MAX_SIZE               256
+
+/* Memory buffer allocator options */
+#define POLARSSL_MEMORY_ALIGN_MULTIPLE        8
+
+#include "polarssl/check_config.h"
+
+#endif /* __POLARSSL_CONFIG_H__ */
diff --git a/common/bl_common.c b/common/bl_common.c
new file mode 100644 (file)
index 0000000..8c241ec
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <errno.h>
+#include <io_storage.h>
+#include <platform.h>
+
+unsigned long page_align(unsigned long value, unsigned dir)
+{
+       unsigned long page_size = 1 << FOUR_KB_SHIFT;
+
+       /* 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;
+}
+
+static inline unsigned int is_page_aligned (unsigned long addr) {
+       const unsigned long page_size = 1 << FOUR_KB_SHIFT;
+
+       return (addr & (page_size - 1)) == 0;
+}
+
+void change_security_state(unsigned int target_security_state)
+{
+       unsigned long scr = read_scr();
+
+       assert(sec_state_is_valid(target_security_state));
+       if (target_security_state == SECURE)
+               scr &= ~SCR_NS_BIT;
+       else
+               scr |= SCR_NS_BIT;
+
+       write_scr(scr);
+}
+
+/******************************************************************************
+ * 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 otherwise.
+ *****************************************************************************/
+static int is_mem_free(uint64_t free_base, size_t free_size,
+                      uint64_t addr, size_t size)
+{
+       return (addr >= free_base) && (addr + size <= free_base + free_size);
+}
+
+/******************************************************************************
+ * 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(uint64_t mem_start, uint64_t mem_end,
+                                  uint64_t submem_start, uint64_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.
+ *****************************************************************************/
+void reserve_mem(uint64_t *free_base, size_t *free_size,
+                uint64_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));
+
+       pos = choose_mem_pos(*free_base, *free_base + *free_size,
+                            addr, addr + size,
+                            &discard_size);
+
+       reserved_size = size + discard_size;
+       *free_size -= reserved_size;
+
+       if (pos == BOTTOM)
+               *free_base = addr + size;
+
+       VERBOSE("Reserved %u bytes (discarded %u bytes %s)\n",
+            reserved_size, discard_size,
+            pos == TOP ? "above" : "below");
+}
+
+static void dump_load_info(unsigned long image_load_addr,
+                          unsigned long image_size,
+                          const meminfo_t *mem_layout)
+{
+       INFO("Trying to load image at address 0x%lx, size = 0x%lx\n",
+               image_load_addr, image_size);
+       INFO("Current memory layout:\n");
+       INFO("  total region = [0x%lx, 0x%lx]\n", mem_layout->total_base,
+                       mem_layout->total_base + mem_layout->total_size);
+       INFO("  free region = [0x%lx, 0x%lx]\n", mem_layout->free_base,
+                       mem_layout->free_base + mem_layout->free_size);
+}
+
+/* Generic function to return the size of an image */
+unsigned long image_size(const char *image_name)
+{
+       uintptr_t dev_handle;
+       uintptr_t image_handle;
+       uintptr_t image_spec;
+       size_t image_size = 0;
+       int io_result = IO_FAIL;
+
+       assert(image_name != NULL);
+
+       /* Obtain a reference to the image by querying the platform layer */
+       io_result = plat_get_image_source(image_name, &dev_handle, &image_spec);
+       if (io_result != IO_SUCCESS) {
+               WARN("Failed to obtain reference to image '%s' (%i)\n",
+                       image_name, io_result);
+               return 0;
+       }
+
+       /* Attempt to access the image */
+       io_result = io_open(dev_handle, image_spec, &image_handle);
+       if (io_result != IO_SUCCESS) {
+               WARN("Failed to access image '%s' (%i)\n",
+                       image_name, io_result);
+               return 0;
+       }
+
+       /* Find the size of the image */
+       io_result = io_size(image_handle, &image_size);
+       if ((io_result != IO_SUCCESS) || (image_size == 0)) {
+               WARN("Failed to determine the size of the image '%s' file (%i)\n",
+                       image_name, 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;
+}
+
+/*******************************************************************************
+ * Generic function to load an image at a specific address given a name and
+ * extents of free memory. It updates the memory layout if the load is
+ * successful, as well as the image information and the entry point information.
+ * The caller might pass a NULL pointer for the entry point if it is not
+ * interested in this information, e.g. because the image just needs to be
+ * loaded in memory but won't ever be executed.
+ * Returns 0 on success, a negative error code otherwise.
+ ******************************************************************************/
+int load_image(meminfo_t *mem_layout,
+              const char *image_name,
+              uint64_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 = IO_FAIL;
+
+       assert(mem_layout != NULL);
+       assert(image_name != 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_name, &dev_handle, &image_spec);
+       if (io_result != IO_SUCCESS) {
+               WARN("Failed to obtain reference to image '%s' (%i)\n",
+                       image_name, io_result);
+               return io_result;
+       }
+
+       /* Attempt to access the image */
+       io_result = io_open(dev_handle, image_spec, &image_handle);
+       if (io_result != IO_SUCCESS) {
+               WARN("Failed to access image '%s' (%i)\n",
+                       image_name, io_result);
+               return io_result;
+       }
+
+       INFO("Loading file '%s' at address 0x%lx\n", image_name, image_base);
+
+       /* Find the size of the image */
+       io_result = io_size(image_handle, &image_size);
+       if ((io_result != IO_SUCCESS) || (image_size == 0)) {
+               WARN("Failed to determine the size of the image '%s' file (%i)\n",
+                       image_name, 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 memory: 0x%lx - 0x%lx\n",
+                       image_base, 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 != IO_SUCCESS) || (bytes_read < image_size)) {
+               WARN("Failed to load '%s' file (%i)\n", image_name, io_result);
+               goto exit;
+       }
+
+       /*
+        * 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);
+       } else {
+               INFO("Skip reserving memory: 0x%lx - 0x%lx\n",
+                               image_base, image_base + image_size);
+       }
+
+       image_data->image_base = image_base;
+       image_data->image_size = image_size;
+
+       if (entry_point_info != NULL)
+               entry_point_info->pc = image_base;
+
+       /*
+        * File has been successfully loaded.
+        * Flush the image in TZRAM so that the next EL can see it.
+        */
+       flush_dcache_range(image_base, image_size);
+
+       INFO("File '%s' loaded: 0x%lx - 0x%lx\n", image_name, image_base,
+            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;
+}
diff --git a/common/tf_printf.c b/common/tf_printf.c
new file mode 100644 (file)
index 0000000..02461c0
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <debug.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+/***********************************************************
+ * The tf_printf implementation for all BL stages
+ ***********************************************************/
+static void unsigned_num_print(unsigned long int unum, unsigned int radix)
+{
+       /* 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);
+
+       while (--i >= 0)
+               putchar(num_buf[i]);
+}
+
+static void string_print(const char *str)
+{
+       while (*str)
+               putchar(*str++);
+}
+
+/*******************************************************************
+ * Reduced format print for Trusted firmware.
+ * The following formats are supported by this print
+ * %x - 32 bit hexadecimal format
+ * %llx and %lx -64 bit hexadecimal format
+ * %s - string format
+ * %d or %i - signed 32 bit decimal format
+ * %u - unsigned 32 bit decimal format
+ * %ld and %lld - signed 64 bit decimal format
+ * %lu and %llu - unsigned 64 bit decimal format
+ * Exits on all other formats.
+ *******************************************************************/
+
+void tf_printf(const char *fmt, ...)
+{
+       va_list args;
+       int bit64;
+       int64_t num;
+       uint64_t unum;
+       char *str;
+
+       va_start(args, fmt);
+       while (*fmt) {
+               bit64 = 0;
+
+               if (*fmt == '%') {
+                       fmt++;
+                       /* Check the format specifier */
+loop:
+                       switch (*fmt) {
+                       case 'i': /* Fall through to next one */
+                       case 'd':
+                               if (bit64)
+                                       num = va_arg(args, int64_t);
+                               else
+                                       num = va_arg(args, int32_t);
+
+                               if (num < 0) {
+                                       putchar('-');
+                                       unum = (unsigned long int)-num;
+                               } else
+                                       unum = (unsigned long int)num;
+
+                               unsigned_num_print(unum, 10);
+                               break;
+                       case 's':
+                               str = va_arg(args, char *);
+                               string_print(str);
+                               break;
+                       case 'x':
+                               if (bit64)
+                                       unum = va_arg(args, uint64_t);
+                               else
+                                       unum = va_arg(args, uint32_t);
+
+                               unsigned_num_print(unum, 16);
+                               break;
+                       case 'l':
+                               bit64 = 1;
+                               fmt++;
+                               goto loop;
+                       case 'u':
+                               if (bit64)
+                                       unum = va_arg(args, uint64_t);
+                               else
+                                       unum = va_arg(args, uint32_t);
+
+                               unsigned_num_print(unum, 10);
+                               break;
+                       default:
+                               /* Exit on any other format specifier */
+                               goto exit;
+                       }
+                       fmt++;
+                       continue;
+               }
+               putchar(*fmt++);
+       }
+exit:
+       va_end(args);
+}
diff --git a/contributing.md b/contributing.md
new file mode 100644 (file)
index 0000000..6b24fb5
--- /dev/null
@@ -0,0 +1,121 @@
+Contributing to ARM Trusted Firmware
+====================================
+
+Before you start contributing to this project you must sign the ARM
+Contributor License Agreement (CLA).
+
+Individuals who want to contribute their own work must sign and return an
+Individual CLA. Companies that want to contribute must sign and return a
+Corporate CLA if their employees' intellectual property has been assigned to
+the employer. Copies of the CLAs are available from the [contributing page] of
+the ARM website.
+
+For this project, ARM also requires the GitHub account name(s) associated with
+each individual contributor or the designated employees of corporate
+contributors. Only contributions originating from these accounts will be
+considered covered by the CLA. To avoid delay, you should provide the Github
+account name(s) at the same time as the signed CLA.
+
+ARM reserves the right to not accept a contribution. This may be for technical,
+commercial or legal reasons.
+
+
+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 ARM Trusted
+    Firmware 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.
+    *   If this is your first contribution, you may add your name or your
+        company name to the [Acknowledgements] 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 the "[Running the software]" section of the
+    [User Guide] for more information.
+
+
+Submitting Changes
+------------------
+
+*   Ensure we have your signed CLA.
+*   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. 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, ARM will integrate them.
+    *   Typically, ARM 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, ARM may rebase
+        it onto the `master` branch first, or ask you to do this.
+    *   If the [pull request] cannot be automatically merged, ARM will ask you
+        to rebase it onto the `master` branch.
+    *   After final integration testing, ARM will push your merge commit to the
+        `master` branch. If a problem is found at this stage, the merge commit
+        will be removed from the `integration` branch and ARM 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-2014, ARM Limited and Contributors. All rights reserved._
+
+
+[User Guide]:                           ./docs/user-guide.md
+[Running the software]:                 ./docs/user-guide.md#6--running-the-software
+[Porting Guide]:                        ./docs/porting-guide.md
+[Firmware Design]:                      ./docs/firmware-design.md
+[Acknowledgements]:                     ./acknowledgements.md "Contributor acknowledgements"
+
+[contributing page]:            http://www.arm.com/community/open-source-contributing.php
+[GitHub account]:               https://github.com/signup/free
+[Fork]:                         https://help.github.com/articles/fork-a-repo
+[issue tracking repository]:    https://github.com/ARM-software/tf-issues
+[issue]:                        https://github.com/ARM-software/tf-issues/issues
+[pull request]:                 https://help.github.com/articles/using-pull-requests
+[automatically closed]:         https://help.github.com/articles/closing-issues-via-commit-messages
+[Git guidelines]:               http://git-scm.com/book/ch5-2.html
+[Linux coding style]:           https://www.kernel.org/doc/Documentation/CodingStyle
+[arm-trusted-firmware]:         https://github.com/ARM-software/arm-trusted-firmware
diff --git a/docs/change-log.md b/docs/change-log.md
new file mode 100644 (file)
index 0000000..c7b5508
--- /dev/null
@@ -0,0 +1,710 @@
+ARM Trusted Firmware - version 1.1
+==================================
+
+New features
+------------
+
+*   A prototype implementation of Trusted Board Boot has been added. Boot
+    loader images are verified by BL1 and BL2 during the cold boot path. BL1 and
+    BL2 use the PolarSSL SSL library to verify certificates and images. The
+    OpenSSL library is used to create the X.509 certificates. Support has been
+    added to `fip_create` tool to package the certificates in a FIP.
+
+*   Support for calling CPU and platform specific reset handlers upon entry into
+    BL3-1 during the cold and warm boot paths has been added. This happens after
+    another Boot ROM `reset_handler()` has already run. This enables a developer
+    to perform additional actions or undo actions already performed during the
+    first call of the reset handlers e.g. apply additional errata workarounds.
+
+*   Support has been added to demonstrate routing of IRQs to EL3 instead of
+    S-EL1 when execution is in secure world.
+
+*   The PSCI implementation now conforms to version 1.0 of the PSCI
+    specification. All the mandatory APIs and selected optional APIs are
+    supported. In particular, support for the `PSCI_FEATURES` API has been
+    added. A capability variable is constructed during initialization by
+    examining the `plat_pm_ops` and `spd_pm_ops` exported by the platform and
+    the Secure Payload Dispatcher.  This is used by the PSCI FEATURES function
+    to determine which PSCI APIs are supported by the platform.
+
+*   Improvements have been made to the PSCI code as follows.
+
+    *   The code has been refactored to remove redundant parameters from
+        internal functions.
+
+    *   Changes have been made to the code for PSCI `CPU_SUSPEND`, `CPU_ON` and
+        `CPU_OFF` calls to facilitate an early return to the caller in case a
+        failure condition is detected. For example, a PSCI `CPU_SUSPEND` call
+        returns `SUCCESS` to the caller if a pending interrupt is detected early
+        in the code path.
+
+    *   Optional platform APIs have been added to validate the `power_state` and
+        `entrypoint` parameters early in PSCI `CPU_ON` and `CPU_SUSPEND` code
+        paths.
+
+    *   PSCI migrate APIs have been reworked to invoke the SPD hook to determine
+        the type of Trusted OS and the CPU it is resident on (if
+        applicable). Also, during a PSCI `MIGRATE` call, the SPD hook to migrate
+        the Trusted OS is invoked.
+
+*   It is now possible to build Trusted Firmware without marking at least an
+    extra page of memory as coherent. The build flag `USE_COHERENT_MEM` can be
+    used to choose between the two implementations. This has been made possible
+    through these changes.
+
+    *   An implementation of Bakery locks, where the locks are not allocated in
+        coherent memory has been added.
+
+    *   Memory which was previously marked as coherent is now kept coherent
+        through the use of software cache maintenance operations.
+
+    Approximately, 4K worth of memory is saved for each boot loader stage when
+    `USE_COHERENT_MEM=0`. Enabling this option increases the latencies
+    associated with acquire and release of locks. It also requires changes to
+    the platform ports.
+
+*   It is now possible to specify the name of the FIP at build time by defining
+    the `FIP_NAME` variable.
+
+*   Issues with depedencies on the 'fiptool' makefile target have been
+    rectified. The `fip_create` tool is now rebuilt whenever its source files
+    change.
+
+*   The BL3-1 runtime console is now also used as the crash console. The crash
+    console is changed to SoC UART0 (UART2) from the previous FPGA UART0 (UART0)
+    on Juno. In FVP, it is changed from UART0 to UART1.
+
+*   CPU errata workarounds are applied only when the revision and part number
+    match. This behaviour has been made consistent across the debug and release
+    builds. The debug build additionally prints a warning if a mismatch is
+    detected.
+
+*   It is now possible to issue cache maintenance operations by set/way for a
+    particular level of data cache. Levels 1-3 are currently supported.
+
+*   The following improvements have been made to the FVP port.
+
+    *   The build option `FVP_SHARED_DATA_LOCATION` which allowed relocation of
+        shared data into the Trusted DRAM has been deprecated. Shared data is
+        now always located at the base of Trusted SRAM.
+
+    *   BL2 Translation tables have been updated to map only the region of
+        DRAM which is accessible to normal world. This is the region of the 2GB
+        DDR-DRAM memory at 0x80000000 excluding the top 16MB. The top 16MB is
+        accessible to only the secure world.
+
+    *   BL3-2 can now reside in the top 16MB of DRAM which is accessible only to
+        the secure world. This can be done by setting the build flag
+        `FVP_TSP_RAM_LOCATION` to the value `dram`.
+
+*   Separate transation tables are created for each boot loader image. The
+    `IMAGE_BLx` build options are used to do this.  This allows each stage to
+    create mappings only for areas in the memory map that it needs.
+
+*   A Secure Payload Dispatcher (OPTEED) for the OP-TEE Trusted OS has been
+    added.  Details of using it with ARM Trusted Firmware can be found in
+    [OP-TEE Dispatcher]
+
+
+
+Issues resolved since last release
+----------------------------------
+
+*   The Juno port has been aligned with the FVP port as follows.
+
+    *   Support for reclaiming all BL1 RW memory and BL2 memory by overlaying
+        the BL3-1/BL3-2 NOBITS sections on top of them has been added to the
+        Juno port.
+
+    *   The top 16MB of the 2GB DDR-DRAM memory at 0x80000000 is configured
+        using the TZC-400 controller to be accessible only to the secure world.
+
+    *   The ARM GIC driver is used to configure the GIC-400 instead of using a
+        GIC driver private to the Juno port.
+
+    *   PSCI `CPU_SUSPEND` calls that target a standby state are now supported.
+
+    *   The TZC-400 driver is used to configure the controller instead of direct
+        accesses to the registers.
+
+*   The Linux kernel version referred to in the user guide has DVFS and HMP
+    support enabled.
+
+*   DS-5 v5.19 did not detect Version 5.8 of the Cortex-A57-A53 Base FVPs in
+    CADI server mode. This issue is not seen with DS-5 v5.20 and Version 6.2 of
+    the Cortex-A57-A53 Base FVPs.
+
+
+Known issues
+------------
+
+*   The Trusted Board Boot implementation is a prototype. There are issues with
+    the modularity and scalability of the design. Support for a Trusted
+    Watchdog, firmware update mechanism, recovery images and Trusted debug is
+    absent. These issues will be addressed in future releases.
+
+*   The FVP and Juno ports do not use the hash of the ROTPK stored in the
+    Trusted Key Storage registers to verify the ROTPK in the
+    `plat_match_rotpk()` function. This prevents the correct establishment of
+    the Chain of Trust at the first step in the Trusted Board Boot process.
+
+*   The version of the AEMv8 Base FVP used in this release resets the model
+    instead of terminating its execution in response to a shutdown request using
+    the PSCI `SYSTEM_OFF` API. This issue will be fixed in a future version of
+    the model.
+
+*   GICv3 support is experimental. There are known issues with GICv3
+    initialization in the ARM Trusted Firmware.
+
+*   While this version greatly reduces the on-chip RAM requirements, there are
+    further RAM usage enhancements that could be made.
+
+*   The firmware design documentation for the Test Secure-EL1 Payload (TSP) and
+    its dispatcher (TSPD) is incomplete. Similarly for the PSCI section.
+
+*   The Juno-specific firmware design documentation is incomplete.
+
+
+ARM Trusted Firmware - version 1.0
+==================================
+
+New features
+------------
+
+*   It is now possible to map higher physical addresses using non-flat virtual
+    to physical address mappings in the MMU setup.
+
+*   Wider use is now made of the per-CPU data cache in BL3-1 to store:
+
+    *   Pointers to the non-secure and secure security state contexts.
+
+    *   A pointer to the CPU-specific operations.
+
+    *   A pointer to PSCI specific information (for example the current power
+        state).
+
+    *   A crash reporting buffer.
+
+*   The following RAM usage improvements result in a BL3-1 RAM usage reduction
+    from 96KB to 56KB (for FVP with TSPD), and a total RAM usage reduction
+    across all images from 208KB to 88KB, compared to the previous release.
+
+    *   Removed the separate `early_exception` vectors from BL3-1 (2KB code size
+        saving).
+
+    *   Removed NSRAM from the FVP memory map, allowing the removal of one
+        (4KB) translation table.
+
+    *   Eliminated the internal `psci_suspend_context` array, saving 2KB.
+
+    *   Correctly dimensioned the PSCI `aff_map_node` array, saving 1.5KB in the
+        FVP port.
+
+    *   Removed calling CPU mpidr from the bakery lock API, saving 160 bytes.
+
+    *   Removed current CPU mpidr from PSCI common code, saving 160 bytes.
+
+    *   Inlined the mmio accessor functions, saving 360 bytes.
+
+    *   Fully reclaimed all BL1 RW memory and BL2 memory on the FVP port by
+        overlaying the BL3-1/BL3-2 NOBITS sections on top of these at runtime.
+
+    *   Made storing the FP register context optional, saving 0.5KB per context
+        (8KB on the FVP port, with TSPD enabled and running on 8 CPUs).
+
+    *   Implemented a leaner `tf_printf()` function, allowing the stack to be
+        greatly reduced.
+
+    *   Removed coherent stacks from the codebase. Stacks allocated in normal
+        memory are now used before and after the MMU is enabled. This saves 768
+        bytes per CPU in BL3-1.
+
+    *   Reworked the crash reporting in BL3-1 to use less stack.
+
+    *   Optimized the EL3 register state stored in the `cpu_context` structure
+        so that registers that do not change during normal execution are
+        re-initialized each time during cold/warm boot, rather than restored
+        from memory. This saves about 1.2KB.
+
+    *   As a result of some of the above, reduced the runtime stack size in all
+        BL images. For BL3-1, this saves 1KB per CPU.
+
+*   PSCI SMC handler improvements to correctly handle calls from secure states
+    and from AArch32.
+
+*   CPU contexts are now initialized from the `entry_point_info`. BL3-1 fully
+    determines the exception level to use for the non-trusted firmware (BL3-3)
+    based on the SPSR value provided by the BL2 platform code (or otherwise
+    provided to BL3-1). This allows platform code to directly run non-trusted
+    firmware payloads at either EL2 or EL1 without requiring an EL2 stub or OS
+    loader.
+
+*   Code refactoring improvements:
+
+    *   Refactored `fvp_config` into a common platform header.
+
+    *   Refactored the fvp gic code to be a generic driver that no longer has an
+        explicit dependency on platform code.
+
+    *   Refactored the CCI-400 driver to not have dependency on platform code.
+
+    *   Simplified the IO driver so it's no longer necessary to call `io_init()`
+        and moved all the IO storage framework code to one place.
+
+    *   Simplified the interface the the TZC-400 driver.
+
+    *   Clarified the platform porting interface to the TSP.
+
+    *   Reworked the TSPD setup code to support the alternate BL3-2
+        intialization flow where BL3-1 generic code hands control to BL3-2,
+        rather than expecting the TSPD to hand control directly to BL3-2.
+
+    *   Considerable rework to PSCI generic code to support CPU specific
+        operations.
+
+*   Improved console log output, by:
+
+    *   Adding the concept of debug log levels.
+
+    *   Rationalizing the existing debug messages and adding new ones.
+
+    *   Printing out the version of each BL stage at runtime.
+
+    *   Adding support for printing console output from assembler code,
+        including when a crash occurs before the C runtime is initialized.
+
+*   Moved up to the latest versions of the FVPs, toolchain, EDK2, kernel, Linaro
+    file system and DS-5.
+
+*   On the FVP port, made the use of the Trusted DRAM region optional at build
+    time (off by default). Normal platforms will not have such a "ready-to-use"
+    DRAM area so it is not a good example to use it.
+
+*   Added support for PSCI `SYSTEM_OFF` and `SYSTEM_RESET` APIs.
+
+*   Added support for CPU specific reset sequences, power down sequences and
+    register dumping during crash reporting. The CPU specific reset sequences
+    include support for errata workarounds.
+
+*   Merged the Juno port into the master branch. Added support for CPU hotplug
+    and CPU idle. Updated the user guide to describe how to build and run on the
+    Juno platform.
+
+
+Issues resolved since last release
+----------------------------------
+
+*   Removed the concept of top/bottom image loading. The image loader now
+    automatically detects the position of the image inside the current memory
+    layout and updates the layout to minimize fragementation. This resolves the
+    image loader limitations of previously releases. There are currently no
+    plans to support dynamic image loading.
+
+*   CPU idle now works on the publicized version of the Foundation FVP.
+
+*   All known issues relating to the compiler version used have now been
+    resolved. This TF version uses Linaro toolchain 14.07 (based on GCC 4.9).
+
+
+Known issues
+------------
+
+*   GICv3 support is experimental. The Linux kernel patches to support this are
+    not widely available. There are known issues with GICv3 initialization in
+    the ARM Trusted Firmware.
+
+*   While this version greatly reduces the on-chip RAM requirements, there are
+    further RAM usage enhancements that could be made.
+
+*   The firmware design documentation for the Test Secure-EL1 Payload (TSP) and
+    its dispatcher (TSPD) is incomplete. Similarly for the PSCI section.
+
+*   The Juno-specific firmware design documentation is incomplete.
+
+*   Some recent enhancements to the FVP port have not yet been translated into
+    the Juno port. These will be tracked via the tf-issues project.
+
+*   The Linux kernel version referred to in the user guide has DVFS and HMP
+    support disabled due to some known instabilities at the time of this
+    release. A future kernel version will re-enable these features.
+
+*   DS-5 v5.19 does not detect Version 5.8 of the Cortex-A57-A53 Base FVPs in
+    CADI server mode. This is because the `<SimName>` reported by the FVP in
+    this version has changed. For example, for the Cortex-A57x4-A53x4 Base FVP,
+    the `<SimName>` reported by the FVP is `FVP_Base_Cortex_A57x4_A53x4`, while
+    DS-5 expects it to be `FVP_Base_A57x4_A53x4`.
+
+    The temporary fix to this problem is to change the name of the FVP in
+    `sw/debugger/configdb/Boards/ARM FVP/Base_A57x4_A53x4/cadi_config.xml`.
+    Change the following line:
+
+        <SimName>System Generator:FVP_Base_A57x4_A53x4</SimName>
+    to
+        <SimName>System Generator:FVP_Base_Cortex-A57x4_A53x4</SimName>
+
+    A similar change can be made to the other Cortex-A57-A53 Base FVP variants.
+
+
+ARM Trusted Firmware - version 0.4
+==================================
+
+New features
+------------
+
+*   Makefile improvements:
+
+    *   Improved dependency checking when building.
+
+    *   Removed `dump` target (build now always produces dump files).
+
+    *   Enabled platform ports to optionally make use of parts of the Trusted
+        Firmware (e.g. BL3-1 only), rather than being forced to use all parts.
+        Also made the `fip` target optional.
+
+    *   Specified the full path to source files and removed use of the `vpath`
+        keyword.
+
+*   Provided translation table library code for potential re-use by platforms
+    other than the FVPs.
+
+*   Moved architectural timer setup to platform-specific code.
+
+*   Added standby state support to PSCI cpu_suspend implementation.
+
+*   SRAM usage improvements:
+
+    *   Started using the `-ffunction-sections`, `-fdata-sections` and
+        `--gc-sections` compiler/linker options to remove unused code and data
+        from the images. Previously, all common functions were being built into
+        all binary images, whether or not they were actually used.
+
+    *   Placed all assembler functions in their own section to allow more unused
+        functions to be removed from images.
+
+    *   Updated BL1 and BL2 to use a single coherent stack each, rather than one
+        per CPU.
+
+    *   Changed variables that were unnecessarily declared and initialized as
+        non-const (i.e. in the .data section) so they are either uninitialized
+        (zero init) or const.
+
+*   Moved the Test Secure-EL1 Payload (BL3-2) to execute in Trusted SRAM by
+    default. The option for it to run in Trusted DRAM remains.
+
+*   Implemented a TrustZone Address Space Controller (TZC-400) driver. A
+    default configuration is provided for the Base FVPs. This means the model
+    parameter `-C bp.secure_memory=1` is now supported.
+
+*   Started saving the PSCI cpu_suspend 'power_state' parameter prior to
+    suspending a CPU. This allows platforms that implement multiple power-down
+    states at the same affinity level to identify a specific state.
+
+*   Refactored the entire codebase to reduce the amount of nesting in header
+    files and to make the use of system/user includes more consistent. Also
+    split platform.h to separate out the platform porting declarations from the
+    required platform porting definitions and the definitions/declarations
+    specific to the platform port.
+
+*   Optimized the data cache clean/invalidate operations.
+
+*   Improved the BL3-1 unhandled exception handling and reporting. Unhandled
+    exceptions now result in a dump of registers to the console.
+
+*   Major rework to the handover interface between BL stages, in particular the
+    interface to BL3-1. The interface now conforms to a specification and is
+    more future proof.
+
+*   Added support for optionally making the BL3-1 entrypoint a reset handler
+    (instead of BL1). This allows platforms with an alternative image loading
+    architecture to re-use BL3-1 with fewer modifications to generic code.
+
+*   Reserved some DDR DRAM for secure use on FVP platforms to avoid future
+    compatibility problems with non-secure software.
+
+*   Added support for secure interrupts targeting the Secure-EL1 Payload (SP)
+    (using GICv2 routing only). Demonstrated this working by adding an interrupt
+    target and supporting test code to the TSP. Also demonstrated non-secure
+    interrupt handling during TSP processing.
+
+
+Issues resolved since last release
+----------------------------------
+
+*   Now support use of the model parameter `-C bp.secure_memory=1` in the Base
+    FVPs (see **New features**).
+
+*   Support for secure world interrupt handling now available (see **New
+    features**).
+
+*   Made enough SRAM savings (see **New features**) to enable the Test Secure-EL1
+    Payload (BL3-2) to execute in Trusted SRAM by default.
+
+*   The tested filesystem used for this release (Linaro AArch64 OpenEmbedded
+    14.04) now correctly reports progress in the console.
+
+*   Improved the Makefile structure to make it easier to separate out parts of
+    the Trusted Firmware for re-use in platform ports. Also, improved target
+    dependency checking.
+
+
+Known issues
+------------
+
+*   GICv3 support is experimental. The Linux kernel patches to support this are
+    not widely available. There are known issues with GICv3 initialization in
+    the ARM Trusted Firmware.
+
+*   Dynamic image loading is not available yet. The current image loader
+    implementation (used to load BL2 and all subsequent images) has some
+    limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead
+    to loading errors, even if the images should theoretically fit in memory.
+
+*   The ARM Trusted Firmware still uses too much on-chip Trusted SRAM. A number
+    of RAM usage enhancements have been identified to rectify this situation.
+
+*   CPU idle does not work on the advertised version of the Foundation FVP.
+    Some FVP fixes are required that are not available externally at the time
+    of writing. This can be worked around by disabling CPU idle in the Linux
+    kernel.
+
+*   Various bugs in ARM Trusted Firmware, UEFI and the Linux kernel have been
+    observed when using Linaro toolchain versions later than 13.11. Although
+    most of these have been fixed, some remain at the time of writing. These
+    mainly seem to relate to a subtle change in the way the compiler converts
+    between 64-bit and 32-bit values (e.g. during casting operations), which
+    reveals previously hidden bugs in client code.
+
+*   The firmware design documentation for the Test Secure-EL1 Payload (TSP) and
+    its dispatcher (TSPD) is incomplete. Similarly for the PSCI section.
+
+
+ARM Trusted Firmware - version 0.3
+==================================
+
+New features
+------------
+
+*   Support for Foundation FVP Version 2.0 added.
+    The documented UEFI configuration disables some devices that are unavailable
+    in the Foundation FVP, including MMC and CLCD. The resultant UEFI binary can
+    be used on the AEMv8 and Cortex-A57-A53 Base FVPs, as well as the Foundation
+    FVP.
+
+    NOTE: The software will not work on Version 1.0 of the Foundation FVP.
+
+*   Enabled third party contributions. Added a new contributing.md containing
+    instructions for how to contribute and updated copyright text in all files
+    to acknowledge contributors.
+
+*   The PSCI CPU_SUSPEND API has been stabilised to the extent where it can be
+    used for entry into power down states with the following restrictions:
+    -   Entry into standby states is not supported.
+    -   The API is only supported on the AEMv8 and Cortex-A57-A53 Base FVPs.
+
+*   The PSCI AFFINITY_INFO api has undergone limited testing on the Base FVPs to
+    allow experimental use.
+
+*   Required C library and runtime header files are now included locally in ARM
+    Trusted Firmware instead of depending on the toolchain standard include
+    paths. The local implementation has been cleaned up and reduced in scope.
+
+*   Added I/O abstraction framework, primarily to allow generic code to load
+    images in a platform-independent way. The existing image loading code has
+    been reworked to use the new framework. Semi-hosting and NOR flash I/O
+    drivers are provided.
+
+*   Introduced Firmware Image Package (FIP) handling code and tools. A FIP
+    combines multiple firmware images with a Table of Contents (ToC) into a
+    single binary image. The new FIP driver is another type of I/O driver. The
+    Makefile builds a FIP by default and the FVP platform code expect to load a
+    FIP from NOR flash, although some support for image loading using semi-
+    hosting is retained.
+
+    NOTE: Building a FIP by default is a non-backwards-compatible change.
+
+    NOTE: Generic BL2 code now loads a BL3-3 (non-trusted firmware) image into
+    DRAM instead of expecting this to be pre-loaded at known location. This is
+    also a non-backwards-compatible change.
+
+    NOTE: Some non-trusted firmware (e.g. UEFI) will need to be rebuilt so that
+    it knows the new location to execute from and no longer needs to copy
+    particular code modules to DRAM itself.
+
+*   Reworked BL2 to BL3-1 handover interface. A new composite structure
+    (bl31_args) holds the superset of information that needs to be passed from
+    BL2 to BL3-1, including information on how handover execution control to
+    BL3-2 (if present) and BL3-3 (non-trusted firmware).
+
+*   Added library support for CPU context management, allowing the saving and
+    restoring of
+    -   Shared system registers between Secure-EL1 and EL1.
+    -   VFP registers.
+    -   Essential EL3 system registers.
+
+*   Added a framework for implementing EL3 runtime services. Reworked the PSCI
+    implementation to be one such runtime service.
+
+*   Reworked the exception handling logic, making use of both SP_EL0 and SP_EL3
+    stack pointers for determining the type of exception, managing general
+    purpose and system register context on exception entry/exit, and handling
+    SMCs. SMCs are directed to the correct EL3 runtime service.
+
+*   Added support for a Test Secure-EL1 Payload (TSP) and a corresponding
+    Dispatcher (TSPD), which is loaded as an EL3 runtime service. The TSPD
+    implements Secure Monitor functionality such as world switching and
+    EL1 context management, and is responsible for communication with the TSP.
+    NOTE: The TSPD does not yet contain support for secure world interrupts.
+    NOTE: The TSP/TSPD is not built by default.
+
+
+Issues resolved since last release
+----------------------------------
+
+*   Support has been added for switching context between secure and normal
+    worlds in EL3.
+
+*   PSCI API calls `AFFINITY_INFO` & `PSCI_VERSION` have now been tested (to
+    a limited extent).
+
+*   The ARM Trusted Firmware build artifacts are now placed in the `./build`
+    directory and sub-directories instead of being placed in the root of the
+    project.
+
+*   The ARM Trusted Firmware is now free from build warnings. Build warnings
+    are now treated as errors.
+
+*   The ARM Trusted Firmware now provides C library support locally within the
+    project to maintain compatibility between toolchains/systems.
+
+*   The PSCI locking code has been reworked so it no longer takes locks in an
+    incorrect sequence.
+
+*   The RAM-disk method of loading a Linux file-system has been confirmed to
+    work with the ARM Trusted Firmware and Linux kernel version (based on
+    version 3.13) used in this release, for both Foundation and Base FVPs.
+
+
+Known issues
+------------
+
+The following is a list of issues which are expected to be fixed in the future
+releases of the ARM Trusted Firmware.
+
+*   The TrustZone Address Space Controller (TZC-400) is not being programmed
+    yet. Use of model parameter `-C bp.secure_memory=1` is not supported.
+
+*   No support yet for secure world interrupt handling.
+
+*   GICv3 support is experimental. The Linux kernel patches to support this are
+    not widely available. There are known issues with GICv3 initialization in
+    the ARM Trusted Firmware.
+
+*   Dynamic image loading is not available yet. The current image loader
+    implementation (used to load BL2 and all subsequent images) has some
+    limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead
+    to loading errors, even if the images should theoretically fit in memory.
+
+*   The ARM Trusted Firmware uses too much on-chip Trusted SRAM. Currently the
+    Test Secure-EL1 Payload (BL3-2) executes in Trusted DRAM since there is not
+    enough SRAM. A number of RAM usage enhancements have been identified to
+    rectify this situation.
+
+*   CPU idle does not work on the advertised version of the Foundation FVP.
+    Some FVP fixes are required that are not available externally at the time
+    of writing.
+
+*   Various bugs in ARM Trusted Firmware, UEFI and the Linux kernel have been
+    observed when using Linaro toolchain versions later than 13.11. Although
+    most of these have been fixed, some remain at the time of writing. These
+    mainly seem to relate to a subtle change in the way the compiler converts
+    between 64-bit and 32-bit values (e.g. during casting operations), which
+    reveals previously hidden bugs in client code.
+
+*   The tested filesystem used for this release (Linaro AArch64 OpenEmbedded
+    14.01) does not report progress correctly in the console. It only seems to
+    produce error output, not standard output. It otherwise appears to function
+    correctly. Other filesystem versions on the same software stack do not
+    exhibit the problem.
+
+*   The Makefile structure doesn't make it easy to separate out parts of the
+    Trusted Firmware for re-use in platform ports, for example if only BL3-1 is
+    required in a platform port. Also, dependency checking in the Makefile is
+    flawed.
+
+*   The firmware design documentation for the Test Secure-EL1 Payload (TSP) and
+    its dispatcher (TSPD) is incomplete. Similarly for the PSCI section.
+
+
+ARM Trusted Firmware - version 0.2
+==================================
+
+New features
+------------
+
+*   First source release.
+
+*   Code for the PSCI suspend feature is supplied, although this is not enabled
+    by default since there are known issues (see below).
+
+
+Issues resolved since last release
+----------------------------------
+
+*   The "psci" nodes in the FDTs provided in this release now fully comply
+    with the recommendations made in the PSCI specification.
+
+
+Known issues
+------------
+
+The following is a list of issues which are expected to be fixed in the future
+releases of the ARM Trusted Firmware.
+
+*   The TrustZone Address Space Controller (TZC-400) is not being programmed
+    yet. Use of model parameter `-C bp.secure_memory=1` is not supported.
+
+*   No support yet for secure world interrupt handling or for switching context
+    between secure and normal worlds in EL3.
+
+*   GICv3 support is experimental. The Linux kernel patches to support this are
+    not widely available. There are known issues with GICv3 initialization in
+    the ARM Trusted Firmware.
+
+*   Dynamic image loading is not available yet. The current image loader
+    implementation (used to load BL2 and all subsequent images) has some
+    limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead
+    to loading errors, even if the images should theoretically fit in memory.
+
+*   Although support for PSCI `CPU_SUSPEND` is present, it is not yet stable
+    and ready for use.
+
+*   PSCI API calls `AFFINITY_INFO` & `PSCI_VERSION` are implemented but have not
+    been tested.
+
+*   The ARM Trusted Firmware make files result in all build artifacts being
+    placed in the root of the project. These should be placed in appropriate
+    sub-directories.
+
+*   The compilation of ARM Trusted Firmware is not free from compilation
+    warnings. Some of these warnings have not been investigated yet so they
+    could mask real bugs.
+
+*   The ARM Trusted Firmware currently uses toolchain/system include files like
+    stdio.h. It should provide versions of these within the project to maintain
+    compatibility between toolchains/systems.
+
+*   The PSCI code takes some locks in an incorrect sequence. This may cause
+    problems with suspend and hotplug in certain conditions.
+
+*   The Linux kernel used in this release is based on version 3.12-rc4. Using
+    this kernel with the ARM Trusted Firmware fails to start the file-system as
+    a RAM-disk. It fails to execute user-space `init` from the RAM-disk. As an
+    alternative, the VirtioBlock mechanism can be used to provide a file-system
+    to the kernel.
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved._
+
+[OP-TEE Dispatcher]:       ./optee-dispatcher.md
diff --git a/docs/cpu-specific-build-macros.md b/docs/cpu-specific-build-macros.md
new file mode 100644 (file)
index 0000000..2368fd2
--- /dev/null
@@ -0,0 +1,70 @@
+ARM CPU Specific Build Macros
+=============================
+
+Contents
+--------
+
+1.  [Introduction](#1--introduction)
+2.  [CPU Errata Workarounds](#2--cpu-errata-workarounds)
+3.  [CPU Specific optimizations](#3--cpu-specific-optimizations)
+
+
+1.  Introduction
+----------------
+
+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.
+
+2.  CPU Errata Workarounds
+--------------------------
+
+ARM Trusted Firmware 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. The errata workarounds are implemented for a particular revision
+or a set of processor revisions. This is checked by 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 is `ERRATA_<Processor name>_<ID>` where the `Processor name`
+is either `A57` for the `Cortex_A57` CPU or `A53` for `Cortex_A53` CPU.
+
+All workarounds are disabled by default. The platform is reponsible 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-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_813420`: This applies errata 813420 workaround to Cortex-A57
+     CPU. This needs to be enabled only for revision r0p0 of the CPU.
+
+3.  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.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._
diff --git a/docs/diagrams/non-sec-int-handling.png b/docs/diagrams/non-sec-int-handling.png
new file mode 100644 (file)
index 0000000..1a5f629
Binary files /dev/null and b/docs/diagrams/non-sec-int-handling.png differ
diff --git a/docs/diagrams/rt-svc-descs-layout.png b/docs/diagrams/rt-svc-descs-layout.png
new file mode 100644 (file)
index 0000000..1a9fa5b
Binary files /dev/null and b/docs/diagrams/rt-svc-descs-layout.png differ
diff --git a/docs/diagrams/sec-int-handling.png b/docs/diagrams/sec-int-handling.png
new file mode 100644 (file)
index 0000000..2ebbca4
Binary files /dev/null and b/docs/diagrams/sec-int-handling.png differ
diff --git a/docs/firmware-design.md b/docs/firmware-design.md
new file mode 100644 (file)
index 0000000..72525bd
--- /dev/null
@@ -0,0 +1,1807 @@
+ARM Trusted Firmware Design
+===========================
+
+Contents :
+
+1.  [Introduction](#1--introduction)
+2.  [Cold boot](#2--cold-boot)
+3.  [EL3 runtime services framework](#3--el3-runtime-services-framework)
+4.  [Power State Coordination Interface](#4--power-state-coordination-interface)
+5.  [Secure-EL1 Payloads and Dispatchers](#5--secure-el1-payloads-and-dispatchers)
+6.  [Crash Reporting in BL3-1](#6--crash-reporting-in-bl3-1)
+7.  [Guidelines for Reset Handlers](#7--guidelines-for-reset-handlers)
+8.  [CPU specific operations framework](#8--cpu-specific-operations-framework)
+9.  [Memory layout of BL images](#9-memory-layout-of-bl-images)
+10. [Firmware Image Package (FIP)](#10--firmware-image-package-fip)
+11. [Use of coherent memory in Trusted Firmware](#11--use-of-coherent-memory-in-trusted-firmware)
+12. [Code Structure](#12--code-structure)
+13. [References](#13--references)
+
+
+1.  Introduction
+----------------
+
+The ARM Trusted Firmware implements a subset of the Trusted Board Boot
+Requirements (TBBR) Platform Design Document (PDD) [1] for ARM reference
+platforms. The TBB sequence starts when the platform is powered on and runs up
+to the stage where it hands-off control to firmware running in the normal
+world in DRAM. This is the cold boot path.
+
+The ARM Trusted Firmware also implements the Power State Coordination Interface
+([PSCI]) PDD [2] as a runtime service. PSCI is the interface from normal world
+software to firmware implementing power management use-cases (for example,
+secondary CPU boot, hotplug and idle). Normal world software can access ARM
+Trusted Firmware runtime services via the ARM SMC (Secure Monitor Call)
+instruction. The SMC instruction must be used as mandated by the [SMC Calling
+Convention PDD][SMCCC] [3].
+
+The ARM Trusted Firmware implements a framework for configuring and managing
+interrupts generated in either security state. The details of the interrupt
+management framework and its design can be found in [ARM Trusted
+Firmware Interrupt Management Design guide][INTRG] [4].
+
+2.  Cold boot
+-------------
+
+The cold boot path starts when the platform is physically turned on. One of
+the CPUs released from reset is chosen as the primary CPU, and the remaining
+CPUs are considered secondary CPUs. The primary CPU is chosen through
+platform-specific means. The cold boot path is mainly executed by the primary
+CPU, other than essential CPU initialization executed by all CPUs. The
+secondary CPUs are kept in a safe platform-specific state until the primary
+CPU has performed enough initialization to boot them.
+
+The cold boot path in this implementation of the ARM Trusted Firmware is divided
+into five steps (in order of execution):
+
+*   Boot Loader stage 1 (BL1) _AP Trusted ROM_
+*   Boot Loader stage 2 (BL2) _Trusted Boot Firmware_
+*   Boot Loader stage 3-1 (BL3-1) _EL3 Runtime Firmware_
+*   Boot Loader stage 3-2 (BL3-2) _Secure-EL1 Payload_ (optional)
+*   Boot Loader stage 3-3 (BL3-3) _Non-trusted Firmware_
+
+ARM development platforms (Fixed Virtual Platforms (FVPs) and Juno) implement a
+combination of the following types of memory regions. Each bootloader stage uses
+one or more of these memory regions.
+
+*   Regions accessible from both non-secure and secure states. For example,
+    non-trusted SRAM, ROM and DRAM.
+*   Regions accessible from only the secure state. For example, trusted SRAM and
+    ROM. The FVPs also implement the trusted DRAM which is statically
+    configured. Additionally, the Base FVPs and Juno development platform
+    configure the TrustZone Controller (TZC) to create a region in the DRAM
+    which is accessible only from the secure state.
+
+
+The sections below provide the following details:
+
+*   initialization and execution of the first three stages during cold boot
+*   specification of the BL3-1 entrypoint requirements for use by alternative
+    Trusted Boot Firmware in place of the provided BL1 and BL2
+*   changes in BL3-1 behavior when using the `RESET_TO_BL31` option which
+    allows BL3-1 to run without BL1 and BL2
+
+
+### BL1
+
+This stage begins execution from the platform's reset vector at EL3. The reset
+address is platform dependent but it is usually located in a Trusted ROM area.
+The BL1 data section is copied to trusted SRAM at runtime.
+
+On the ARM FVP port, BL1 code starts execution from the reset vector at address
+`0x00000000` (trusted ROM). The BL1 data section is copied to the start of
+trusted SRAM at address `0x04000000`.
+
+On the Juno ARM development platform port, BL1 code starts execution at
+`0x0BEC0000` (FLASH). The BL1 data section is copied to trusted SRAM at address
+`0x04001000.
+
+The functionality implemented by this stage is as follows.
+
+#### Determination of boot path
+
+Whenever a CPU is released from reset, BL1 needs to distinguish between a warm
+boot and a cold boot. This is done using platform-specific mechanisms (see the
+`platform_get_entrypoint()` function in the [Porting Guide]). In the case of a
+warm boot, a CPU is expected to continue execution from a seperate
+entrypoint. In the case of a cold boot, the secondary CPUs are placed in a safe
+platform-specific state (see the `plat_secondary_cold_boot_setup()` function in
+the [Porting Guide]) while the primary CPU executes the remaining cold boot path
+as described in the following sections.
+
+#### Architectural initialization
+
+BL1 performs minimal architectural initialization as follows.
+
+*   Exception vectors
+
+    BL1 sets up simple exception vectors for both synchronous and asynchronous
+    exceptions. The default behavior upon receiving an exception is to populate
+    a status code in the general purpose register `X0` and call the
+    `plat_report_exception()` function (see the [Porting Guide]). The status
+    code is one of:
+
+        0x0 : Synchronous exception from Current EL with SP_EL0
+        0x1 : IRQ exception from Current EL with SP_EL0
+        0x2 : FIQ exception from Current EL with SP_EL0
+        0x3 : System Error exception from Current EL with SP_EL0
+        0x4 : Synchronous exception from Current EL with SP_ELx
+        0x5 : IRQ exception from Current EL with SP_ELx
+        0x6 : FIQ exception from Current EL with SP_ELx
+        0x7 : System Error exception from Current EL with SP_ELx
+        0x8 : Synchronous exception from Lower EL using aarch64
+        0x9 : IRQ exception from Lower EL using aarch64
+        0xa : FIQ exception from Lower EL using aarch64
+        0xb : System Error exception from Lower EL using aarch64
+        0xc : Synchronous exception from Lower EL using aarch32
+        0xd : IRQ exception from Lower EL using aarch32
+        0xe : FIQ exception from Lower EL using aarch32
+        0xf : System Error exception from Lower EL using aarch32
+
+    The `plat_report_exception()` implementation on the ARM FVP port programs
+    the Versatile Express System LED register in the following format to
+    indicate the occurence of an unexpected exception:
+
+        SYS_LED[0]   - Security state (Secure=0/Non-Secure=1)
+        SYS_LED[2:1] - Exception Level (EL3=0x3, EL2=0x2, EL1=0x1, EL0=0x0)
+        SYS_LED[7:3] - Exception Class (Sync/Async & origin). This is the value
+                       of the status code
+
+    A write to the LED register reflects in the System LEDs (S6LED0..7) in the
+    CLCD window of the FVP.
+
+    BL1 does not expect to receive any exceptions other than the SMC exception.
+    For the latter, BL1 installs a simple stub. The stub expects to receive
+    only a single type of SMC (determined by its function ID in the general
+    purpose register `X0`). This SMC is raised by BL2 to make BL1 pass control
+    to BL3-1 (loaded by BL2) at EL3. Any other SMC leads to an assertion
+    failure.
+
+*   CPU initialization
+
+    BL1 calls the `reset_handler()` function which in turn calls the CPU
+    specific reset handler function (see the section: "CPU specific operations
+    framework").
+
+*   MMU setup
+
+    BL1 sets up EL3 memory translation by creating page tables to cover the
+    first 4GB of physical address space. This covers all the memories and
+    peripherals needed by BL1.
+
+*   Control register setup
+    -   `SCTLR_EL3`. Instruction cache is enabled by setting the `SCTLR_EL3.I`
+        bit. Alignment and stack alignment checking is enabled by setting the
+        `SCTLR_EL3.A` and `SCTLR_EL3.SA` bits. Exception endianness is set to
+        little-endian by clearing the `SCTLR_EL3.EE` bit.
+
+    -  `SCR_EL3`. The register width of the next lower exception level is set to
+        AArch64 by setting the `SCR.RW` bit.
+
+    -   `CPTR_EL3`. Accesses to the `CPACR_EL1` register from EL1 or EL2, or the
+        `CPTR_EL2` register from EL2 are configured to not trap to EL3 by
+        clearing the `CPTR_EL3.TCPAC` bit. Access to the trace functionality is
+        configured not to trap to EL3 by clearing the `CPTR_EL3.TTA` bit.
+        Instructions that access the registers associated with Floating Point
+        and Advanced SIMD execution are configured to not trap to EL3 by
+        clearing the `CPTR_EL3.TFP` bit.
+
+#### Platform initialization
+
+BL1 enables issuing of snoop and DVM (Distributed Virtual Memory) requests from
+the CCI-400 slave interface corresponding to the cluster that includes the
+primary CPU. BL1 also initializes UART0 (PL011 console), which enables access to
+the `printf` family of functions in BL1.
+
+#### BL2 image load and execution
+
+BL1 execution continues as follows:
+
+1.  BL1 determines the amount of free trusted SRAM memory available by
+    calculating the extent of its own data section, which also resides in
+    trusted SRAM. BL1 loads a BL2 raw binary image from platform storage, at a
+    platform-specific base address. If the BL2 image file is not present or if
+    there is not enough free trusted SRAM the following error message is
+    printed:
+
+        "Failed to load boot loader stage 2 (BL2) firmware."
+
+    If the load is successful, BL1 updates the limits of the remaining free
+    trusted SRAM. It also populates information about the amount of trusted
+    SRAM used by the BL2 image. The exact load location of the image is
+    provided as a base address in the platform header. Further description of
+    the memory layout can be found later in this document.
+
+2.  BL1 prints the following string from the primary CPU to indicate successful
+    execution of the BL1 stage:
+
+        "Booting trusted firmware boot loader stage 1"
+
+3.  BL1 passes control to the BL2 image at Secure EL1, starting from its load
+    address.
+
+4.  BL1 also passes information about the amount of trusted SRAM used and
+    available for use. This information is populated at a platform-specific
+    memory address.
+
+
+### BL2
+
+BL1 loads and passes control to BL2 at Secure-EL1. BL2 is linked against and
+loaded at a platform-specific base address (more information can be found later
+in this document). The functionality implemented by BL2 is as follows.
+
+#### Architectural initialization
+
+BL2 performs minimal architectural initialization required for subsequent
+stages of the ARM Trusted Firmware and normal world software. It sets up
+Secure EL1 memory translation by creating page tables to address the first 4GB
+of the physical address space in a similar way to BL1. EL1 and EL0 are given
+access to Floating Point & Advanced SIMD registers by clearing the `CPACR.FPEN`
+bits.
+
+#### Platform initialization
+
+BL2 copies the information regarding the trusted SRAM populated by BL1 using a
+platform-specific mechanism. It calculates the limits of DRAM (main memory)
+to determine whether there is enough space to load the BL3-3 image. A platform
+defined base address is used to specify the load address for the BL3-1 image.
+It also defines the extents of memory available for use by the BL3-2 image.
+BL2 also initializes UART0 (PL011 console), which enables  access to the
+`printf` family of functions in BL2. Platform security is initialized to allow
+access to controlled components. The storage abstraction layer is initialized
+which is used to load further bootloader images.
+
+#### BL3-0 (System Control Processor Firmware) image load
+
+Some systems have a separate System Control Processor (SCP) for power, clock,
+reset and system control. BL2 loads the optional BL3-0 image from platform
+storage into a platform-specific region of secure memory. The subsequent
+handling of BL3-0 is platform specific. For example, on the Juno ARM development
+platform port the image is transferred into SCP memory using the SCPI protocol
+after being loaded in the trusted SRAM memory at address `0x04009000`. The SCP
+executes BL3-0 and signals to the Application Processor (AP) for BL2 execution
+to continue.
+
+#### BL3-1 (EL3 Runtime Firmware) image load
+
+BL2 loads the BL3-1 image from platform storage into a platform-specific address
+in trusted SRAM. If there is not enough memory to load the image or image is
+missing it leads to an assertion failure. If the BL3-1 image loads successfully,
+BL2 updates the amount of trusted SRAM used and available for use by BL3-1.
+This information is populated at a platform-specific memory address.
+
+#### BL3-2 (Secure-EL1 Payload) image load
+
+BL2 loads the optional BL3-2 image from platform storage into a platform-
+specific region of secure memory. The image executes in the secure world. BL2
+relies on BL3-1 to pass control to the BL3-2 image, if present. Hence, BL2
+populates a platform-specific area of memory with the entrypoint/load-address
+of the BL3-2 image. The value of the Saved Processor Status Register (`SPSR`)
+for entry into BL3-2 is not determined by BL2, it is initialized by the
+Secure-EL1 Payload Dispatcher (see later) within BL3-1, which is responsible for
+managing interaction with BL3-2. This information is passed to BL3-1.
+
+#### BL3-3 (Non-trusted Firmware) image load
+
+BL2 loads the BL3-3 image (e.g. UEFI or other test or boot software) from
+platform storage into non-secure memory as defined by the platform.
+
+BL2 relies on BL3-1 to pass control to BL3-3 once secure state initialization is
+complete. Hence, BL2 populates a platform-specific area of memory with the
+entrypoint and Saved Program Status Register (`SPSR`) of the normal world
+software image. The entrypoint is the load address of the BL3-3 image. The
+`SPSR` is determined as specified in Section 5.13 of the [PSCI PDD] [PSCI]. This
+information is passed to BL3-1.
+
+#### BL3-1 (EL3 Runtime Firmware) execution
+
+BL2 execution continues as follows:
+
+1.  BL2 passes control back to BL1 by raising an SMC, providing BL1 with the
+    BL3-1 entrypoint. The exception is handled by the SMC exception handler
+    installed by BL1.
+
+2.  BL1 turns off the MMU and flushes the caches. It clears the
+    `SCTLR_EL3.M/I/C` bits, flushes the data cache to the point of coherency
+    and invalidates the TLBs.
+
+3.  BL1 passes control to BL3-1 at the specified entrypoint at EL3.
+
+
+### BL3-1
+
+The image for this stage is loaded by BL2 and BL1 passes control to BL3-1 at
+EL3. BL3-1 executes solely in trusted SRAM. BL3-1 is linked against and
+loaded at a platform-specific base address (more information can be found later
+in this document). The functionality implemented by BL3-1 is as follows.
+
+#### Architectural initialization
+
+Currently, BL3-1 performs a similar architectural initialization to BL1 as
+far as system register settings are concerned. Since BL1 code resides in ROM,
+architectural initialization in BL3-1 allows override of any previous
+initialization done by BL1. BL3-1 creates page tables to address the first
+4GB of physical address space and initializes the MMU accordingly. It initializes
+a buffer of frequently used pointers, called per-CPU pointer cache, in memory for
+faster access. Currently the per-CPU pointer cache contains only the pointer
+to crash stack. It then replaces the exception vectors populated by BL1 with its
+own. BL3-1 exception vectors implement more elaborate support for
+handling SMCs since this is the only mechanism to access the runtime services
+implemented by BL3-1 (PSCI for example). BL3-1 checks each SMC for validity as
+specified by the [SMC calling convention PDD][SMCCC] before passing control to
+the required SMC handler routine. BL3-1 programs the `CNTFRQ_EL0` register with
+the clock frequency of the system counter, which is provided by the platform.
+
+#### Platform initialization
+
+BL3-1 performs detailed platform initialization, which enables normal world
+software to function correctly. It also retrieves entrypoint information for
+the BL3-3 image loaded by BL2 from the platform defined memory address populated
+by BL2. BL3-1 also initializes UART0 (PL011 console), which enables
+access to the `printf` family of functions in BL3-1.  It enables the system
+level implementation of the generic timer through the memory mapped interface.
+
+* GICv2 initialization:
+
+    -   Enable group0 interrupts in the GIC CPU interface.
+    -   Configure group0 interrupts to be asserted as FIQs.
+    -   Disable the legacy interrupt bypass mechanism.
+    -   Configure the priority mask register to allow interrupts of all
+        priorities to be signaled to the CPU interface.
+    -   Mark SGIs 8-15, the secure physical timer interrupt (#29) and the
+        trusted watchdog interrupt (#56) as group0 (secure).
+    -   Target the trusted watchdog interrupt to CPU0.
+    -   Enable these group0 interrupts in the GIC distributor.
+    -   Configure all other interrupts as group1 (non-secure).
+    -   Enable signaling of group0 interrupts in the GIC distributor.
+
+*   GICv3 initialization:
+
+    If a GICv3 implementation is available in the platform, BL3-1 initializes
+    the GICv3 in GICv2 emulation mode with settings as described for GICv2
+    above.
+
+*   Power management initialization:
+
+    BL3-1 implements a state machine to track CPU and cluster state. The state
+    can be one of `OFF`, `ON_PENDING`, `SUSPEND` or `ON`. All secondary CPUs are
+    initially in the `OFF` state. The cluster that the primary CPU belongs to is
+    `ON`; any other cluster is `OFF`. BL3-1 initializes the data structures that
+    implement the state machine, including the locks that protect them. BL3-1
+    accesses the state of a CPU or cluster immediately after reset and before
+    the data cache is enabled in the warm boot path. It is not currently
+    possible to use 'exclusive' based spinlocks, therefore BL3-1 uses locks
+    based on Lamport's Bakery algorithm instead. BL3-1 allocates these locks in
+    device memory by default.
+
+*   Runtime services initialization:
+
+    The runtime service framework and its initialization is described in the
+    "EL3 runtime services framework" section below.
+
+    Details about the PSCI service are provided in the "Power State Coordination
+    Interface" section below.
+
+*   BL3-2 (Secure-EL1 Payload) image initialization
+
+    If a BL3-2 image is present then there must be a matching Secure-EL1 Payload
+    Dispatcher (SPD) service (see later for details). During initialization
+    that service  must register a function to carry out initialization of BL3-2
+    once the runtime services are fully initialized. BL3-1 invokes such a
+    registered function to initialize BL3-2 before running BL3-3.
+
+    Details on BL3-2 initialization and the SPD's role are described in the
+    "Secure-EL1 Payloads and Dispatchers" section below.
+
+*   BL3-3 (Non-trusted Firmware) execution
+
+    BL3-1 initializes the EL2 or EL1 processor context for normal-world cold
+    boot, ensuring that no secure state information finds its way into the
+    non-secure execution state. BL3-1 uses the entrypoint information provided
+    by BL2 to jump to the Non-trusted firmware image (BL3-3) at the highest
+    available Exception Level (EL2 if available, otherwise EL1).
+
+
+### Using alternative Trusted Boot Firmware in place of BL1 and BL2
+
+Some platforms have existing implementations of Trusted Boot Firmware that
+would like to use ARM Trusted Firmware BL3-1 for the EL3 Runtime Firmware. To
+enable this firmware architecture it is important to provide a fully documented
+and stable interface between the Trusted Boot Firmware and BL3-1.
+
+Future changes to the BL3-1 interface will be done in a backwards compatible
+way, and this enables these firmware components to be independently enhanced/
+updated to develop and exploit new functionality.
+
+#### Required CPU state when calling `bl31_entrypoint()` during cold boot
+
+This function must only be called by the primary CPU, if this is called by any
+other CPU the firmware will abort.
+
+On entry to this function the calling primary CPU must be executing in AArch64
+EL3, little-endian data access, and all interrupt sources masked:
+
+    PSTATE.EL = 3
+    PSTATE.RW = 1
+    PSTATE.DAIF = 0xf
+    SCTLR_EL3.EE = 0
+
+X0 and X1 can be used to pass information from the Trusted Boot Firmware to the
+platform code in BL3-1:
+
+    X0 : Reserved for common Trusted Firmware information
+    X1 : Platform specific information
+
+BL3-1 zero-init sections (e.g. `.bss`) should not contain valid data on entry,
+these will be zero filled prior to invoking platform setup code.
+
+##### Use of the X0 and X1 parameters
+
+The parameters are platform specific and passed from `bl31_entrypoint()` to
+`bl31_early_platform_setup()`. The value of these parameters is never directly
+used by the common BL3-1 code.
+
+The convention is that `X0` conveys information regarding the BL3-1, BL3-2 and
+BL3-3 images from the Trusted Boot firmware and `X1` can be used for other
+platform specific purpose. This convention allows platforms which use ARM
+Trusted Firmware's BL1 and BL2 images to transfer additional platform specific
+information from Secure Boot without conflicting with future evolution of the
+Trusted Firmware using `X0` to pass a `bl31_params` structure.
+
+BL3-1 common and SPD initialization code depends on image and entrypoint
+information about BL3-3 and BL3-2, which is provided via BL3-1 platform APIs.
+This information is required until the start of execution of BL3-3. This
+information can be provided in a platform defined manner, e.g. compiled into
+the platform code in BL3-1, or provided in a platform defined memory location
+by the Trusted Boot firmware, or passed from the Trusted Boot Firmware via the
+Cold boot Initialization parameters. This data may need to be cleaned out of
+the CPU caches if it is provided by an earlier boot stage and then accessed by
+BL3-1 platform code before the caches are enabled.
+
+ARM Trusted Firmware's BL2 implementation passes a `bl31_params` structure in
+`X0` and the FVP port interprets this in the BL3-1 platform code.
+
+##### MMU, Data caches & Coherency
+
+BL3-1 does not depend on the enabled state of the MMU, data caches or
+interconnect coherency on entry to `bl31_entrypoint()`. If these are disabled
+on entry, these should be enabled during `bl31_plat_arch_setup()`.
+
+##### Data structures used in the BL3-1 cold boot interface
+
+These structures are designed to support compatibility and independent
+evolution of the structures and the firmware images. For example, a version of
+BL3-1 that can interpret the BL3-x image information from different versions of
+BL2, a platform that uses an extended entry_point_info structure to convey
+additional register information to BL3-1, or a ELF image loader that can convey
+more details about the firmware images.
+
+To support these scenarios the structures are versioned and sized, which enables
+BL3-1 to detect which information is present and respond appropriately. The
+`param_header` is defined to capture this information:
+
+    typedef struct param_header {
+        uint8_t type;       /* type of the structure */
+        uint8_t version;    /* version of this structure */
+        uint16_t size;      /* size of this structure in bytes */
+        uint32_t attr;      /* attributes: unused bits SBZ */
+    } param_header_t;
+
+The structures using this format are `entry_point_info`, `image_info` and
+`bl31_params`. The code that allocates and populates these structures must set
+the header fields appropriately, and the `SET_PARA_HEAD()` a macro is defined
+to simplify this action.
+
+#### Required CPU state for BL3-1 Warm boot initialization
+
+When requesting a CPU power-on, or suspending a running CPU, ARM Trusted
+Firmware provides the platform power management code with a Warm boot
+initialization entry-point, to be invoked by the CPU immediately after the
+reset handler. On entry to the Warm boot initialization function the calling
+CPU must be in AArch64 EL3, little-endian data access and all interrupt sources
+masked:
+
+    PSTATE.EL = 3
+    PSTATE.RW = 1
+    PSTATE.DAIF = 0xf
+    SCTLR_EL3.EE = 0
+
+The PSCI implementation will initialize the processor state and ensure that the
+platform power management code is then invoked as required to initialize all
+necessary system, cluster and CPU resources.
+
+
+### Using BL3-1 as the CPU reset vector
+
+On some platforms the runtime firmware (BL3-x images) for the application
+processors are loaded by trusted firmware running on a secure system processor
+on the SoC, rather than by BL1 and BL2 running on the primary application
+processor. For this type of SoC it is desirable for the application processor
+to always reset to BL3-1 which eliminates the need for BL1 and BL2.
+
+ARM Trusted Firmware provides a build-time option `RESET_TO_BL31` that includes
+some additional logic in the BL3-1 entrypoint to support this use case.
+
+In this configuration, the platform's Trusted Boot Firmware must ensure that
+BL3-1 is loaded to its runtime address, which must match the CPU's RVBAR reset
+vector address, before the application processor is powered on. Additionally,
+platform software is responsible for loading the other BL3-x images required and
+providing entry point information for them to BL3-1. Loading these images might
+be done by the Trusted Boot Firmware or by platform code in BL3-1.
+
+The ARM FVP port supports the `RESET_TO_BL31` configuration, in which case the
+`bl31.bin` image must be loaded to its run address in Trusted SRAM and all CPU
+reset vectors be changed from the default `0x0` to this run address. See the
+[User Guide] for details of running the FVP models in this way.
+
+This configuration requires some additions and changes in the BL3-1
+functionality:
+
+#### Determination of boot path
+
+In this configuration, BL3-1 uses the same reset framework and code as the one
+described for BL1 above. On a warm boot a CPU is directed to the PSCI
+implementation via a platform defined mechanism. On a cold boot, the platform
+must place any secondary CPUs into a safe state while the primary CPU executes
+a modified BL3-1 initialization, as described below.
+
+#### Architectural initialization
+
+As the first image to execute in this configuration BL3-1 must ensure that
+interconnect coherency is enabled (if required) before enabling the MMU.
+
+#### Platform initialization
+
+In this configuration, when the CPU resets to BL3-1 there are no parameters
+that can be passed in registers by previous boot stages. Instead, the platform
+code in BL3-1 needs to know, or be able to determine, the location of the BL3-2
+(if required) and BL3-3 images and provide this information in response to the
+`bl31_plat_get_next_image_ep_info()` function.
+
+As the first image to execute in this configuration BL3-1 must also ensure that
+any security initialisation, for example programming a TrustZone address space
+controller, is carried out during early platform initialisation.
+
+
+3.  EL3 runtime services framework
+----------------------------------
+
+Software executing in the non-secure state and in the secure state at exception
+levels lower than EL3 will request runtime services using the Secure Monitor
+Call (SMC) instruction. These requests will follow the convention described in
+the SMC Calling Convention PDD ([SMCCC]). The [SMCCC] assigns function
+identifiers to each SMC request and describes how arguments are passed and
+returned.
+
+The EL3 runtime services framework enables the development of services by
+different providers that can be easily integrated into final product firmware.
+The following sections describe the framework which facilitates the
+registration, initialization and use of runtime services in EL3 Runtime
+Firmware (BL3-1).
+
+The design of the runtime services depends heavily on the concepts and
+definitions described in the [SMCCC], in particular SMC Function IDs, Owning
+Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and SMC64 calling
+conventions. Please refer to that document for more detailed explanation of
+these terms.
+
+The following runtime services are expected to be implemented first. They have
+not all been instantiated in the current implementation.
+
+1.  Standard service calls
+
+    This service is for management of the entire system. The Power State
+    Coordination Interface ([PSCI]) is the first set of standard service calls
+    defined by ARM (see PSCI section later).
+
+    NOTE: Currently this service is called PSCI since there are no other
+    defined standard service calls.
+
+2.  Secure-EL1 Payload Dispatcher service
+
+    If a system runs a Trusted OS or other Secure-EL1 Payload (SP) then
+    it also requires a _Secure Monitor_ at EL3 to switch the EL1 processor
+    context between the normal world (EL1/EL2) and trusted world (Secure-EL1).
+    The Secure Monitor will make these world switches in response to SMCs. The
+    [SMCCC] provides for such SMCs with the Trusted OS Call and Trusted
+    Application Call OEN ranges.
+
+    The interface between the EL3 Runtime Firmware and the Secure-EL1 Payload is
+    not defined by the [SMCCC] or any other standard. As a result, each
+    Secure-EL1 Payload requires a specific Secure Monitor that runs as a runtime
+    service - within ARM Trusted Firmware this service is referred to as the
+    Secure-EL1 Payload Dispatcher (SPD).
+
+    ARM Trusted Firmware provides a Test Secure-EL1 Payload (TSP) and its
+    associated Dispatcher (TSPD). Details of SPD design and TSP/TSPD operation
+    are described in the "Secure-EL1 Payloads and Dispatchers" section below.
+
+3.  CPU implementation service
+
+    This service will provide an interface to CPU implementation specific
+    services for a given platform e.g. access to processor errata workarounds.
+    This service is currently unimplemented.
+
+Additional services for ARM Architecture, SiP and OEM calls can be implemented.
+Each implemented service handles a range of SMC function identifiers as
+described in the [SMCCC].
+
+
+### Registration
+
+A runtime service is registered using the `DECLARE_RT_SVC()` macro, specifying
+the name of the service, the range of OENs covered, the type of service and
+initialization and call handler functions. This macro instantiates a `const
+struct rt_svc_desc` for the service with these details (see `runtime_svc.h`).
+This structure is allocated in a special ELF section `rt_svc_descs`, enabling
+the framework to find all service descriptors included into BL3-1.
+
+The specific service for a SMC Function is selected based on the OEN and call
+type of the Function ID, and the framework uses that information in the service
+descriptor to identify the handler for the SMC Call.
+
+The service descriptors do not include information to identify the precise set
+of SMC function identifiers supported by this service implementation, the
+security state from which such calls are valid nor the capability to support
+64-bit and/or 32-bit callers (using SMC32 or SMC64). Responding appropriately
+to these aspects of a SMC call is the responsibility of the service
+implementation, the framework is focused on integration of services from
+different providers and minimizing the time taken by the framework before the
+service handler is invoked.
+
+Details of the parameters, requirements and behavior of the initialization and
+call handling functions are provided in the following sections.
+
+
+### Initialization
+
+`runtime_svc_init()` in `runtime_svc.c` initializes the runtime services
+framework running on the primary CPU during cold boot as part of the BL3-1
+initialization. This happens prior to initializing a Trusted OS and running
+Normal world boot firmware that might in turn use these services.
+Initialization involves validating each of the declared runtime service
+descriptors, calling the service initialization function and populating the
+index used for runtime lookup of the service.
+
+The BL3-1 linker script collects all of the declared service descriptors into a
+single array and defines symbols that allow the framework to locate and traverse
+the array, and determine its size.
+
+The framework does basic validation of each descriptor to halt firmware
+initialization if service declaration errors are detected. The framework does
+not check descriptors for the following error conditions, and may behave in an
+unpredictable manner under such scenarios:
+
+1.  Overlapping OEN ranges
+2.  Multiple descriptors for the same range of OENs and `call_type`
+3.  Incorrect range of owning entity numbers for a given `call_type`
+
+Once validated, the service `init()` callback is invoked. This function carries
+out any essential EL3 initialization before servicing requests. The `init()`
+function is only invoked on the primary CPU during cold boot. If the service
+uses per-CPU data this must either be initialized for all CPUs during this call,
+or be done lazily when a CPU first issues an SMC call to that service. If
+`init()` returns anything other than `0`, this is treated as an initialization
+error and the service is ignored: this does not cause the firmware to halt.
+
+The OEN and call type fields present in the SMC Function ID cover a total of
+128 distinct services, but in practice a single descriptor can cover a range of
+OENs, e.g. SMCs to call a Trusted OS function. To optimize the lookup of a
+service handler, the framework uses an array of 128 indices that map every
+distinct OEN/call-type combination either to one of the declared services or to
+indicate the service is not handled. This `rt_svc_descs_indices[]` array is
+populated for all of the OENs covered by a service after the service `init()`
+function has reported success. So a service that fails to initialize will never
+have it's `handle()` function invoked.
+
+The following figure shows how the `rt_svc_descs_indices[]` index maps the SMC
+Function ID call type and OEN onto a specific service handler in the
+`rt_svc_descs[]` array.
+
+![Image 1](diagrams/rt-svc-descs-layout.png?raw=true)
+
+
+### Handling an SMC
+
+When the EL3 runtime services framework receives a Secure Monitor Call, the SMC
+Function ID is passed in W0 from the lower exception level (as per the
+[SMCCC]). If the calling register width is AArch32, it is invalid to invoke an
+SMC Function which indicates the SMC64 calling convention: such calls are
+ignored and return the Unknown SMC Function Identifier result code `0xFFFFFFFF`
+in R0/X0.
+
+Bit[31] (fast/standard call) and bits[29:24] (owning entity number) of the SMC
+Function ID are combined to index into the `rt_svc_descs_indices[]` array. The
+resulting value might indicate a service that has no handler, in this case the
+framework will also report an Unknown SMC Function ID. Otherwise, the value is
+used as a further index into the `rt_svc_descs[]` array to locate the required
+service and handler.
+
+The service's `handle()` callback is provided with five of the SMC parameters
+directly, the others are saved into memory for retrieval (if needed) by the
+handler. The handler is also provided with an opaque `handle` for use with the
+supporting library for parameter retrieval, setting return values and context
+manipulation; and with `flags` indicating the security state of the caller. The
+framework finally sets up the execution stack for the handler, and invokes the
+services `handle()` function.
+
+On return from the handler the result registers are populated in X0-X3 before
+restoring the stack and CPU state and returning from the original SMC.
+
+
+4.  Power State Coordination Interface
+--------------------------------------
+
+TODO: Provide design walkthrough of PSCI implementation.
+
+The PSCI v1.0 specification categorizes APIs as optional and mandatory. All the
+mandatory APIs in PSCI v1.0 and all the APIs in PSCI v0.2 draft specification
+[Power State Coordination Interface PDD] [PSCI] are implemented. The table lists
+the PSCI v1.0 APIs and their support in generic code.
+
+An API implementation might have a dependency on platform code e.g. CPU_SUSPEND
+requires the platform to export a part of the implementation. Hence the level
+of support of the mandatory APIs depends upon the support exported by the
+platform port as well. The Juno and FVP (all variants) platforms export all the
+required support.
+
+| PSCI v1.0 API         |Supported| Comments                                  |
+|:----------------------|:--------|:------------------------------------------|
+|`PSCI_VERSION`         | Yes     | The version returned is 1.0               |
+|`CPU_SUSPEND`          | Yes*    | The original `power_state` format is used |
+|`CPU_OFF`              | Yes*    |                                           |
+|`CPU_ON`               | Yes*    |                                           |
+|`AFFINITY_INFO`        | Yes     |                                           |
+|`MIGRATE`              | Yes**   |                                           |
+|`MIGRATE_INFO_TYPE`    | Yes**   |                                           |
+|`MIGRATE_INFO_CPU`     | Yes**   |                                           |
+|`SYSTEM_OFF`           | Yes*    |                                           |
+|`SYSTEM_RESET`         | Yes*    |                                           |
+|`PSCI_FEATURES`        | Yes     |                                           |
+|`CPU_FREEZE`           | No      |                                           |
+|`CPU_DEFAULT_SUSPEND`  | No      |                                           |
+|`CPU_HW_STATE`         | No      |                                           |
+|`SYSTEM_SUSPEND`       | Yes*    |                                           |
+|`PSCI_SET_SUSPEND_MODE`| No      |                                           |
+|`PSCI_STAT_RESIDENCY`  | No      |                                           |
+|`PSCI_STAT_COUNT`      | No      |                                           |
+
+*Note : These PSCI APIs require platform power management hooks to be
+registered with the generic PSCI code to be supported.
+
+**Note : These PSCI APIs require appropriate Secure Payload Dispatcher
+hooks to be registered with the generic PSCI code to be supported.
+
+
+5.  Secure-EL1 Payloads and Dispatchers
+---------------------------------------
+
+On a production system that includes a Trusted OS running in Secure-EL1/EL0,
+the Trusted OS is coupled with a companion runtime service in the BL3-1
+firmware. This service is responsible for the initialisation of the Trusted
+OS and all communications with it. The Trusted OS is the BL3-2 stage of the
+boot flow in ARM Trusted Firmware. The firmware will attempt to locate, load
+and execute a BL3-2 image.
+
+ARM Trusted Firmware uses a more general term for the BL3-2 software that runs
+at Secure-EL1 - the _Secure-EL1 Payload_ - as it is not always a Trusted OS.
+
+The ARM Trusted Firmware provides a Test Secure-EL1 Payload (TSP) and a Test
+Secure-EL1 Payload Dispatcher (TSPD) service as an example of how a Trusted OS
+is supported on a production system using the Runtime Services Framework. On
+such a system, the Test BL3-2 image and service are replaced by the Trusted OS
+and its dispatcher service. The ARM Trusted Firmware build system expects that
+the dispatcher will define the build flag `NEED_BL32` to enable it to include
+the BL3-2 in the build either as a binary or to compile from source depending
+on whether the `BL32` build option is specified or not.
+
+The TSP runs in Secure-EL1. It is designed to demonstrate synchronous
+communication with the normal-world software running in EL1/EL2. Communication
+is initiated by the normal-world software
+
+*   either directly through a Fast SMC (as defined in the [SMCCC])
+
+*   or indirectly through a [PSCI] SMC. The [PSCI] implementation in turn
+    informs the TSPD about the requested power management operation. This allows
+    the TSP to prepare for or respond to the power state change
+
+The TSPD service is responsible for.
+
+*   Initializing the TSP
+
+*   Routing requests and responses between the secure and the non-secure
+    states during the two types of communications just described
+
+### Initializing a BL3-2 Image
+
+The Secure-EL1 Payload Dispatcher (SPD) service is responsible for initializing
+the BL3-2 image. It needs access to the information passed by BL2 to BL3-1 to do
+so. This is provided by:
+
+    entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t);
+
+which returns a reference to the `entry_point_info` structure corresponding to
+the image which will be run in the specified security state. The SPD uses this
+API to get entry point information for the SECURE image, BL3-2.
+
+In the absence of a BL3-2 image, BL3-1 passes control to the normal world
+bootloader image (BL3-3). When the BL3-2 image is present, it is typical
+that the SPD wants control to be passed to BL3-2 first and then later to BL3-3.
+
+To do this the SPD has to register a BL3-2 initialization function during
+initialization of the SPD service. The BL3-2 initialization function has this
+prototype:
+
+    int32_t init();
+
+and is registered using the `bl31_register_bl32_init()` function.
+
+Trusted Firmware supports two approaches for the SPD to pass control to BL3-2
+before returning through EL3 and running the non-trusted firmware (BL3-3):
+
+1.  In the BL3-2 setup function, use `bl31_set_next_image_type()` to
+    request that the exit from `bl31_main()` is to the BL3-2 entrypoint in
+    Secure-EL1. BL3-1 will exit to BL3-2 using the asynchronous method by
+    calling bl31_prepare_next_image_entry() and el3_exit().
+
+    When the BL3-2 has completed initialization at Secure-EL1, it returns to
+    BL3-1 by issuing an SMC, using a Function ID allocated to the SPD. On
+    receipt of this SMC, the SPD service handler should switch the CPU context
+    from trusted to normal world and use the `bl31_set_next_image_type()` and
+    `bl31_prepare_next_image_entry()` functions to set up the initial return to
+    the normal world firmware BL3-3. On return from the handler the framework
+    will exit to EL2 and run BL3-3.
+
+2.  The BL3-2 setup function registers a initialization function using
+    `bl31_register_bl32_init()` which provides a SPD-defined mechanism to
+    invoke a 'world-switch synchronous call' to Secure-EL1 to run the BL3-2
+    entrypoint.
+    NOTE: The Test SPD service included with the Trusted Firmware provides one
+    implementation of such a mechanism.
+
+    On completion BL3-2 returns control to BL3-1 via a SMC, and on receipt the
+    SPD service handler invokes the synchronous call return mechanism to return
+    to the BL3-2 initialization function. On return from this function,
+    `bl31_main()` will set up the return to the normal world firmware BL3-3 and
+    continue the boot process in the normal world.
+
+
+6.  Crash Reporting in BL3-1
+----------------------------
+
+The BL3-1 implements a scheme for reporting the processor state when an unhandled
+exception is encountered. The reporting mechanism attempts to preserve all the
+register contents and report it via the default serial output. The general purpose
+registers, EL3, Secure EL1 and some EL2 state registers are reported.
+
+A dedicated per-CPU crash stack is maintained by BL3-1 and this is retrieved via
+the per-CPU pointer cache. The implementation attempts to minimise the memory
+required for this feature. The file `crash_reporting.S` contains the
+implementation for crash reporting.
+
+The sample crash output is shown below.
+
+    x0 :0x000000004F00007C
+    x1 :0x0000000007FFFFFF
+    x2 :0x0000000004014D50
+    x3 :0x0000000000000000
+    x4 :0x0000000088007998
+    x5 :0x00000000001343AC
+    x6 :0x0000000000000016
+    x7 :0x00000000000B8A38
+    x8 :0x00000000001343AC
+    x9 :0x00000000000101A8
+    x10        :0x0000000000000002
+    x11        :0x000000000000011C
+    x12        :0x00000000FEFDC644
+    x13        :0x00000000FED93FFC
+    x14        :0x0000000000247950
+    x15        :0x00000000000007A2
+    x16        :0x00000000000007A4
+    x17        :0x0000000000247950
+    x18        :0x0000000000000000
+    x19        :0x00000000FFFFFFFF
+    x20        :0x0000000004014D50
+    x21        :0x000000000400A38C
+    x22        :0x0000000000247950
+    x23        :0x0000000000000010
+    x24        :0x0000000000000024
+    x25        :0x00000000FEFDC868
+    x26        :0x00000000FEFDC86A
+    x27        :0x00000000019EDEDC
+    x28        :0x000000000A7CFDAA
+    x29        :0x0000000004010780
+    x30        :0x000000000400F004
+    scr_el3    :0x0000000000000D3D
+    sctlr_el3  :0x0000000000C8181F
+    cptr_el3   :0x0000000000000000
+    tcr_el3    :0x0000000080803520
+    daif       :0x00000000000003C0
+    mair_el3   :0x00000000000004FF
+    spsr_el3   :0x00000000800003CC
+    elr_el3    :0x000000000400C0CC
+    ttbr0_el3  :0x00000000040172A0
+    esr_el3    :0x0000000096000210
+    sp_el3     :0x0000000004014D50
+    far_el3    :0x000000004F00007C
+    spsr_el1   :0x0000000000000000
+    elr_el1    :0x0000000000000000
+    spsr_abt   :0x0000000000000000
+    spsr_und   :0x0000000000000000
+    spsr_irq   :0x0000000000000000
+    spsr_fiq   :0x0000000000000000
+    sctlr_el1  :0x0000000030C81807
+    actlr_el1  :0x0000000000000000
+    cpacr_el1  :0x0000000000300000
+    csselr_el1 :0x0000000000000002
+    sp_el1     :0x0000000004028800
+    esr_el1    :0x0000000000000000
+    ttbr0_el1  :0x000000000402C200
+    ttbr1_el1  :0x0000000000000000
+    mair_el1   :0x00000000000004FF
+    amair_el1  :0x0000000000000000
+    tcr_el1    :0x0000000000003520
+    tpidr_el1  :0x0000000000000000
+    tpidr_el0  :0x0000000000000000
+    tpidrro_el0        :0x0000000000000000
+    dacr32_el2 :0x0000000000000000
+    ifsr32_el2 :0x0000000000000000
+    par_el1    :0x0000000000000000
+    far_el1    :0x0000000000000000
+    afsr0_el1  :0x0000000000000000
+    afsr1_el1  :0x0000000000000000
+    contextidr_el1     :0x0000000000000000
+    vbar_el1   :0x0000000004027000
+    cntp_ctl_el0       :0x0000000000000000
+    cntp_cval_el0      :0x0000000000000000
+    cntv_ctl_el0       :0x0000000000000000
+    cntv_cval_el0      :0x0000000000000000
+    cntkctl_el1        :0x0000000000000000
+    fpexc32_el2        :0x0000000004000700
+    sp_el0     :0x0000000004010780
+
+7.  Guidelines for Reset Handlers
+---------------------------------
+
+Trusted Firmware implements a framework that allows CPU and platform ports to
+perform actions immediately after a CPU is released from reset in both the cold
+and warm boot paths. This is done by calling the `reset_handler()` function in
+both the BL1 and BL3-1 images. It in turn calls the platform and CPU specific
+reset handling functions.
+
+Details for implementing a CPU specific reset handler can be found in
+Section 8. Details for implementing a platform specific reset handler can be
+found in the [Porting Guide](see the `plat_reset_handler()` function).
+
+When adding functionality to a reset handler, the following points should be
+kept in mind.
+
+1.   The first reset handler in the system exists either in a ROM image
+     (e.g. BL1), or BL3-1 if `RESET_TO_BL31` is true. This may be detected at
+     compile time using the constant `FIRST_RESET_HANDLER_CALL`.
+
+2.   When considering ROM images, it's important to consider non TF-based ROMs
+     and ROMs based on previous versions of the TF code.
+
+3.   If the functionality should be applied to a ROM and there is no possibility
+     of a ROM being used that does not apply the functionality (or equivalent),
+     then the functionality should be applied within a `#if
+     FIRST_RESET_HANDLER_CALL` block.
+
+4.   If the functionality should execute in BL3-1 in order to override or
+     supplement a ROM version of the functionality, then the functionality
+     should be applied in the `#else` part of a `#if FIRST_RESET_HANDLER_CALL`
+     block.
+
+5.   If the functionality should be applied to a ROM but there is a possibility
+     of ROMs being used that do not apply the functionality, then the
+     functionality should be applied outside of a `FIRST_RESET_HANDLER_CALL`
+     block, so that BL3-1 has an opportunity to apply the functionality instead.
+     In this case, additional code may be needed to cope with different ROMs
+     that do or do not apply the functionality.
+
+
+8.  CPU specific operations framework
+-----------------------------
+
+Certain aspects of the ARMv8 architecture are implementation defined,
+that is, certain behaviours are not architecturally defined, but must be defined
+and documented by individual processor implementations. The ARM Trusted
+Firmware implements a framework which categorises the common implementation
+defined behaviours and allows a processor to export its implementation of that
+behaviour. The categories are:
+
+1.  Processor specific reset sequence.
+
+2.  Processor specific power down sequences.
+
+3.  Processor specific register dumping as a part of crash reporting.
+
+Each of the above categories fulfils a different requirement.
+
+1.  allows any processor specific initialization before the caches and MMU
+    are turned on, like implementation of errata workarounds, entry into
+    the intra-cluster coherency domain etc.
+
+2.  allows each processor to implement the power down sequence mandated in
+    its Technical Reference Manual (TRM).
+
+3.  allows a processor to provide additional information to the developer
+    in the event of a crash, for example Cortex-A53 has registers which
+    can expose the data cache contents.
+
+Please note that only 2. is mandated by the TRM.
+
+The CPU specific operations framework scales to accommodate a large number of
+different CPUs during power down and reset handling. The platform can specify
+any CPU optimization it wants to enable for each CPU. It can also specify
+the CPU errata workarounds to be applied for each CPU type during reset
+handling by defining CPU errata compile time macros. Details on these macros
+can be found in the [cpu-specific-build-macros.md][CPUBM] file.
+
+The CPU specific operations framework depends on the `cpu_ops` structure which
+needs to be exported for each type of CPU in the platform. It is defined in
+`include/lib/cpus/aarch64/cpu_macros.S` and has the following fields : `midr`,
+`reset_func()`, `core_pwr_dwn()`, `cluster_pwr_dwn()` and `cpu_reg_dump()`.
+
+The CPU specific files in `lib/cpus` export a `cpu_ops` data structure with
+suitable handlers for that CPU.  For example, `lib/cpus/cortex_a53.S` exports
+the `cpu_ops` for Cortex-A53 CPU. According to the platform configuration,
+these CPU specific files must must be included in the build by the platform
+makefile. The generic CPU specific operations framework code exists in
+`lib/cpus/aarch64/cpu_helpers.S`.
+
+### CPU specific Reset Handling
+
+After a reset, the state of the CPU when it calls generic reset handler is:
+MMU turned off, both instruction and data caches turned off and not part
+of any coherency domain.
+
+The BL entrypoint code first invokes the `plat_reset_handler()` to allow
+the platform to perform any system initialization required and any system
+errata workarounds that needs to be applied. The `get_cpu_ops_ptr()` reads
+the current CPU midr, finds the matching `cpu_ops` entry in the `cpu_ops`
+array and returns it. Note that only the part number and implementer fields
+in midr are used to find the matching `cpu_ops` entry. The `reset_func()` in
+the returned `cpu_ops` is then invoked which executes the required reset
+handling for that CPU and also any errata workarounds enabled by the platform.
+This function must preserve the values of general purpose registers x20 to x29.
+
+Refer to Section "Guidelines for Reset Handlers" for general guidelines
+regarding placement of code in a reset handler.
+
+### CPU specific power down sequence
+
+During the BL3-1 initialization sequence, the pointer to the matching `cpu_ops`
+entry is stored in per-CPU data by `init_cpu_ops()` so that it can be quickly
+retrieved during power down sequences.
+
+The PSCI service, upon receiving a power down request, determines the highest
+affinity level at which to execute power down sequence for a particular CPU and
+invokes the corresponding 'prepare' power down handler in the CPU specific
+operations framework. For example, when a CPU executes a power down for affinity
+level 0, the `prepare_core_pwr_dwn()` retrieves the `cpu_ops` pointer from the
+per-CPU data and the corresponding `core_pwr_dwn()` is invoked. Similarly when
+a CPU executes power down at affinity level 1, the `prepare_cluster_pwr_dwn()`
+retrieves the `cpu_ops` pointer and the corresponding `cluster_pwr_dwn()` is
+invoked.
+
+At runtime the platform hooks for power down are invoked by the PSCI service to
+perform platform specific operations during a power down sequence, for example
+turning off CCI coherency during a cluster power down.
+
+### CPU specific register reporting during crash
+
+If the crash reporting is enabled in BL3-1, when a crash occurs, the crash
+reporting framework calls `do_cpu_reg_dump` which retrieves the matching
+`cpu_ops` using `get_cpu_ops_ptr()` function. The `cpu_reg_dump()` in
+`cpu_ops` is invoked, which then returns the CPU specific register values to
+be reported and a pointer to the ASCII list of register names in a format
+expected by the crash reporting framework.
+
+
+9. Memory layout of BL images
+-----------------------------
+
+Each bootloader image can be divided in 2 parts:
+
+ *    the static contents of the image. These are data actually stored in the
+      binary on the disk. In the ELF terminology, they are called `PROGBITS`
+      sections;
+
+ *    the run-time contents of the image. These are data that don't occupy any
+      space in the binary on the disk. The ELF binary just contains some
+      metadata indicating where these data will be stored at run-time and the
+      corresponding sections need to be allocated and initialized at run-time.
+      In the ELF terminology, they are called `NOBITS` sections.
+
+All PROGBITS sections are grouped together at the beginning of the image,
+followed by all NOBITS sections. This is true for all Trusted Firmware images
+and it is governed by the linker scripts. This ensures that the raw binary
+images are as small as possible. If a NOBITS section would sneak in between
+PROGBITS sections then the resulting binary file would contain a bunch of zero
+bytes at the location of this NOBITS section, making the image unnecessarily
+bigger. Smaller images allow faster loading from the FIP to the main memory.
+
+### Linker scripts and symbols
+
+Each bootloader stage image layout is described by its own linker script. The
+linker scripts export some symbols into the program symbol table. Their values
+correspond to particular addresses. The trusted firmware code can refer to these
+symbols to figure out the image memory layout.
+
+Linker symbols follow the following naming convention in the trusted firmware.
+
+*   `__<SECTION>_START__`
+
+    Start address of a given section named `<SECTION>`.
+
+*   `__<SECTION>_END__`
+
+    End address of a given section named `<SECTION>`. If there is an alignment
+    constraint on the section's end address then `__<SECTION>_END__` corresponds
+    to the end address of the section's actual contents, rounded up to the right
+    boundary. Refer to the value of `__<SECTION>_UNALIGNED_END__`  to know the
+    actual end address of the section's contents.
+
+*   `__<SECTION>_UNALIGNED_END__`
+
+    End address of a given section named `<SECTION>` without any padding or
+    rounding up due to some alignment constraint.
+
+*   `__<SECTION>_SIZE__`
+
+    Size (in bytes) of a given section named `<SECTION>`. If there is an
+    alignment constraint on the section's end address then `__<SECTION>_SIZE__`
+    corresponds to the size of the section's actual contents, rounded up to the
+    right boundary. In other words, `__<SECTION>_SIZE__ = __<SECTION>_END__ -
+    _<SECTION>_START__`. Refer to the value of `__<SECTION>_UNALIGNED_SIZE__`
+    to know the actual size of the section's contents.
+
+*   `__<SECTION>_UNALIGNED_SIZE__`
+
+    Size (in bytes) of a given section named `<SECTION>` without any padding or
+    rounding up due to some alignment constraint. In other words,
+    `__<SECTION>_UNALIGNED_SIZE__ = __<SECTION>_UNALIGNED_END__ -
+    __<SECTION>_START__`.
+
+Some of the linker symbols are mandatory as the trusted firmware code relies on
+them to be defined. They are listed in the following subsections. Some of them
+must be provided for each bootloader stage and some are specific to a given
+bootloader stage.
+
+The linker scripts define some extra, optional symbols. They are not actually
+used by any code but they help in understanding the bootloader images' memory
+layout as they are easy to spot in the link map files.
+
+#### Common linker symbols
+
+Early setup code needs to know the extents of the BSS section to zero-initialise
+it before executing any C code. The following linker symbols are defined for
+this purpose:
+
+* `__BSS_START__` This address must be aligned on a 16-byte boundary.
+* `__BSS_SIZE__`
+
+Similarly, the coherent memory section (if enabled) must be zero-initialised.
+Also, the MMU setup code needs to know the extents of this section to set the
+right memory attributes for it. The following linker symbols are defined for
+this purpose:
+
+* `__COHERENT_RAM_START__` This address must be aligned on a page-size boundary.
+* `__COHERENT_RAM_END__` This address must be aligned on a page-size boundary.
+* `__COHERENT_RAM_UNALIGNED_SIZE__`
+
+#### BL1's linker symbols
+
+BL1's early setup code needs to know the extents of the .data section to
+relocate it from ROM to RAM before executing any C code. The following linker
+symbols are defined for this purpose:
+
+* `__DATA_ROM_START__` This address must be aligned on a 16-byte boundary.
+* `__DATA_RAM_START__` This address must be aligned on a 16-byte boundary.
+* `__DATA_SIZE__`
+
+BL1's platform setup code needs to know the extents of its read-write data
+region to figure out its memory layout. The following linker symbols are defined
+for this purpose:
+
+* `__BL1_RAM_START__` This is the start address of BL1 RW data.
+* `__BL1_RAM_END__` This is the end address of BL1 RW data.
+
+#### BL2's, BL3-1's and TSP's linker symbols
+
+BL2, BL3-1 and TSP need to know the extents of their read-only section to set
+the right memory attributes for this memory region in their MMU setup code. The
+following linker symbols are defined for this purpose:
+
+* `__RO_START__`
+* `__RO_END__`
+
+### How to choose the right base addresses for each bootloader stage image
+
+There is currently no support for dynamic image loading in the Trusted Firmware.
+This means that all bootloader images need to be linked against their ultimate
+runtime locations and the base addresses of each image must be chosen carefully
+such that images don't overlap each other in an undesired way. As the code
+grows, the base addresses might need adjustments to cope with the new memory
+layout.
+
+The memory layout is completely specific to the platform and so there is no
+general recipe for choosing the right base addresses for each bootloader image.
+However, there are tools to aid in understanding the memory layout. These are
+the link map files: `build/<platform>/<build-type>/bl<x>/bl<x>.map`, with `<x>`
+being the stage bootloader. They provide a detailed view of the memory usage of
+each image. Among other useful information, they provide the end address of
+each image.
+
+* `bl1.map` link map file provides `__BL1_RAM_END__` address.
+* `bl2.map` link map file provides `__BL2_END__` address.
+* `bl31.map` link map file provides `__BL31_END__` address.
+* `bl32.map` link map file provides `__BL32_END__` address.
+
+For each bootloader image, the platform code must provide its start address
+as well as a limit address that it must not overstep. The latter is used in the
+linker scripts to check that the image doesn't grow past that address. If that
+happens, the linker will issue a message similar to the following:
+
+    aarch64-none-elf-ld: BLx has exceeded its limit.
+
+Additionally, if the platform memory layout implies some image overlaying like
+on FVP, BL3-1 and TSP need to know the limit address that their PROGBITS
+sections must not overstep. The platform code must provide those.
+
+
+####  Memory layout on ARM FVPs
+
+The following list describes the memory layout on the FVP:
+
+*   A 4KB page of shared memory is used to store the entrypoint mailboxes
+    and the parameters passed between bootloaders. The shared memory is located
+    at the base of the Trusted SRAM. The amount of Trusted SRAM available to
+    load the bootloader images will be reduced by the size of the shared memory.
+
+*   BL1 is originally sitting in the Trusted ROM at address `0x0`. Its
+    read-write data are relocated at the top of the Trusted SRAM at runtime.
+
+*   BL3-1 is loaded at the top of the Trusted SRAM, such that its NOBITS
+    sections will overwrite BL1 R/W data.
+
+*   BL2 is loaded below BL3-1.
+
+*   BL3-2 can be loaded in one of the following locations:
+
+    *   Trusted SRAM
+    *   Trusted DRAM
+    *   Secure region of DRAM (top 16MB of DRAM configured by the TrustZone
+        controller)
+
+When BL3-2 is loaded into Trusted SRAM, its NOBITS sections are allowed to
+overlay BL2. This memory layout is designed to give the BL3-2 image as much
+memory as possible when it is loaded into Trusted SRAM.
+
+The location of the BL3-2 image will result in different memory maps. This is
+illustrated in the following diagrams using the TSP as an example.
+
+**TSP in Trusted SRAM (default option):**
+
+               Trusted SRAM
+    0x04040000 +----------+  loaded by BL2  ------------------
+               | BL1 (rw) |  <<<<<<<<<<<<<  |  BL3-1 NOBITS  |
+               |----------|  <<<<<<<<<<<<<  |----------------|
+               |          |  <<<<<<<<<<<<<  | BL3-1 PROGBITS |
+               |----------|                 ------------------
+               |   BL2    |  <<<<<<<<<<<<<  |  BL3-2 NOBITS  |
+               |----------|  <<<<<<<<<<<<<  |----------------|
+               |          |  <<<<<<<<<<<<<  | BL3-2 PROGBITS |
+    0x04001000 +----------+                 ------------------
+               |  Shared  |
+    0x04000000 +----------+
+
+               Trusted ROM
+    0x04000000 +----------+
+               | BL1 (ro) |
+    0x00000000 +----------+
+
+
+**TSP in Trusted DRAM:**
+
+               Trusted DRAM
+    0x08000000 +----------+
+               |  BL3-2   |
+    0x06000000 +----------+
+
+               Trusted SRAM
+    0x04040000 +----------+  loaded by BL2  ------------------
+               | BL1 (rw) |  <<<<<<<<<<<<<  |  BL3-1 NOBITS  |
+               |----------|  <<<<<<<<<<<<<  |----------------|
+               |          |  <<<<<<<<<<<<<  | BL3-1 PROGBITS |
+               |----------|                 ------------------
+               |   BL2    |
+               |----------|
+               |          |
+    0x04001000 +----------+
+               |  Shared  |
+    0x04000000 +----------+
+
+               Trusted ROM
+    0x04000000 +----------+
+               | BL1 (ro) |
+    0x00000000 +----------+
+
+**TSP in the TZC-Secured DRAM:**
+
+                   DRAM
+    0xffffffff +----------+
+               |  BL3-2   |  (secure)
+    0xff000000 +----------+
+               |          |
+               :          :  (non-secure)
+               |          |
+    0x80000000 +----------+
+
+               Trusted SRAM
+    0x04040000 +----------+  loaded by BL2  ------------------
+               | BL1 (rw) |  <<<<<<<<<<<<<  |  BL3-1 NOBITS  |
+               |----------|  <<<<<<<<<<<<<  |----------------|
+               |          |  <<<<<<<<<<<<<  | BL3-1 PROGBITS |
+               |----------|                 ------------------
+               |   BL2    |
+               |----------|
+               |          |
+    0x04001000 +----------+
+               |  Shared  |
+    0x04000000 +----------+
+
+               Trusted ROM
+    0x04000000 +----------+
+               | BL1 (ro) |
+    0x00000000 +----------+
+
+Moving the TSP image out of the Trusted SRAM doesn't change the memory layout
+of the other boot loader images in Trusted SRAM.
+
+
+####  Memory layout on Juno ARM development platform
+
+The following list describes the memory layout on Juno:
+
+*   Trusted SRAM at 0x04000000 contains the MHU page, BL1 r/w section, BL2
+    image, BL3-1 image and, optionally, the BL3-2 image.
+
+*   The MHU 4 KB page is used as communication channel between SCP and AP. It
+    also contains the entrypoint mailboxes for the AP. Mailboxes are stored in
+    the first 128 bytes of the MHU page.
+
+*   BL1 resides in flash memory at address `0x0BEC0000`. Its read-write data
+    section is relocated to the top of the Trusted SRAM at runtime.
+
+*   BL3-1 is loaded at the top of the Trusted SRAM, such that its NOBITS
+    sections will overwrite BL1 R/W data. This implies that BL1 global variables
+    will remain valid only until execution reaches the BL3-1 entry point during
+    a cold boot.
+
+*   BL2 is loaded below BL3-1.
+
+*   BL3-0 is loaded temporarily into the BL3-1 memory region and transfered to
+    the SCP before being overwritten by BL3-1.
+
+*   The BL3-2 image is optional and can be loaded into one of these two
+    locations: Trusted SRAM (right after the MHU page) or DRAM (14 MB starting
+    at 0xFF000000 and secured by the TrustZone controller). When loaded into
+    Trusted SRAM, its NOBITS sections are allowed to overlap BL2.
+
+Depending on the location of the BL3-2 image, it will result in different memory
+maps, illustrated by the following diagrams.
+
+**BL3-2 in Trusted SRAM (default option):**
+
+                  Flash0
+    0x0C000000 +----------+
+               :          :
+    0x0BED0000 |----------|
+               | BL1 (ro) |
+    0x0BEC0000 |----------|
+               :          :
+    0x08000000 +----------+                  BL3-1 is loaded
+                                             after BL3-0 has
+               Trusted SRAM                  been sent to SCP
+    0x04040000 +----------+  loaded by BL2  ------------------
+               | BL1 (rw) |  <<<<<<<<<<<<<  |  BL3-1 NOBITS  |
+               |----------|  <<<<<<<<<<<<<  |----------------|
+               |  BL3-0   |  <<<<<<<<<<<<<  | BL3-1 PROGBITS |
+               |----------|                 ------------------
+               |   BL2    |  <<<<<<<<<<<<<  |  BL3-2 NOBITS  |
+               |----------|  <<<<<<<<<<<<<  |----------------|
+               |          |  <<<<<<<<<<<<<  | BL3-2 PROGBITS |
+    0x04001000 +----------+                 ------------------
+               |   MHU    |
+    0x04000000 +----------+
+
+
+**BL3-2 in the secure region of DRAM:**
+
+                   DRAM
+    0xFFE00000 +----------+
+               |  BL3-2   |  (secure)
+    0xFF000000 |----------|
+               |          |
+               :          :  (non-secure)
+               |          |
+    0x80000000 +----------+
+
+                  Flash0
+    0x0C000000 +----------+
+               :          :
+    0x0BED0000 |----------|
+               | BL1 (ro) |
+    0x0BEC0000 |----------|
+               :          :
+    0x08000000 +----------+                  BL3-1 is loaded
+                                             after BL3-0 has
+               Trusted SRAM                  been sent to SCP
+    0x04040000 +----------+  loaded by BL2  ------------------
+               | BL1 (rw) |  <<<<<<<<<<<<<  |  BL3-1 NOBITS  |
+               |----------|  <<<<<<<<<<<<<  |----------------|
+               |  BL3-0   |  <<<<<<<<<<<<<  | BL3-1 PROGBITS |
+               |----------|                 ------------------
+               |   BL2    |
+               |----------|
+               |          |
+    0x04001000 +----------+
+               |   MHU    |
+    0x04000000 +----------+
+
+Loading the BL3-2 image in DRAM doesn't change the memory layout of the other
+images in Trusted SRAM.
+
+
+10.  Firmware Image Package (FIP)
+---------------------------------
+
+Using a Firmware Image Package (FIP) allows for packing bootloader images (and
+potentially other payloads) into a single archive that can be loaded by the ARM
+Trusted Firmware from non-volatile platform storage. A driver to load images
+from a FIP has been added to the storage layer and allows a package to be read
+from supported platform storage. A tool to create Firmware Image Packages is
+also provided and described below.
+
+### Firmware Image Package layout
+
+The FIP layout consists of a table of contents (ToC) followed by payload data.
+The ToC itself has a header followed by one or more table entries. The ToC is
+terminated by an end marker entry. All ToC entries describe some payload data
+that has been appended to the end of the binary package. With the information
+provided in the ToC entry the corresponding payload data can be retrieved.
+
+    ------------------
+    | ToC Header     |
+    |----------------|
+    | ToC Entry 0    |
+    |----------------|
+    | ToC Entry 1    |
+    |----------------|
+    | ToC End Marker |
+    |----------------|
+    |                |
+    |     Data 0     |
+    |                |
+    |----------------|
+    |                |
+    |     Data 1     |
+    |                |
+    ------------------
+
+The ToC header and entry formats are described in the header file
+`include/firmware_image_package.h`. This file is used by both the tool and the
+ARM Trusted firmware.
+
+The ToC header has the following fields:
+    `name`: The name of the ToC. This is currently used to validate the header.
+    `serial_number`: A non-zero number provided by the creation tool
+    `flags`: Flags associated with this data. None are yet defined.
+
+A ToC entry has the following fields:
+    `uuid`: All files are referred to by a pre-defined Universally Unique
+        IDentifier [UUID] . The UUIDs are defined in
+        `include/firmware_image_package`. The platform translates the requested
+        image name into the corresponding UUID when accessing the package.
+    `offset_address`: The offset address at which the corresponding payload data
+        can be found. The offset is calculated from the ToC base address.
+    `size`: The size of the corresponding payload data in bytes.
+    `flags`: Flags associated with this entry. Non are yet defined.
+
+### Firmware Image Package creation tool
+
+The FIP creation tool can be used to pack specified images into a binary package
+that can be loaded by the ARM Trusted Firmware from platform storage. The tool
+currently only supports packing bootloader images. Additional image definitions
+can be added to the tool as required.
+
+The tool can be found in `tools/fip_create`.
+
+### Loading from a Firmware Image Package (FIP)
+
+The Firmware Image Package (FIP) driver can load images from a binary package on
+non-volatile platform storage. For the FVPs this is currently NOR FLASH.
+
+Bootloader images are loaded according to the platform policy as specified in
+`plat/<platform>/plat_io_storage.c`. For the FVPs this means the platform will
+attempt to load images from a Firmware Image Package located at the start of NOR
+FLASH0.
+
+Currently the FVP's policy only allows loading of a known set of images. The
+platform policy can be modified to allow additional images.
+
+
+11. Use of coherent memory in Trusted Firmware
+----------------------------------------------
+
+There might be loss of coherency when physical memory with mismatched
+shareability, cacheability and memory attributes is accessed by multiple CPUs
+(refer to section B2.9 of [ARM ARM] for more details). This possibility occurs
+in Trusted Firmware during power up/down sequences when coherency, MMU and
+caches are turned on/off incrementally.
+
+Trusted Firmware defines coherent memory as a region of memory with Device
+nGnRE attributes in the translation tables. The translation granule size in
+Trusted Firmware is 4KB. This is the smallest possible size of the coherent
+memory region.
+
+By default, all data structures which are susceptible to accesses with
+mismatched attributes from various CPUs are allocated in a coherent memory
+region (refer to section 2.1 of [Porting Guide]). The coherent memory region
+accesses are Outer Shareable, non-cacheable and they can be accessed
+with the Device nGnRE attributes when the MMU is turned on. Hence, at the
+expense of at least an extra page of memory, Trusted Firmware is able to work
+around coherency issues due to mismatched memory attributes.
+
+The alternative to the above approach is to allocate the susceptible data
+structures in Normal WriteBack WriteAllocate Inner shareable memory. This
+approach requires the data structures to be designed so that it is possible to
+work around the issue of mismatched memory attributes by performing software
+cache maintenance on them.
+
+### Disabling the use of coherent memory in Trusted Firmware
+
+It might be desirable to avoid the cost of allocating coherent memory on
+platforms which are memory constrained. Trusted Firmware enables inclusion of
+coherent memory in firmware images through the build flag `USE_COHERENT_MEM`.
+This flag is enabled by default. It can be disabled to choose the second
+approach described above.
+
+The below sections analyze the data structures allocated in the coherent memory
+region and the changes required to allocate them in normal memory.
+
+### PSCI Affinity map nodes
+
+The `psci_aff_map` data structure stores the hierarchial node information for
+each affinity level in the system including the PSCI states associated with them.
+By default, this data structure is allocated in the coherent memory region in
+the Trusted Firmware because it can be accessed by multiple CPUs, either with
+their caches enabled or disabled.
+
+       typedef struct aff_map_node {
+               unsigned long mpidr;
+               unsigned char ref_count;
+               unsigned char state;
+               unsigned char level;
+       #if USE_COHERENT_MEM
+               bakery_lock_t lock;
+       #else
+               unsigned char aff_map_index;
+       #endif
+       } aff_map_node_t;
+
+In order to move this data structure to normal memory, the use of each of its
+fields must be analyzed. Fields like `mpidr` and `level` are only written once
+during cold boot. Hence removing them from coherent memory involves only doing
+a clean and invalidate of the cache lines after these fields are written.
+
+The fields `state` and `ref_count` can be concurrently accessed by multiple
+CPUs in different cache states. A Lamport's Bakery lock is used to ensure mutual
+exlusion to these fields. As a result, it is possible to move these fields out
+of coherent memory by performing software cache maintenance on them. The field
+`lock` is the bakery lock data structure when `USE_COHERENT_MEM` is enabled.
+The `aff_map_index` is used to identify the bakery lock when `USE_COHERENT_MEM`
+is disabled.
+
+### Bakery lock data
+
+The bakery lock data structure `bakery_lock_t` is allocated in coherent memory
+and is accessed by multiple CPUs with mismatched attributes. `bakery_lock_t` is
+defined as follows:
+
+    typedef struct bakery_lock {
+        int owner;
+        volatile char entering[BAKERY_LOCK_MAX_CPUS];
+        volatile unsigned number[BAKERY_LOCK_MAX_CPUS];
+    } bakery_lock_t;
+
+It is a characteristic of Lamport's Bakery algorithm that the volatile per-CPU
+fields can be read by all CPUs but only written to by the owning CPU.
+
+Depending upon the data cache line size, the per-CPU fields of the
+`bakery_lock_t` structure for multiple CPUs may exist on a single cache line.
+These per-CPU fields can be read and written during lock contention by multiple
+CPUs with mismatched memory attributes. Since these fields are a part of the
+lock implementation, they do not have access to any other locking primitive to
+safeguard against the resulting coherency issues. As a result, simple software
+cache maintenance is not enough to allocate them in coherent memory. Consider
+the following example.
+
+CPU0 updates its per-CPU field with data cache enabled. This write updates a
+local cache line which contains a copy of the fields for other CPUs as well. Now
+CPU1 updates its per-CPU field of the `bakery_lock_t` structure with data cache
+disabled. CPU1 then issues a DCIVAC operation to invalidate any stale copies of
+its field in any other cache line in the system. This operation will invalidate
+the update made by CPU0 as well.
+
+To use bakery locks when `USE_COHERENT_MEM` is disabled, the lock data structure
+has been redesigned. The changes utilise the characteristic of Lamport's Bakery
+algorithm mentioned earlier. The per-CPU fields of the new lock structure are
+aligned such that they are allocated on separate cache lines. The per-CPU data
+framework in Trusted Firmware is used to achieve this. This enables software to
+perform software cache maintenance on the lock data structure without running
+into coherency issues associated with mismatched attributes.
+
+The per-CPU data framework enables consolidation of data structures on the
+fewest cache lines possible. This saves memory as compared to the scenario where
+each data structure is separately aligned to the cache line boundary to achieve
+the same effect.
+
+The bakery lock data structure `bakery_info_t` is defined for use when
+`USE_COHERENT_MEM` is disabled as follows:
+
+    typedef struct bakery_info {
+        /*
+         * The lock_data is a bit-field of 2 members:
+         * Bit[0]       : choosing. This field is set when the CPU is
+         *                choosing its bakery number.
+         * Bits[1 - 15] : number. This is the bakery number allocated.
+         */
+         volatile uint16_t lock_data;
+    } bakery_info_t;
+
+The `bakery_info_t` represents a single per-CPU field of one lock and
+the combination of corresponding `bakery_info_t` structures for all CPUs in the
+system represents the complete bakery lock. It is embedded in the per-CPU
+data framework `cpu_data` as shown below:
+
+      CPU0 cpu_data
+    ------------------
+    | ....           |
+    |----------------|
+    | `bakery_info_t`| <-- Lock_0 per-CPU field
+    |    Lock_0      |     for CPU0
+    |----------------|
+    | `bakery_info_t`| <-- Lock_1 per-CPU field
+    |    Lock_1      |     for CPU0
+    |----------------|
+    | ....           |
+    |----------------|
+    | `bakery_info_t`| <-- Lock_N per-CPU field
+    |    Lock_N      |     for CPU0
+    ------------------
+
+
+      CPU1 cpu_data
+    ------------------
+    | ....           |
+    |----------------|
+    | `bakery_info_t`| <-- Lock_0 per-CPU field
+    |    Lock_0      |     for CPU1
+    |----------------|
+    | `bakery_info_t`| <-- Lock_1 per-CPU field
+    |    Lock_1      |     for CPU1
+    |----------------|
+    | ....           |
+    |----------------|
+    | `bakery_info_t`| <-- Lock_N per-CPU field
+    |    Lock_N      |     for CPU1
+    ------------------
+
+Consider a system of 2 CPUs with 'N' bakery locks as shown above.  For an
+operation on Lock_N, the corresponding `bakery_info_t` in both CPU0 and CPU1
+`cpu_data` need to be fetched and appropriate cache operations need to be
+performed for each access.
+
+For multiple bakery locks, an array of `bakery_info_t` is declared in `cpu_data`
+and each lock is given an `id` to identify it in the array.
+
+### Non Functional Impact of removing coherent memory
+
+Removal of the coherent memory region leads to the additional software overhead
+of performing cache maintenance for the affected data structures. However, since
+the memory where the data structures are allocated is cacheable, the overhead is
+mostly mitigated by an increase in performance.
+
+There is however a performance impact for bakery locks, due to:
+*   Additional cache maintenance operations, and
+*   Multiple cache line reads for each lock operation, since the bakery locks
+    for each CPU are distributed across different cache lines.
+
+The implementation has been optimized to mimimize this additional overhead.
+Measurements indicate that when bakery locks are allocated in Normal memory, the
+minimum latency of acquiring a lock is on an average 3-4 micro seconds whereas
+in Device memory the same is 2 micro seconds. The measurements were done on the
+Juno ARM development platform.
+
+As mentioned earlier, almost a page of memory can be saved by disabling
+`USE_COHERENT_MEM`. Each platform needs to consider these trade-offs to decide
+whether coherent memory should be used. If a platform disables
+`USE_COHERENT_MEM` and needs to use bakery locks in the porting layer, it should
+reserve memory in `cpu_data` by defining the macro `PLAT_PCPU_DATA_SIZE` (see
+the [Porting Guide]). Refer to the reference platform code for examples.
+
+
+12.  Code Structure
+-------------------
+
+Trusted Firmware code is logically divided between the three boot loader
+stages mentioned in the previous sections. The code is also divided into the
+following categories (present as directories in the source code):
+
+*   **Architecture specific.** This could be AArch32 or AArch64.
+*   **Platform specific.** Choice of architecture specific code depends upon
+    the platform.
+*   **Common code.** This is platform and architecture agnostic code.
+*   **Library code.** This code comprises of functionality commonly used by all
+    other code.
+*   **Stage specific.** Code specific to a boot stage.
+*   **Drivers.**
+*   **Services.** EL3 runtime services, e.g. PSCI or SPD. Specific SPD services
+    reside in the `services/spd` directory (e.g. `services/spd/tspd`).
+
+Each boot loader stage uses code from one or more of the above mentioned
+categories. Based upon the above, the code layout looks like this:
+
+    Directory    Used by BL1?    Used by BL2?    Used by BL3-1?
+    bl1          Yes             No              No
+    bl2          No              Yes             No
+    bl31         No              No              Yes
+    arch         Yes             Yes             Yes
+    plat         Yes             Yes             Yes
+    drivers      Yes             No              Yes
+    common       Yes             Yes             Yes
+    lib          Yes             Yes             Yes
+    services     No              No              Yes
+
+The build system provides a non configurable build option IMAGE_BLx for each
+boot loader stage (where x = BL stage). e.g. for BL1 , IMAGE_BL1 will be
+defined by the build system. This enables the Trusted Firmware to compile
+certain code only for specific boot loader stages
+
+All assembler files have the `.S` extension. The linker source files for each
+boot stage have the extension `.ld.S`. These are processed by GCC to create the
+linker scripts which have the extension `.ld`.
+
+FDTs provide a description of the hardware platform and are used by the Linux
+kernel at boot time. These can be found in the `fdts` directory.
+
+
+13.  References
+---------------
+
+1.  Trusted Board Boot Requirements CLIENT PDD (ARM DEN 0006B-5). Available
+    under NDA through your ARM account representative.
+
+2.  [Power State Coordination Interface PDD (ARM DEN 0022B.b)][PSCI].
+
+3.  [SMC Calling Convention PDD (ARM DEN 0028A)][SMCCC].
+
+4.  [ARM Trusted Firmware Interrupt Management Design guide][INTRG].
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved._
+
+[ARM ARM]:          http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a.e/index.html "ARMv8-A Reference Manual (ARM DDI0487A.E)"
+[PSCI]:             http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf "Power State Coordination Interface PDD (ARM DEN 0022C)"
+[SMCCC]:            http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html "SMC Calling Convention PDD (ARM DEN 0028A)"
+[UUID]:             https://tools.ietf.org/rfc/rfc4122.txt "A Universally Unique IDentifier (UUID) URN Namespace"
+[User Guide]:       ./user-guide.md
+[Porting Guide]:    ./porting-guide.md
+[INTRG]:            ./interrupt-framework-design.md
+[CPUBM]:            ./cpu-specific-build-macros.md.md
diff --git a/docs/interrupt-framework-design.md b/docs/interrupt-framework-design.md
new file mode 100644 (file)
index 0000000..ff001b1
--- /dev/null
@@ -0,0 +1,848 @@
+ARM Trusted Firmware Interrupt Management Design guide
+======================================================
+
+Contents :
+
+1.  [Introduction](#1-introduction)
+    *   [Assumptions](#11-assumptions)
+    *   [Concepts](#12-concepts)
+        -   [Interrupt Types](#121-interrupt-types)
+        -   [Routing Model](#122-routing-model)
+        -   [Valid Routing Models](#123-valid-routing-models)
+            +   [Secure-EL1 Interrupts](#1231-secure-el1-interrupts)
+            +   [Non-secure Interrupts](#1232-non-secure-interrupts)
+        -   [Mapping of Interrupt Type to Signal](#124-mapping-of-interrupt-type-to-signal)
+
+2.  [Interrupt Management](#2-interrupt-management)
+    *   [Software Components](#21-software-components)
+    *   [Interrupt Registration](#22-interrupt-registration)
+        -   [EL3 Runtime Firmware](#221-el3-runtime-firmware)
+        -   [Secure Payload Dispatcher](#222-secure-payload-dispatcher)
+            +   [Test Secure Payload Dispatcher behavior](#2221-test-secure-payload-dispatcher-behavior)
+        -   [Secure Payload](#223-secure-payload)
+            +   [Secure Payload IHF design w.r.t Secure-EL1 interrupts](#2231-secure-payload-ihf-design-wrt-secure-el1-interrupts)
+            +   [Secure Payload IHF design w.r.t Non-secure interrupts](#2232-secure-payload-ihf-design-wrt-non-secure-interrupts)
+            +   [Test Secure Payload behavior](#2233-test-secure-payload-behavior)
+    *   [Interrupt Handling](#23-interrupt-handling)
+        -   [EL3 Runtime Firmware](#231-el3-runtime-firmware)
+        -   [Secure Payload Dispatcher](#232-secure-payload-dispatcher)
+            +   [Interrupt Entry](#2321-interrupt-entry)
+            +   [Interrupt Exit](#2322-interrupt-exit)
+            +   [Test Secure Payload Dispatcher behavior](#2323-test-secure-payload-dispatcher-behavior)
+        -   [Secure Payload](#233-secure-payload)
+            +   [Test Secure Payload behavior](#2331-test-secure-payload-behavior)
+
+
+1. Introduction
+----------------
+This document describes the design of the Interrupt management framework in ARM
+Trusted Firmware. This section briefly describes the requirements from this
+framework. It also briefly explains some concepts and assumptions. They will
+help in understanding the implementation of the framework explained in
+subsequent sections.
+
+This framework is responsible for managing interrupts routed to EL3. It also
+allows EL3 software to configure the interrupt routing behavior. Its main
+objective is to implement the following two requirements.
+
+1.  It should be possible to route interrupts meant to be handled by secure
+    software (Secure interrupts) to EL3, when execution is in non-secure state
+    (normal world). The framework should then take care of handing control of
+    the interrupt to either software in EL3 or Secure-EL1 depending upon the
+    software configuration and the GIC implementation. This requirement ensures
+    that secure interrupts are under the control of the secure software with
+    respect to their delivery and handling without the possibility of
+    intervention from non-secure software.
+
+2.  It should be possible to route interrupts meant to be handled by
+    non-secure software (Non-secure interrupts) to the last executed exception
+    level in the normal world when the execution is in secure world at
+    exception levels lower than EL3. This could be done with or without the
+    knowledge of software executing in Secure-EL1/Secure-EL0. The choice of
+    approach should be governed by the secure software. This requirement
+    ensures that non-secure software is able to execute in tandem with the
+    secure software without overriding it.
+
+### 1.1 Assumptions
+The framework makes the following assumptions to simplify its implementation.
+
+1.  All secure interrupts are handled in Secure-EL1. They can be delivered to
+    Secure-EL1 via EL3 but they cannot be handled in EL3. It will be possible
+    to extend the framework to handle secure interrupts in EL3 in the future.
+
+2.  Interrupt exceptions (`PSTATE.I` and `F` bits) are masked during execution
+    in EL3.
+
+### 1.2 Concepts
+
+#### 1.2.1 Interrupt types
+The framework categorises an interrupt to be one of the following depending upon
+the exception level(s) it is handled in.
+
+1.  Secure EL1 interrupt. This type of interrupt can be routed to EL3 or
+    Secure-EL1 depending upon the security state of the current execution
+    context. It is always handled in Secure-EL1.
+
+2.  Non-secure interrupt. This type of interrupt can be routed to EL3,
+    Secure-EL1, Non-secure EL1 or EL2 depending upon the security state of the
+    current execution context. It is always handled in either Non-secure EL1
+    or EL2.
+
+3.  EL3 interrupt. This type of interrupt can be routed to EL3 or Secure-EL1
+    depending upon the security state of the current execution context. It is
+    always handled in EL3.
+
+In the current implementation of the framework, all secure interrupts are
+treated as Secure EL1 interrupts. It will be possible for EL3 software to
+configure a secure interrupt as an EL3 interrupt in future implementations.  The
+following constants define the various interrupt types in the framework
+implementation.
+
+    #define INTR_TYPE_S_EL1      0
+    #define INTR_TYPE_EL3        1
+    #define INTR_TYPE_NS         2
+
+
+#### 1.2.2 Routing model
+A type of interrupt can be either generated as an FIQ or an IRQ. The target
+exception level of an interrupt type is configured through the FIQ and IRQ bits
+in the Secure Configuration Register at EL3 (`SCR_EL3.FIQ` and `SCR_EL3.IRQ`
+bits). When `SCR_EL3.FIQ`=1, FIQs are routed to EL3. Otherwise they are routed
+to the First Exception Level (FEL) capable of handling interrupts. When
+`SCR_EL3.IRQ`=1, IRQs are routed to EL3. Otherwise they are routed to the
+FEL. This register is configured independently by EL3 software for each security
+state prior to entry into a lower exception level in that security state.
+
+A routing model for a type of interrupt (generated as FIQ or IRQ) is defined as
+its target exception level for each security state. It is represented by a
+single bit for each security state. A value of `0` means that the interrupt
+should be routed to the FEL. A value of `1` means that the interrupt should be
+routed to EL3. A routing model is applicable only when execution is not in EL3.
+
+The default routing model for an interrupt type is to route it to the FEL in
+either security state.
+
+#### 1.2.3 Valid routing models
+The framework considers certain routing models for each type of interrupt to be
+incorrect as they conflict with the requirements mentioned in Section 1. The
+following sub-sections describe all the possible routing models and specify
+which ones are valid or invalid. Only the Secure-EL1 and Non-secure interrupt
+types are considered as EL3 interrupts are currently unsupported (See 1.1). The
+terminology used in the following sub-sections is explained below.
+
+1.  __CSS__. Current Security State. `0` when secure and `1` when non-secure
+
+2.  __TEL3__. Target Exception Level 3. `0` when targeted to the FEL. `1` when
+    targeted to EL3.
+
+
+##### 1.2.3.1 Secure-EL1 interrupts
+
+1.  __CSS=0, TEL3=0__. Interrupt is routed to the FEL when execution is in
+    secure state. This is a valid routing model as secure software is in
+    control of handling secure interrupts.
+
+2.  __CSS=0, TEL3=1__. Interrupt is routed to EL3 when execution is in secure
+    state. This is a valid routing model as secure software in EL3 can
+    handover the interrupt to Secure-EL1 for handling.
+
+3.  __CSS=1, TEL3=0__. Interrupt is routed to the FEL when execution is in
+    non-secure state. This is an invalid routing model as a secure interrupt
+    is not visible to the secure software which violates the motivation behind
+    the ARM Security Extensions.
+
+4.  __CSS=1, TEL3=1__. Interrupt is routed to EL3 when execution is in
+    non-secure state. This is a valid routing model as secure software in EL3
+    can handover the interrupt to Secure-EL1 for handling.
+
+
+##### 1.2.3.2 Non-secure interrupts
+
+1.  __CSS=0, TEL3=0__. Interrupt is routed to the FEL when execution is in
+    secure state. This allows the secure software to trap non-secure
+    interrupts, perform its bookeeping and hand the interrupt to the
+    non-secure software through EL3. This is a valid routing model as secure
+    software is in control of how its execution is pre-empted by non-secure
+    interrupts.
+
+2.  __CSS=0, TEL3=1__. Interrupt is routed to EL3 when execution is in secure
+    state. This is a valid routing model as secure software in EL3 can save
+    the state of software in Secure-EL1/Secure-EL0 before handing the
+    interrupt to non-secure software. This model requires additional
+    coordination between Secure-EL1 and EL3 software to ensure that the
+    former's state is correctly saved by the latter.
+
+3.  __CSS=1, TEL3=0__. Interrupt is routed to FEL when execution is in
+    non-secure state. This is an valid routing model as a non-secure interrupt
+    is handled by non-secure software.
+
+4.   __CSS=1, TEL3=1__. Interrupt is routed to EL3 when execution is in
+    non-secure state. This is an invalid routing model as there is no valid
+    reason to route the interrupt to EL3 software and then hand it back to
+    non-secure software for handling.
+
+
+#### 1.2.4 Mapping of interrupt type to signal
+The framework is meant to work with any interrupt controller implemented by a
+platform. A interrupt controller could generate a type of interrupt as either an
+FIQ or IRQ signal to the CPU depending upon the current security state.The
+mapping between the type and signal is known only to the platform. The framework
+uses this information to determine whether the IRQ or the FIQ bit should be
+programmed in `SCR_EL3` while applying the routing model for a type of
+interrupt. The platform provides this information through the
+`plat_interrupt_type_to_line()` API (described in the [Porting
+Guide]). For example, on the FVP port when the platform uses an ARM GICv2
+interrupt controller, Secure-EL1 interrupts are signalled through the FIQ signal
+while Non-secure interrupts are signalled through the IRQ signal. This applies
+when execution is in either security state.
+
+
+2. Interrupt management
+-----------------------
+The following sections describe how interrupts are managed by the interrupt
+handling framework. This entails:
+
+1.  Providing an interface to allow registration of a handler and specification
+    of the routing model for a type of interrupt.
+
+2.  Implementing support to hand control of an interrupt type to its registered
+    handler when the interrupt is generated.
+
+Both aspects of interrupt management involve various components in the secure
+software stack spanning from EL3 to Secure-EL1. These components are described
+in the section 2.1. The framework stores information associated with each type
+of interrupt in the following data structure.
+
+```
+typedef struct intr_type_desc {
+        interrupt_type_handler_t handler;
+        uint32_t flags;
+        uint32_t scr_el3[2];
+} intr_type_desc_t;
+```
+
+The `flags` field stores the routing model for the interrupt type in
+bits[1:0]. Bit[0] stores the routing model when execution is in the secure
+state. Bit[1] stores the routing model when execution is in the non-secure
+state. As mentioned in Section 1.2.2, a value of `0` implies that the interrupt
+should be targeted to the FEL. A value of `1` implies that it should be targeted
+to EL3. The remaining bits are reserved and SBZ. The helper macro
+`set_interrupt_rm_flag()` should be used to set the bits in the `flags`
+parameter.
+
+The `scr_el3[2]` field also stores the routing model but as a mapping of the
+model in the `flags` field to the corresponding bit in the `SCR_EL3` for each
+security state.
+
+The framework also depends upon the platform port to configure the interrupt
+controller to distinguish between secure and non-secure interrupts. The platform
+is expected to be aware of the secure devices present in the system and their
+associated interrupt numbers. It should configure the interrupt controller to
+enable the secure interrupts, ensure that their priority is always higher than
+the non-secure interrupts and target them to the primary CPU. It should also
+export the interface described in the [Porting Guide] to enable
+handling of interrupts.
+
+In the remainder of this document, for the sake of simplicity it is assumed that
+the FIQ signal is used to generate Secure-EL1 interrupts and the IRQ signal is
+used to generate non-secure interrupts in either security state.
+
+### 2.1 Software components
+Roles and responsibilities for interrupt management are sub-divided between the
+following components of software running in EL3 and Secure-EL1. Each component is
+briefly described below.
+
+1.  EL3 Runtime Firmware. This component is common to all ports of the ARM
+    Trusted Firmware.
+
+2.  Secure Payload Dispatcher (SPD) service. This service interfaces with the
+    Secure Payload (SP) software which runs in exception levels lower than EL3
+    i.e. Secure-EL1/Secure-EL0. It is responsible for switching execution
+    between software running in secure and non-secure states at exception
+    levels lower than EL3. A switch is triggered by a Secure Monitor Call from
+    either state. It uses the APIs exported by the Context management library
+    to implement this functionality. Switching execution between the two
+    security states is a requirement for interrupt management as well. This
+    results in a significant dependency on the SPD service. ARM Trusted
+    firmware implements an example Test Secure Payload Dispatcher (TSPD)
+    service.
+
+    An SPD service plugs into the EL3 runtime firmware and could be common to
+    some ports of the ARM Trusted Firmware.
+
+3.  Secure Payload (SP). On a production system, the Secure Payload corresponds
+    to a Secure OS which runs in Secure-EL1/Secure-EL0. It interfaces with the
+    SPD service to manage communication with non-secure software. ARM Trusted
+    Firmware implements an example secure payload called Test Secure Payload
+    (TSP) which runs only in Secure-EL1.
+
+    A Secure payload implementation could be common to some ports of the ARM
+    Trusted Firmware just like the SPD service.
+
+
+### 2.2 Interrupt registration
+This section describes in detail the role of each software component (see 2.1)
+during the registration of a handler for an interrupt type.
+
+
+#### 2.2.1 EL3 runtime firmware
+This component declares the following prototype for a handler of an interrupt type.
+
+        typedef uint64_t (*interrupt_type_handler_t)(uint32_t id,
+                                            uint32_t flags,
+                                            void *handle,
+                                            void *cookie);
+
+The value of the `id` parameter depends upon the definition of the
+`IMF_READ_INTERRUPT_ID` build time flag. When the flag is defined, `id` contains
+the number of the highest priority pending interrupt of the type that this
+handler was registered for. When the flag is not defined `id` contains
+`INTR_ID_UNAVAILABLE`.
+
+The `flags` parameter contains miscellaneous information as follows.
+
+1.  Security state, bit[0]. This bit indicates the security state of the lower
+    exception level when the interrupt was generated. A value of `1` means
+    that it was in the non-secure state. A value of `0` indicates that it was
+    in the secure state. This bit can be used by the handler to ensure that
+    interrupt was generated and routed as per the routing model specified
+    during registration.
+
+2.  Reserved, bits[31:1]. The remaining bits are reserved for future use.
+
+The `handle` parameter points to the `cpu_context` structure of the current CPU
+for the security state specified in the `flags` parameter.
+
+Once the handler routine completes, execution will return to either the secure
+or non-secure state. The handler routine should return a pointer to
+`cpu_context` structure of the current CPU for the the target security state. It
+should treat all error conditions as critical errors and take appropriate action
+within its implementation e.g. use assertion failures.
+
+The runtime firmware provides the following API for registering a handler for a
+particular type of interrupt. A Secure Payload Dispatcher service should use
+this API to register a handler for Secure-EL1 and optionally for non-secure
+interrupts. This API also requires the caller to specify the routing model for
+the type of interrupt.
+
+    int32_t register_interrupt_type_handler(uint32_t type,
+                                       interrupt_type_handler handler,
+                                       uint64_t flags);
+
+
+The `type` parameter can be one of the three interrupt types listed above i.e.
+`INTR_TYPE_S_EL1`, `INTR_TYPE_NS` & `INTR_TYPE_EL3` (currently unimplemented).
+The `flags` parameter is as described in Section 2.
+
+The function will return `0` upon a successful registration. It will return
+`-EALREADY` in case a handler for the interrupt type has already been
+registered.  If the `type` is unrecognised or the `flags` or the `handler` are
+invalid it will return `-EINVAL`. It will return `-ENOTSUP` if the specified
+`type` is not supported by the framework i.e. `INTR_TYPE_EL3`.
+
+Interrupt routing is governed by the configuration of the `SCR_EL3.FIQ/IRQ` bits
+prior to entry into a lower exception level in either security state. The
+context management library maintains a copy of the `SCR_EL3` system register for
+each security state in the `cpu_context` structure of each CPU. It exports the
+following APIs to let EL3 Runtime Firmware program and retrieve the routing
+model for each security state for the current CPU. The value of `SCR_EL3` stored
+in the `cpu_context` is used by the `el3_exit()` function to program the
+`SCR_EL3` register prior to returning from the EL3 exception level.
+
+        uint32_t cm_get_scr_el3(uint32_t security_state);
+        void cm_write_scr_el3_bit(uint32_t security_state,
+                                  uint32_t bit_pos,
+                                  uint32_t value);
+
+`cm_get_scr_el3()` returns the value of the `SCR_EL3` register for the specified
+security state of the current CPU. `cm_write_scr_el3()` writes a `0` or `1` to
+the bit specified by `bit_pos`. `register_interrupt_type_handler()` invokes
+`set_routing_model()` API which programs the `SCR_EL3` according to the routing
+model using the `cm_get_scr_el3()` and `cm_write_scr_el3_bit()` APIs.
+
+It is worth noting that in the current implementation of the framework, the EL3
+runtime firmware is responsible for programming the routing model. The SPD is
+responsible for ensuring that the routing model has been adhered to upon
+receiving an interrupt.
+
+#### 2.2.2 Secure payload dispatcher
+A SPD service is responsible for determining and maintaining the interrupt
+routing model supported by itself and the Secure Payload. It is also responsible
+for ferrying interrupts between secure and non-secure software depending upon
+the routing model. It could determine the routing model at build time or at
+runtime. It must use this information to register a handler for each interrupt
+type using the `register_interrupt_type_handler()` API in EL3 runtime firmware.
+
+If the routing model is not known to the SPD service at build time, then it must
+be provided by the SP as the result of its initialisation. The SPD should
+program the routing model only after SP initialisation has completed e.g. in the
+SPD initialisation function pointed to by the `bl32_init` variable.
+
+The SPD should determine the mechanism to pass control to the Secure Payload
+after receiving an interrupt from the EL3 runtime firmware. This information
+could either be provided to the SPD service at build time or by the SP at
+runtime.
+
+#### 2.2.2.1 Test secure payload dispatcher behavior
+The TSPD only handles Secure-EL1 interrupts and is provided with the following
+routing model at build time.
+
+*   Secure-EL1 interrupts are routed to EL3 when execution is in non-secure
+    state and are routed to the FEL when execution is in the secure state
+    i.e __CSS=0, TEL3=0__ & __CSS=1, TEL3=1__ for Secure-EL1 interrupts
+
+*   The default routing model is used for non-secure interrupts i.e they are
+    routed to the FEL in either security state i.e __CSS=0, TEL3=0__ &
+    __CSS=1, TEL3=0__ for Non-secure interrupts
+
+It performs the following actions in the `tspd_init()` function to fulfill the
+requirements mentioned earlier.
+
+1.  It passes control to the Test Secure Payload to perform its
+    initialisation. The TSP provides the address of the vector table
+    `tsp_vectors` in the SP which also includes the handler for Secure-EL1
+    interrupts in the `fiq_entry` field. The TSPD passes control to the TSP at
+    this address when it receives a Secure-EL1 interrupt.
+
+    The handover agreement between the TSP and the TSPD requires that the TSPD
+    masks all interrupts (`PSTATE.DAIF` bits) when it calls
+    `tsp_fiq_entry()`. The TSP has to preserve the callee saved general
+    purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use
+    `x0-x18` to enable its C runtime.
+
+2.  The TSPD implements a handler function for Secure-EL1 interrupts. It
+    registers it with the EL3 runtime firmware using the
+    `register_interrupt_type_handler()` API as follows
+
+        /* Forward declaration */
+        interrupt_type_handler tspd_secure_el1_interrupt_handler;
+        int32_t rc, flags = 0;
+        set_interrupt_rm_flag(flags, NON_SECURE);
+        rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+                                         tspd_secure_el1_interrupt_handler,
+                                         flags);
+        assert(rc == 0);
+
+#### 2.2.3 Secure payload
+A Secure Payload must implement an interrupt handling framework at Secure-EL1
+(Secure-EL1 IHF) to support its chosen interrupt routing model. Secure payload
+execution will alternate between the below cases.
+
+1.  In the code where IRQ, FIQ or both interrupts are enabled, if an interrupt
+    type is targeted to the FEL, then it will be routed to the Secure-EL1
+    exception vector table. This is defined as the asynchronous model of
+    handling interrupts. This mode applies to both Secure-EL1 and non-secure
+    interrupts.
+
+2.  In the code where both interrupts are disabled, if an interrupt type is
+    targeted to the FEL, then execution will eventually migrate to the
+    non-secure state. Any non-secure interrupts will be handled as described
+    in the routing model where __CSS=1 and TEL3=0__. Secure-EL1 interrupts
+    will be routed to EL3 (as per the routing model where __CSS=1 and
+    TEL3=1__) where the SPD service will hand them to the SP. This is defined
+    as the synchronous mode of handling interrupts.
+
+The interrupt handling framework implemented by the SP should support one or
+both these interrupt handling models depending upon the chosen routing model.
+
+The following list briefly describes how the choice of a valid routing model
+(See 1.2.3) effects the implementation of the Secure-EL1 IHF. If the choice of
+the interrupt routing model is not known to the SPD service at compile time,
+then the SP should pass this information to the SPD service at runtime during
+its initialisation phase.
+
+As mentioned earlier, it is assumed that the FIQ signal is used to generate
+Secure-EL1 interrupts and the IRQ signal is used to generate non-secure
+interrupts in either security state.
+
+##### 2.2.3.1 Secure payload IHF design w.r.t secure-EL1 interrupts
+1.  __CSS=0, TEL3=0__. If `PSTATE.F=0`, Secure-EL1 interrupts will be
+    trigerred at one of the Secure-EL1 FIQ exception vectors. The Secure-EL1
+    IHF should implement support for handling FIQ interrupts asynchronously.
+
+    If `PSTATE.F=1` then Secure-EL1 interrupts will be handled as per the
+    synchronous interrupt handling model. The SP could implement this scenario
+    by exporting a seperate entrypoint for Secure-EL1 interrupts to the SPD
+    service during the registration phase. The SPD service would also need to
+    know the state of the system, general purpose and the `PSTATE` registers
+    in which it should arrange to return execution to the SP. The SP should
+    provide this information in an implementation defined way during the
+    registration phase if it is not known to the SPD service at build time.
+
+2.  __CSS=1, TEL3=1__. Interrupts are routed to EL3 when execution is in
+    non-secure state. They should be handled through the synchronous interrupt
+    handling model as described in 1. above.
+
+3.  __CSS=0, TEL3=1__. Secure interrupts are routed to EL3 when execution is in
+    secure state. They will not be visible to the SP. The `PSTATE.F` bit in
+    Secure-EL1/Secure-EL0 will not mask FIQs. The EL3 runtime firmware will
+    call the handler registered by the SPD service for Secure-EL1
+    interrupts. Secure-EL1 IHF should then handle all Secure-EL1 interrupt
+    through the synchronous interrupt handling model described in 1. above.
+
+
+##### 2.2.3.2 Secure payload IHF design w.r.t non-secure interrupts
+1.  __CSS=0, TEL3=0__. If `PSTATE.I=0`, non-secure interrupts will be
+    trigerred at one of the Secure-EL1 IRQ exception vectors . The Secure-EL1
+    IHF should co-ordinate with the SPD service to transfer execution to the
+    non-secure state where the interrupt should be handled e.g the SP could
+    allocate a function identifier to issue a SMC64 or SMC32 to the SPD
+    service which indicates that the SP execution has been pre-empted by a
+    non-secure interrupt. If this function identifier is not known to the SPD
+    service at compile time then the SP could provide it during the
+    registration phase.
+
+    If `PSTATE.I=1` then the non-secure interrupt will pend until execution
+    resumes in the non-secure state.
+
+2.  __CSS=0, TEL3=1__.  Non-secure interrupts are routed to EL3. They will not
+    be visible to the SP. The `PSTATE.I` bit in Secure-EL1/Secure-EL0 will
+    have not effect. The SPD service should register a non-secure interrupt
+    handler which should save the SP state correctly and resume execution in
+    the non-secure state where the interrupt will be handled. The Secure-EL1
+    IHF does not need to take any action.
+
+3.  __CSS=1, TEL3=0__.  Non-secure interrupts are handled in the FEL in
+    non-secure state (EL1/EL2) and are not visible to the SP. This routing
+    model does not affect the SP behavior.
+
+
+A Secure Payload must also ensure that all Secure-EL1 interrupts are correctly
+configured at the interrupt controller by the platform port of the EL3 runtime
+firmware. It should configure any additional Secure-EL1 interrupts which the EL3
+runtime firmware is not aware of through its platform port.
+
+#### 2.2.3.3 Test secure payload behavior
+The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is
+described in Section 2.2.2. It is known to the TSPD service at build time.
+
+The TSP implements an entrypoint (`tsp_fiq_entry()`) for handling Secure-EL1
+interrupts taken in non-secure state and routed through the TSPD service
+(synchronous handling model). It passes the reference to this entrypoint via
+`tsp_vectors` to the TSPD service.
+
+The TSP also replaces the default exception vector table referenced through the
+`early_exceptions` variable, with a vector table capable of handling FIQ and IRQ
+exceptions taken at the same (Secure-EL1) exception level. This table is
+referenced through the `tsp_exceptions` variable and programmed into the
+VBAR_EL1. It caters for the asynchronous handling model.
+
+The TSP also programs the Secure Physical Timer in the ARM Generic Timer block
+to raise a periodic interrupt (every half a second) for the purpose of testing
+interrupt management across all the software components listed in 2.1
+
+
+### 2.3 Interrupt handling
+This section describes in detail the role of each software component (see
+Section 2.1) in handling an interrupt of a particular type.
+
+#### 2.3.1 EL3 runtime firmware
+The EL3 runtime firmware populates the IRQ and FIQ exception vectors referenced
+by the `runtime_exceptions` variable as follows.
+
+1.  IRQ and FIQ exceptions taken from the current exception level with
+    `SP_EL0` or `SP_EL3` are reported as irrecoverable error conditions. As
+    mentioned earlier, EL3 runtime firmware always executes with the
+    `PSTATE.I` and `PSTATE.F` bits set.
+
+2.  The following text describes how the IRQ and FIQ exceptions taken from a
+    lower exception level using AArch64 or AArch32 are handled.
+
+When an interrupt is generated, the vector for each interrupt type is
+responsible for:
+
+1.  Saving the entire general purpose register context (x0-x30) immediately
+    upon exception entry. The registers are saved in the per-cpu `cpu_context`
+    data structure referenced by the `SP_EL3`register.
+
+2.  Saving the `ELR_EL3`, `SP_EL0` and `SPSR_EL3` system registers in the
+    per-cpu `cpu_context` data structure referenced by the `SP_EL3` register.
+
+3.  Switching to the C runtime stack by restoring the `CTX_RUNTIME_SP` value
+    from the per-cpu `cpu_context` data structure in `SP_EL0` and
+    executing the `msr spsel, #0` instruction.
+
+4.  Determining the type of interrupt. Secure-EL1 interrupts will be signalled
+    at the FIQ vector. Non-secure interrupts will be signalled at the IRQ
+    vector. The platform should implement the following API to determine the
+    type of the pending interrupt.
+
+        uint32_t plat_ic_get_interrupt_type(void);
+
+    It should return either `INTR_TYPE_S_EL1` or `INTR_TYPE_NS`.
+
+5.  Determining the handler for the type of interrupt that has been generated.
+    The following API has been added for this purpose.
+
+        interrupt_type_handler get_interrupt_type_handler(uint32_t interrupt_type);
+
+    It returns the reference to the registered handler for this interrupt
+    type. The `handler` is retrieved from the `intr_type_desc_t` structure as
+    described in Section 2. `NULL` is returned if no handler has been
+    registered for this type of interrupt. This scenario is reported as an
+    irrecoverable error condition.
+
+6.  Calling the registered handler function for the interrupt type generated.
+    The firmware also determines the interrupt id if the IMF_READ_INTERRUPT_ID
+    build time flag is set. The id is set to `INTR_ID_UNAVAILABLE` if the flag
+    is not set. The id along with the current security state and a reference to
+    the `cpu_context_t` structure for the current security state are passed to
+    the handler function as its arguments.
+
+    The handler function returns a reference to the per-cpu `cpu_context_t`
+    structure for the target security state.
+
+7.  Calling `el3_exit()` to return from EL3 into a lower exception level in
+    the security state determined by the handler routine. The `el3_exit()`
+    function is responsible for restoring the register context from the
+    `cpu_context_t` data structure for the target security state.
+
+
+#### 2.3.2 Secure payload dispatcher
+
+##### 2.3.2.1 Interrupt entry
+The SPD service begins handling an interrupt when the EL3 runtime firmware calls
+the handler function for that type of interrupt. The SPD service is responsible
+for the following:
+
+1.  Validating the interrupt. This involves ensuring that the interrupt was
+    generating according to the interrupt routing model specified by the SPD
+    service during registration. It should use the interrupt id and the
+    security state of the exception level (passed in the `flags` parameter of
+    the handler) where the interrupt was taken from to determine this. If the
+    interrupt is not recognised then the handler should treat it as an
+    irrecoverable error condition.
+
+    A SPD service can register a handler for Secure-EL1 and/or Non-secure
+    interrupts. The following text describes further error scenarios keeping
+    this in mind:
+
+    1.  __SPD service has registered a handler for Non-secure interrupts__:
+        When an interrupt is received by the handler, it could check its id
+        to ensure it has been configured as a non-secure interrupt at the
+        interrupt controller. A secure interrupt should never be handed to
+        the non-secure interrupt handler. A non-secure interrupt should
+        never be routed to EL3 when execution is in non-secure state. The
+        handler could check the security state flag to ensure this.
+
+    2.  __SPD service has registered a handler for Secure-EL1 interrupts__:
+        When an interrupt is received by the handler, it could check its id
+        to ensure it has been configured as a secure interrupt at the
+        interrupt controller. A non-secure interrupt should never be handed
+        to the secure interrupt handler. If the routing model chosen is such
+        that Secure-EL1 interrupts are not routed to EL3 when execution is
+        in non-secure state, then a Secure-EL1 interrupt generated in the
+        secure state would be invalid. The handler could use the security
+        state flag to check this.
+
+    The SPD service should use the platform API:
+    `plat_ic_get_interrupt_type()` to determine the type of interrupt for the
+    specified id.
+
+2.  Determining whether the security state of the exception level for handling
+    the interrupt is the same as the security state of the exception level
+    where the interrupt was generated. This depends upon the routing model and
+    type of the interrupt. The SPD should use this information to determine if
+    a context switch is required. The following two cases would require a
+    context switch from secure to non-secure or vice-versa.
+
+    1.  A Secure-EL1 interrupt taken from the non-secure state should be
+        routed to the Secure Payload.
+
+    2.  A non-secure interrupt taken from the secure state should be routed
+        to the last known non-secure exception level.
+
+    The SPD service must save the system register context of the current
+    security state. It must then restore the system register context of the
+    target security state. It should use the `cm_set_next_eret_context()` API
+    to ensure that the next `cpu_context` to be restored is of the target
+    security state.
+
+    If the target state is secure then execution should be handed to the SP as
+    per the synchronous interrupt handling model it implements. A Secure-EL1
+    interrupt can be routed to EL3 while execution is in the SP. This implies
+    that SP execution can be preempted while handling an interrupt by a
+    another higher priority Secure-EL1 interrupt (or a EL3 interrupt in the
+    future). The SPD service should manage secure interrupt priorities before
+    handing control to the SP to prevent this type of preemption which can
+    leave the system in an inconsistent state.
+
+3.  Setting the return value of the handler to the per-cpu `cpu_context` if
+    the interrupt has been successfully validated and ready to be handled at a
+    lower exception level.
+
+The routing model allows non-secure interrupts to be taken to Secure-EL1 when in
+secure state. The SPD service and the SP should implement a mechanism for
+routing these interrupts to the last known exception level in the non-secure
+state. The former should save the SP context, restore the non-secure context and
+arrange for entry into the non-secure state so that the interrupt can be
+handled.
+
+##### 2.3.2.2 Interrupt exit
+When the Secure Payload has finished handling a Secure-EL1 interrupt, it could
+return control back to the SPD service through a SMC32 or SMC64. The SPD service
+should handle this secure monitor call so that execution resumes in the
+exception level and the security state from where the Secure-EL1 interrupt was
+originally taken.
+
+##### 2.3.2.3 Test secure payload dispatcher behavior
+The example TSPD service registers a handler for Secure-EL1 interrupts taken
+from the non-secure state. Its handler `tspd_secure_el1_interrupt_handler()`
+takes the following actions upon being invoked.
+
+1.  It uses the `id` parameter to query the interrupt controller to ensure
+    that the interrupt is a Secure-EL1 interrupt. It asserts if this is not
+    the case.
+
+2.  It uses the security state provided in the `flags` parameter to ensure
+    that the secure interrupt originated from the non-secure state. It asserts
+    if this is not the case.
+
+3.  It saves the system register context for the non-secure state by calling
+    `cm_el1_sysregs_context_save(NON_SECURE);`.
+
+4.  It sets the `ELR_EL3` system register to `tsp_fiq_entry` and sets the
+    `SPSR_EL3.DAIF` bits in the secure CPU context. It sets `x0` to
+    `TSP_HANDLE_FIQ_AND_RETURN`. If the TSP was in the middle of handling a
+    standard SMC, then the `ELR_EL3` and `SPSR_EL3` registers in the secure CPU
+    context are saved first.
+
+5.  It restores the system register context for the secure state by calling
+    `cm_el1_sysregs_context_restore(SECURE);`.
+
+6.  It ensures that the secure CPU context is used to program the next
+    exception return from EL3 by calling `cm_set_next_eret_context(SECURE);`.
+
+7.  It returns the per-cpu `cpu_context` to indicate that the interrupt can
+    now be handled by the SP. `x1` is written with the value of `elr_el3`
+    register for the non-secure state. This information is used by the SP for
+    debugging purposes.
+
+The figure below describes how the interrupt handling is implemented by the TSPD
+when a Secure-EL1 interrupt is generated when execution is in the non-secure
+state.
+
+![Image 1](diagrams/sec-int-handling.png?raw=true)
+
+The TSP issues an SMC with `TSP_HANDLED_S_EL1_FIQ` as the function identifier to
+signal completion of interrupt handling.
+
+The TSP issues an SMC with `TSP_PREEMPTED` as the function identifier to signal
+generation of a non-secure interrupt in Secure-EL1.
+
+The TSPD service takes the following actions in `tspd_smc_handler()` function
+upon receiving an SMC with `TSP_HANDLED_S_EL1_FIQ` and `TSP_PREEMPTED` as the
+function identifiers:
+
+1.  It ensures that the call originated from the secure state otherwise
+    execution returns to the non-secure state with `SMC_UNK` in `x0`.
+
+2.  If the function identifier is `TSP_HANDLED_S_EL1_FIQ`, it restores the
+    saved `ELR_EL3` and `SPSR_EL3` system registers back to the secure CPU
+    context (see step 4 above) in case the TSP had been preempted by a non
+    secure interrupt earlier.  It does not save the secure context since the
+    TSP is expected to preserve it (see Section 2.2.2.1)
+
+3.  If the function identifier is `TSP_PREEMPTED`, it saves the system
+    register context for the secure state by calling
+    `cm_el1_sysregs_context_save(SECURE)`.
+
+4.  It restores the system register context for the non-secure state by
+    calling `cm_el1_sysregs_context_restore(NON_SECURE)`. It sets `x0` to
+    `SMC_PREEMPTED` if the incoming function identifier is
+    `TSP_PREEMPTED`. The Normal World is expected to resume the TSP after the
+    non-secure interrupt handling by issuing an SMC with `TSP_FID_RESUME` as
+    the function identifier.
+
+5.  It ensures that the non-secure CPU context is used to program the next
+    exception return from EL3 by calling
+    `cm_set_next_eret_context(NON_SECURE)`.
+
+6.  `tspd_smc_handler()` returns a reference to the non-secure `cpu_context`
+    as the return value.
+
+As mentioned in 4. above, if a non-secure interrupt preempts the TSP execution
+then the non-secure software issues an SMC with `TSP_FID_RESUME` as the function
+identifier to resume TSP execution. The TSPD service takes the following actions
+in `tspd_smc_handler()` function upon receiving this SMC:
+
+1.  It ensures that the call originated from the non secure state. An
+    assertion is raised otherwise.
+
+2.  Checks whether the TSP needs a resume i.e check if it was preempted. It
+    then saves the system register context for the secure state by calling
+    `cm_el1_sysregs_context_save(NON_SECURE)`.
+
+3.  Restores the secure context by calling
+    `cm_el1_sysregs_context_restore(SECURE)`
+
+4.  It ensures that the secure CPU context is used to program the next
+    exception return from EL3 by calling `cm_set_next_eret_context(SECURE)`.
+
+5.  `tspd_smc_handler()` returns a reference to the secure `cpu_context` as the
+    return value.
+
+The figure below describes how the TSP/TSPD handle a non-secure interrupt when
+it is generated during execution in the TSP with `PSTATE.I` = 0.
+
+![Image 2](diagrams/non-sec-int-handling.png?raw=true)
+
+
+#### 2.3.3 Secure payload
+The SP should implement one or both of the synchronous and asynchronous
+interrupt handling models depending upon the interrupt routing model it has
+chosen (as described in 2.2.3).
+
+In the synchronous model, it should begin handling a Secure-EL1 interrupt after
+receiving control from the SPD service at an entrypoint agreed upon during build
+time or during the registration phase. Before handling the interrupt, the SP
+should save any Secure-EL1 system register context which is needed for resuming
+normal execution in the SP later e.g. `SPSR_EL1, `ELR_EL1`. After handling the
+interrupt, the SP could return control back to the exception level and security
+state where the interrupt was originally taken from. The SP should use an SMC32
+or SMC64 to ask the SPD service to do this.
+
+In the asynchronous model, the Secure Payload is responsible for handling
+non-secure and Secure-EL1 interrupts at the IRQ and FIQ vectors in its exception
+vector table when `PSTATE.I` and `PSTATE.F` bits are 0. As described earlier,
+when a non-secure interrupt is generated, the SP should coordinate with the SPD
+service to pass control back to the non-secure state in the last known exception
+level. This will allow the non-secure interrupt to be handled in the non-secure
+state.
+
+##### 2.3.3.1 Test secure payload behavior
+The TSPD hands control of a Secure-EL1 interrupt to the TSP at the
+`tsp_fiq_entry()`.  The TSP handles the interrupt while ensuring that the
+handover agreement described in Section 2.2.2.1 is maintained. It updates some
+statistics by calling `tsp_update_sync_fiq_stats()`. It then calls
+`tsp_fiq_handler()` which.
+
+1.  Checks whether the interrupt is the secure physical timer interrupt. It
+    uses the platform API `plat_ic_get_pending_interrupt_id()` to get the
+    interrupt number.
+
+2.   Handles the interrupt by acknowledging it using the
+    `plat_ic_acknowledge_interrupt()` platform API, calling
+    `tsp_generic_timer_handler()` to reprogram the secure physical generic
+    timer and calling the `plat_ic_end_of_interrupt()` platform API to signal
+    end of interrupt processing.
+
+The TSP passes control back to the TSPD by issuing an SMC64 with
+`TSP_HANDLED_S_EL1_FIQ` as the function identifier.
+
+The TSP handles interrupts under the asynchronous model as follows.
+
+1.  Secure-EL1 interrupts are handled by calling the `tsp_fiq_handler()`
+    function. The function has been described above.
+
+2.  Non-secure interrupts are handled by issuing an SMC64 with `TSP_PREEMPTED`
+    as the function identifier. Execution resumes at the instruction that
+    follows this SMC instruction when the TSPD hands control to the TSP in
+    response to an SMC with `TSP_FID_RESUME` as the function identifier from
+    the non-secure state (see section 2.3.2.1).
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._
+
+[Porting Guide]:             ./porting-guide.md
diff --git a/docs/optee-dispatcher.md b/docs/optee-dispatcher.md
new file mode 100644 (file)
index 0000000..c154f6b
--- /dev/null
@@ -0,0 +1,13 @@
+OP-TEE Dispatcher
+=================
+
+[OP-TEE OS] is a Trusted OS running as Secure EL1.
+
+To build and execute [OP-TEE OS] follow the instructions at
+[ARM Trusted Firmware with OP-TEE] [OP-TEE OS]
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._
+
+[OP-TEE OS]:  http://github.com/OP-TEE/optee_os/tree/master/documentation/arm_trusted_firmware.md
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
new file mode 100644 (file)
index 0000000..5e85023
--- /dev/null
@@ -0,0 +1,1569 @@
+ARM Trusted Firmware Porting Guide
+==================================
+
+Contents
+--------
+
+1.  [Introduction](#1--introduction)
+2.  [Common Modifications](#2--common-modifications)
+    *   [Common mandatory modifications](#21-common-mandatory-modifications)
+    *   [Handling reset](#22-handling-reset)
+    *   [Common optional modifications](#23-common-optional-modifications)
+3.  [Boot Loader stage specific modifications](#3--modifications-specific-to-a-boot-loader-stage)
+    *   [Boot Loader stage 1 (BL1)](#31-boot-loader-stage-1-bl1)
+    *   [Boot Loader stage 2 (BL2)](#32-boot-loader-stage-2-bl2)
+    *   [Boot Loader stage 3-1 (BL3-1)](#32-boot-loader-stage-3-1-bl3-1)
+    *   [PSCI implementation (in BL3-1)](#33-power-state-coordination-interface-in-bl3-1)
+    *   [Interrupt Management framework (in BL3-1)](#34--interrupt-management-framework-in-bl3-1)
+    *   [Crash Reporting mechanism (in BL3-1)](#35--crash-reporting-mechanism-in-bl3-1)
+4.  [Build flags](#4--build-flags)
+5.  [C Library](#5--c-library)
+6.  [Storage abstraction layer](#6--storage-abstraction-layer)
+
+- - - - - - - - - - - - - - - - - -
+
+1.  Introduction
+----------------
+
+Porting the ARM Trusted Firmware to a new platform involves making some
+mandatory and optional modifications for both the cold and warm boot paths.
+Modifications consist of:
+
+*   Implementing a platform-specific function or variable,
+*   Setting up the execution context in a certain way, or
+*   Defining certain constants (for example #defines).
+
+The platform-specific functions and variables are all declared in
+[include/plat/common/platform.h]. The firmware provides a default implementation
+of variables and functions to fulfill the optional requirements. These
+implementations are all weakly defined; they are provided to ease the porting
+effort. Each platform port can override them with its own implementation if the
+default implementation is inadequate.
+
+Some modifications are common to all Boot Loader (BL) stages. Section 2
+discusses these in detail. The subsequent sections discuss the remaining
+modifications for each BL stage in detail.
+
+This document should be read in conjunction with the ARM Trusted Firmware
+[User Guide].
+
+
+2.  Common modifications
+------------------------
+
+This section covers the modifications that should be made by the platform for
+each BL stage to correctly port the firmware stack. They are categorized as
+either mandatory or optional.
+
+
+2.1 Common mandatory modifications
+----------------------------------
+A platform port must enable the Memory Management Unit (MMU) with identity
+mapped page tables, and enable both the instruction and data caches for each BL
+stage. In the ARM FVP port, each BL stage configures the MMU in its platform-
+specific architecture setup function, for example `blX_plat_arch_setup()`.
+
+If the build option `USE_COHERENT_MEM` is enabled, each platform must allocate a
+block of identity mapped secure memory with Device-nGnRE attributes aligned to
+page boundary (4K) for each BL stage. This memory is identified by the section
+name `tzfw_coherent_mem` so that its possible for the firmware to place
+variables in it using the following C code directive:
+
+    __attribute__ ((section("tzfw_coherent_mem")))
+
+Or alternatively the following assembler code directive:
+
+    .section tzfw_coherent_mem
+
+The `tzfw_coherent_mem` section is used to allocate any data structures that are
+accessed both when a CPU is executing with its MMU and caches enabled, and when
+it's running with its MMU and caches disabled. Examples are given below.
+
+The following variables, functions and constants must be defined by the platform
+for the firmware to work correctly.
+
+
+### File : platform_def.h [mandatory]
+
+Each platform must ensure that a header file of this name is in the system
+include path with the following constants defined. This may require updating the
+list of `PLAT_INCLUDES` in the `platform.mk` file. In the ARM FVP port, this
+file is found in [plat/fvp/include/platform_def.h].
+
+*   **#define : PLATFORM_LINKER_FORMAT**
+
+    Defines the linker format used by the platform, for example
+    `elf64-littleaarch64` used by the FVP.
+
+*   **#define : PLATFORM_LINKER_ARCH**
+
+    Defines the processor architecture for the linker by the platform, for
+    example `aarch64` used by the FVP.
+
+*   **#define : PLATFORM_STACK_SIZE**
+
+    Defines the normal stack memory available to each CPU. This constant is used
+    by [plat/common/aarch64/platform_mp_stack.S] and
+    [plat/common/aarch64/platform_up_stack.S].
+
+*   **#define : FIRMWARE_WELCOME_STR**
+
+    Defines the character string printed by BL1 upon entry into the `bl1_main()`
+    function.
+
+*   **#define : BL2_IMAGE_NAME**
+
+    Name of the BL2 binary image on the host file-system. This name is used by
+    BL1 to load BL2 into secure memory from non-volatile storage.
+
+*   **#define : BL31_IMAGE_NAME**
+
+    Name of the BL3-1 binary image on the host file-system. This name is used by
+    BL2 to load BL3-1 into secure memory from platform storage.
+
+*   **#define : BL33_IMAGE_NAME**
+
+    Name of the BL3-3 binary image on the host file-system. This name is used by
+    BL2 to load BL3-3 into non-secure memory from platform storage.
+
+*   **#define : BL2_CERT_NAME**
+
+    Name of the BL2 content certificate on the host file-system (mandatory when
+    Trusted Board Boot is enabled).
+
+*   **#define : TRUSTED_KEY_CERT_NAME**
+
+    Name of the Trusted Key certificate on the host file-system (mandatory when
+    Trusted Board Boot is enabled).
+
+*   **#define : BL31_KEY_CERT_NAME**
+
+    Name of the BL3-1 Key certificate on the host file-system (mandatory when
+    Trusted Board Boot is enabled).
+
+*   **#define : BL31_CERT_NAME**
+
+    Name of the BL3-1 Content certificate on the host file-system (mandatory
+    when Trusted Board Boot is enabled).
+
+*   **#define : BL33_KEY_CERT_NAME**
+
+    Name of the BL3-3 Key certificate on the host file-system (mandatory when
+    Trusted Board Boot is enabled).
+
+*   **#define : BL33_CERT_NAME**
+
+    Name of the BL3-3 Content certificate on the host file-system (mandatory
+    when Trusted Board Boot is enabled).
+
+*   **#define : PLATFORM_CACHE_LINE_SIZE**
+
+    Defines the size (in bytes) of the largest cache line across all the cache
+    levels in the platform.
+
+*   **#define : PLATFORM_CLUSTER_COUNT**
+
+    Defines the total number of clusters implemented by the platform in the
+    system.
+
+*   **#define : PLATFORM_CORE_COUNT**
+
+    Defines the total number of CPUs implemented by the platform across all
+    clusters in the system.
+
+*   **#define : PLATFORM_MAX_CPUS_PER_CLUSTER**
+
+    Defines the maximum number of CPUs that can be implemented within a cluster
+    on the platform.
+
+*   **#define : PLATFORM_NUM_AFFS**
+
+    Defines the total number of nodes in the affinity heirarchy at all affinity
+    levels used by the platform.
+
+*   **#define : BL1_RO_BASE**
+
+    Defines the base address in secure ROM where BL1 originally lives. Must be
+    aligned on a page-size boundary.
+
+*   **#define : BL1_RO_LIMIT**
+
+    Defines the maximum address in secure ROM that BL1's actual content (i.e.
+    excluding any data section allocated at runtime) can occupy.
+
+*   **#define : BL1_RW_BASE**
+
+    Defines the base address in secure RAM where BL1's read-write data will live
+    at runtime. Must be aligned on a page-size boundary.
+
+*   **#define : BL1_RW_LIMIT**
+
+    Defines the maximum address in secure RAM that BL1's read-write data can
+    occupy at runtime.
+
+*   **#define : BL2_BASE**
+
+    Defines the base address in secure RAM where BL1 loads the BL2 binary image.
+    Must be aligned on a page-size boundary.
+
+*   **#define : BL2_LIMIT**
+
+    Defines the maximum address in secure RAM that the BL2 image can occupy.
+
+*   **#define : BL31_BASE**
+
+    Defines the base address in secure RAM where BL2 loads the BL3-1 binary
+    image. Must be aligned on a page-size boundary.
+
+*   **#define : BL31_LIMIT**
+
+    Defines the maximum address in secure RAM that the BL3-1 image can occupy.
+
+*   **#define : NS_IMAGE_OFFSET**
+
+    Defines the base address in non-secure DRAM where BL2 loads the BL3-3 binary
+    image. Must be aligned on a page-size boundary.
+
+If a BL3-0 image is supported by the platform, the following constants must
+also be defined:
+
+*   **#define : BL30_IMAGE_NAME**
+
+    Name of the BL3-0 binary image on the host file-system. This name is used by
+    BL2 to load BL3-0 into secure memory from platform storage before being
+    transfered to the SCP.
+
+*   **#define : BL30_KEY_CERT_NAME**
+
+    Name of the BL3-0 Key certificate on the host file-system (mandatory when
+    Trusted Board Boot is enabled).
+
+*   **#define : BL30_CERT_NAME**
+
+    Name of the BL3-0 Content certificate on the host file-system (mandatory
+    when Trusted Board Boot is enabled).
+
+If a BL3-2 image is supported by the platform, the following constants must
+also be defined:
+
+*   **#define : BL32_IMAGE_NAME**
+
+    Name of the BL3-2 binary image on the host file-system. This name is used by
+    BL2 to load BL3-2 into secure memory from platform storage.
+
+*   **#define : BL32_KEY_CERT_NAME**
+
+    Name of the BL3-2 Key certificate on the host file-system (mandatory when
+    Trusted Board Boot is enabled).
+
+*   **#define : BL32_CERT_NAME**
+
+    Name of the BL3-2 Content certificate on the host file-system (mandatory
+    when Trusted Board Boot is enabled).
+
+*   **#define : BL32_BASE**
+
+    Defines the base address in secure memory where BL2 loads the BL3-2 binary
+    image. Must be aligned on a page-size boundary.
+
+*   **#define : BL32_LIMIT**
+
+    Defines the maximum address that the BL3-2 image can occupy.
+
+If the Test Secure-EL1 Payload (TSP) instantiation of BL3-2 is supported by the
+platform, the following constants must also be defined:
+
+*   **#define : TSP_SEC_MEM_BASE**
+
+    Defines the base address of the secure memory used by the TSP image on the
+    platform. This must be at the same address or below `BL32_BASE`.
+
+*   **#define : TSP_SEC_MEM_SIZE**
+
+    Defines the size of the secure memory used by the BL3-2 image on the
+    platform. `TSP_SEC_MEM_BASE` and `TSP_SEC_MEM_SIZE` must fully accomodate
+    the memory required by the BL3-2 image, defined by `BL32_BASE` and
+    `BL32_LIMIT`.
+
+*   **#define : TSP_IRQ_SEC_PHY_TIMER**
+
+    Defines the ID of the secure physical generic timer interrupt used by the
+    TSP's interrupt handling code.
+
+If the platform port uses the IO storage framework, the following constants
+must also be defined:
+
+*   **#define : MAX_IO_DEVICES**
+
+    Defines the maximum number of registered IO devices. Attempting to register
+    more devices than this value using `io_register_device()` will fail with
+    IO_RESOURCES_EXHAUSTED.
+
+*   **#define : MAX_IO_HANDLES**
+
+    Defines the maximum number of open IO handles. Attempting to open more IO
+    entities than this value using `io_open()` will fail with
+    IO_RESOURCES_EXHAUSTED.
+
+If the platform needs to allocate data within the per-cpu data framework in
+BL3-1, it should define the following macro. Currently this is only required if
+the platform decides not to use the coherent memory section by undefining the
+USE_COHERENT_MEM build flag. In this case, the framework allocates the required
+memory within the the per-cpu data to minimize wastage.
+
+*   **#define : PLAT_PCPU_DATA_SIZE**
+
+    Defines the memory (in bytes) to be reserved within the per-cpu data
+    structure for use by the platform layer.
+
+The following constants are optional. They should be defined when the platform
+memory layout implies some image overlaying like on FVP.
+
+*   **#define : BL31_PROGBITS_LIMIT**
+
+    Defines the maximum address in secure RAM that the BL3-1's progbits sections
+    can occupy.
+
+*   **#define : TSP_PROGBITS_LIMIT**
+
+    Defines the maximum address that the TSP's progbits sections can occupy.
+
+### File : plat_macros.S [mandatory]
+
+Each platform must ensure a file of this name is in the system include path with
+the following macro defined. In the ARM FVP port, this file is found in
+[plat/fvp/include/plat_macros.S].
+
+*   **Macro : plat_print_gic_regs**
+
+    This macro allows the crash reporting routine to print GIC registers
+    in case of an unhandled exception in BL3-1. This aids in debugging and
+    this macro can be defined to be empty in case GIC register reporting is
+    not desired.
+
+*   **Macro : plat_print_interconnect_regs**
+
+    This macro allows the crash reporting routine to print interconnect registers
+    in case of an unhandled exception in BL3-1. This aids in debugging and
+    this macro can be defined to be empty in case interconnect register reporting
+    is not desired. In the ARM FVP port, the CCI snoop control registers are
+    reported.
+
+### Other mandatory modifications
+
+The following mandatory modifications may be implemented in any file
+the implementer chooses. In the ARM FVP port, they are implemented in
+[plat/fvp/aarch64/plat_common.c].
+
+*   **Function : uint64_t plat_get_syscnt_freq(void)**
+
+    This function is used by the architecture setup code to retrieve the
+    counter frequency for the CPU's generic timer.  This value will be
+    programmed into the `CNTFRQ_EL0` register.
+    In the ARM FVP port, it returns the base frequency of the system counter,
+    which is retrieved from the first entry in the frequency modes table.
+
+
+2.2 Handling Reset
+------------------
+
+BL1 by default implements the reset vector where execution starts from a cold
+or warm boot. BL3-1 can be optionally set as a reset vector using the
+RESET_TO_BL31 make variable.
+
+For each CPU, the reset vector code is responsible for the following tasks:
+
+1.  Distinguishing between a cold boot and a warm boot.
+
+2.  In the case of a cold boot and the CPU being a secondary CPU, ensuring that
+    the CPU is placed in a platform-specific state until the primary CPU
+    performs the necessary steps to remove it from this state.
+
+3.  In the case of a warm boot, ensuring that the CPU jumps to a platform-
+    specific address in the BL3-1 image in the same processor mode as it was
+    when released from reset.
+
+The following functions need to be implemented by the platform port to enable
+reset vector code to perform the above tasks.
+
+
+### Function : platform_get_entrypoint() [mandatory]
+
+    Argument : unsigned long
+    Return   : unsigned int
+
+This function is called with the `SCTLR.M` and `SCTLR.C` bits disabled. The CPU
+is identified by its `MPIDR`, which is passed as the argument. The function is
+responsible for distinguishing between a warm and cold reset using platform-
+specific means. If it's a warm reset then it returns the entrypoint into the
+BL3-1 image that the CPU must jump to. If it's a cold reset then this function
+must return zero.
+
+This function is also responsible for implementing a platform-specific mechanism
+to handle the condition where the CPU has been warm reset but there is no
+entrypoint to jump to.
+
+This function does not follow the Procedure Call Standard used by the
+Application Binary Interface for the ARM 64-bit architecture. The caller should
+not assume that callee saved registers are preserved across a call to this
+function.
+
+This function fulfills requirement 1 and 3 listed above.
+
+
+### Function : plat_secondary_cold_boot_setup() [mandatory]
+
+    Argument : void
+    Return   : void
+
+This function is called with the MMU and data caches disabled. It is responsible
+for placing the executing secondary CPU in a platform-specific state until the
+primary CPU performs the necessary actions to bring it out of that state and
+allow entry into the OS.
+
+In the ARM FVP port, each secondary CPU powers itself off. The primary CPU is
+responsible for powering up the secondary CPU when normal world software
+requires them.
+
+This function fulfills requirement 2 above.
+
+
+### Function : platform_is_primary_cpu() [mandatory]
+
+    Argument : unsigned long
+    Return   : unsigned int
+
+This function identifies a CPU by its `MPIDR`, which is passed as the argument,
+to determine whether this CPU is the primary CPU or a secondary CPU. A return
+value of zero indicates that the CPU is not the primary CPU, while a non-zero
+return value indicates that the CPU is the primary CPU.
+
+
+### Function : platform_mem_init() [mandatory]
+
+    Argument : void
+    Return   : void
+
+This function is called before any access to data is made by the firmware, in
+order to carry out any essential memory initialization.
+
+The ARM FVP port uses this function to initialize the mailbox memory used for
+providing the warm-boot entry-point addresses.
+
+
+### Function: plat_match_rotpk()
+
+    Argument : const unsigned char *, unsigned int
+    Return   : int
+
+This function is mandatory when Trusted Board Boot is enabled. It receives a
+pointer to a buffer containing a signing key and its size as parameters and
+returns 0 (success) if that key matches the ROT (Root Of Trust) key stored in
+the platform. Any other return value means a mismatch.
+
+
+
+2.3 Common optional modifications
+---------------------------------
+
+The following are helper functions implemented by the firmware that perform
+common platform-specific tasks. A platform may choose to override these
+definitions.
+
+
+### Function : platform_get_core_pos()
+
+    Argument : unsigned long
+    Return   : int
+
+A platform may need to convert the `MPIDR` of a CPU to an absolute number, which
+can be used as a CPU-specific linear index into blocks of memory (for example
+while allocating per-CPU stacks). This routine contains a simple mechanism
+to perform this conversion, using the assumption that each cluster contains a
+maximum of 4 CPUs:
+
+    linear index = cpu_id + (cluster_id * 4)
+
+    cpu_id = 8-bit value in MPIDR at affinity level 0
+    cluster_id = 8-bit value in MPIDR at affinity level 1
+
+
+### Function : platform_set_stack()
+
+    Argument : unsigned long
+    Return   : void
+
+This function sets the current stack pointer to the normal memory stack that
+has been allocated for the CPU specificed by MPIDR. For BL images that only
+require a stack for the primary CPU the parameter is ignored. The size of
+the stack allocated to each CPU is specified by the platform defined constant
+`PLATFORM_STACK_SIZE`.
+
+Common implementations of this function for the UP and MP BL images are
+provided in [plat/common/aarch64/platform_up_stack.S] and
+[plat/common/aarch64/platform_mp_stack.S]
+
+
+### Function : platform_get_stack()
+
+    Argument : unsigned long
+    Return   : unsigned long
+
+This function returns the base address of the normal memory stack that
+has been allocated for the CPU specificed by MPIDR. For BL images that only
+require a stack for the primary CPU the parameter is ignored. The size of
+the stack allocated to each CPU is specified by the platform defined constant
+`PLATFORM_STACK_SIZE`.
+
+Common implementations of this function for the UP and MP BL images are
+provided in [plat/common/aarch64/platform_up_stack.S] and
+[plat/common/aarch64/platform_mp_stack.S]
+
+
+### Function : plat_report_exception()
+
+    Argument : unsigned int
+    Return   : void
+
+A platform may need to report various information about its status when an
+exception is taken, for example the current exception level, the CPU security
+state (secure/non-secure), the exception type, and so on. This function is
+called in the following circumstances:
+
+*   In BL1, whenever an exception is taken.
+*   In BL2, whenever an exception is taken.
+
+The default implementation doesn't do anything, to avoid making assumptions
+about the way the platform displays its status information.
+
+This function receives the exception type as its argument. Possible values for
+exceptions types are listed in the [include/runtime_svc.h] header file. Note
+that these constants are not related to any architectural exception code; they
+are just an ARM Trusted Firmware convention.
+
+
+### Function : plat_reset_handler()
+
+    Argument : void
+    Return   : void
+
+A platform may need to do additional initialization after reset. This function
+allows the platform to do the platform specific intializations. Platform
+specific errata workarounds could also be implemented here. The api should
+preserve the values of callee saved registers x19 to x29.
+
+The default implementation doesn't do anything. If a platform needs to override
+the default implementation, refer to the [Firmware Design Guide] for general
+guidelines regarding placement of code in a reset handler.
+
+### Function : plat_disable_acp()
+
+    Argument : void
+    Return   : void
+
+This api allows a platform to disable the Accelerator Coherency Port (if
+present) during a cluster power down sequence. The default weak implementation
+doesn't do anything. Since this api is called during the power down sequence,
+it has restrictions for stack usage and it can use the registers x0 - x17 as
+scratch registers. It should preserve the value in x18 register as it is used
+by the caller to store the return address.
+
+
+3.  Modifications specific to a Boot Loader stage
+-------------------------------------------------
+
+3.1 Boot Loader Stage 1 (BL1)
+-----------------------------
+
+BL1 implements the reset vector where execution starts from after a cold or
+warm boot. For each CPU, BL1 is responsible for the following tasks:
+
+1.  Handling the reset as described in section 2.2
+
+2.  In the case of a cold boot and the CPU being the primary CPU, ensuring that
+    only this CPU executes the remaining BL1 code, including loading and passing
+    control to the BL2 stage.
+
+3.  Loading the BL2 image from non-volatile storage into secure memory at the
+    address specified by the platform defined constant `BL2_BASE`.
+
+4.  Populating a `meminfo` structure with the following information in memory,
+    accessible by BL2 immediately upon entry.
+
+        meminfo.total_base = Base address of secure RAM visible to BL2
+        meminfo.total_size = Size of secure RAM visible to BL2
+        meminfo.free_base  = Base address of secure RAM available for
+                             allocation to BL2
+        meminfo.free_size  = Size of secure RAM available for allocation to BL2
+
+    BL1 places this `meminfo` structure at the beginning of the free memory
+    available for its use. Since BL1 cannot allocate memory dynamically at the
+    moment, its free memory will be available for BL2's use as-is. However, this
+    means that BL2 must read the `meminfo` structure before it starts using its
+    free memory (this is discussed in Section 3.2).
+
+    In future releases of the ARM Trusted Firmware it will be possible for
+    the platform to decide where it wants to place the `meminfo` structure for
+    BL2.
+
+    BL1 implements the `bl1_init_bl2_mem_layout()` function to populate the
+    BL2 `meminfo` structure. The platform may override this implementation, for
+    example if the platform wants to restrict the amount of memory visible to
+    BL2. Details of how to do this are given below.
+
+The following functions need to be implemented by the platform port to enable
+BL1 to perform the above tasks.
+
+
+### Function : bl1_plat_arch_setup() [mandatory]
+
+    Argument : void
+    Return   : void
+
+This function performs any platform-specific and architectural setup that the
+platform requires.  Platform-specific setup might include configuration of
+memory controllers, configuration of the interconnect to allow the cluster
+to service cache snoop requests from another cluster, and so on.
+
+In the ARM FVP port, this function enables CCI snoops into the cluster that the
+primary CPU is part of. It also enables the MMU.
+
+This function helps fulfill requirement 2 above.
+
+
+### Function : bl1_platform_setup() [mandatory]
+
+    Argument : void
+    Return   : void
+
+This function executes with the MMU and data caches enabled. It is responsible
+for performing any remaining platform-specific setup that can occur after the
+MMU and data cache have been enabled.
+
+This function is also responsible for initializing the storage abstraction layer
+which is used to load further bootloader images.
+
+This function helps fulfill requirement 3 above.
+
+
+### Function : bl1_plat_sec_mem_layout() [mandatory]
+
+    Argument : void
+    Return   : meminfo *
+
+This function should only be called on the cold boot path. It executes with the
+MMU and data caches enabled. The pointer returned by this function must point to
+a `meminfo` structure containing the extents and availability of secure RAM for
+the BL1 stage.
+
+    meminfo.total_base = Base address of secure RAM visible to BL1
+    meminfo.total_size = Size of secure RAM visible to BL1
+    meminfo.free_base  = Base address of secure RAM available for allocation
+                         to BL1
+    meminfo.free_size  = Size of secure RAM available for allocation to BL1
+
+This information is used by BL1 to load the BL2 image in secure RAM. BL1 also
+populates a similar structure to tell BL2 the extents of memory available for
+its own use.
+
+This function helps fulfill requirement 3 above.
+
+
+### Function : bl1_init_bl2_mem_layout() [optional]
+
+    Argument : meminfo *, meminfo *, unsigned int, unsigned long
+    Return   : void
+
+BL1 needs to tell the next stage the amount of secure RAM available
+for it to use. This information is populated in a `meminfo`
+structure.
+
+Depending upon where BL2 has been loaded in secure RAM (determined by
+`BL2_BASE`), BL1 calculates the amount of free memory available for BL2 to use.
+BL1 also ensures that its data sections resident in secure RAM are not visible
+to BL2. An illustration of how this is done in the ARM FVP port is given in the
+[User Guide], in the Section "Memory layout on Base FVP".
+
+
+### Function : bl1_plat_set_bl2_ep_info() [mandatory]
+
+    Argument : image_info *, entry_point_info *
+    Return   : void
+
+This function is called after loading BL2 image and it can be used to overwrite
+the entry point set by loader and also set the security state and SPSR which
+represents the entry point system state for BL2.
+
+On FVP, we are setting the security state and the SPSR for the BL2 entrypoint
+
+
+3.2 Boot Loader Stage 2 (BL2)
+-----------------------------
+
+The BL2 stage is executed only by the primary CPU, which is determined in BL1
+using the `platform_is_primary_cpu()` function. BL1 passed control to BL2 at
+`BL2_BASE`. BL2 executes in Secure EL1 and is responsible for:
+
+1.  (Optional) Loading the BL3-0 binary image (if present) from platform
+    provided non-volatile storage. To load the BL3-0 image, BL2 makes use of
+    the `meminfo` returned by the `bl2_plat_get_bl30_meminfo()` function.
+    The platform also defines the address in memory where BL3-0 is loaded
+    through the optional constant `BL30_BASE`. BL2 uses this information
+    to determine if there is enough memory to load the BL3-0 image.
+    Subsequent handling of the BL3-0 image is platform-specific and is
+    implemented in the `bl2_plat_handle_bl30()` function.
+    If `BL30_BASE` is not defined then this step is not performed.
+
+2.  Loading the BL3-1 binary image into secure RAM from non-volatile storage. To
+    load the BL3-1 image, BL2 makes use of the `meminfo` structure passed to it
+    by BL1. This structure allows BL2 to calculate how much secure RAM is
+    available for its use. The platform also defines the address in secure RAM
+    where BL3-1 is loaded through the constant `BL31_BASE`. BL2 uses this
+    information to determine if there is enough memory to load the BL3-1 image.
+
+3.  (Optional) Loading the BL3-2 binary image (if present) from platform
+    provided non-volatile storage. To load the BL3-2 image, BL2 makes use of
+    the `meminfo` returned by the `bl2_plat_get_bl32_meminfo()` function.
+    The platform also defines the address in memory where BL3-2 is loaded
+    through the optional constant `BL32_BASE`. BL2 uses this information
+    to determine if there is enough memory to load the BL3-2 image.
+    If `BL32_BASE` is not defined then this and the next step is not performed.
+
+4.  (Optional) Arranging to pass control to the BL3-2 image (if present) that
+    has been pre-loaded at `BL32_BASE`. BL2 populates an `entry_point_info`
+    structure in memory provided by the platform with information about how
+    BL3-1 should pass control to the BL3-2 image.
+
+5.  Loading the normal world BL3-3 binary image into non-secure DRAM from
+    platform storage and arranging for BL3-1 to pass control to this image. This
+    address is determined using the `plat_get_ns_image_entrypoint()` function
+    described below.
+
+6.  BL2 populates an `entry_point_info` structure in memory provided by the
+    platform with information about how BL3-1 should pass control to the
+    other BL images.
+
+The following functions must be implemented by the platform port to enable BL2
+to perform the above tasks.
+
+
+### Function : bl2_early_platform_setup() [mandatory]
+
+    Argument : meminfo *
+    Return   : void
+
+This function executes with the MMU and data caches disabled. It is only called
+by the primary CPU. The arguments to this function is the address of the
+`meminfo` structure populated by BL1.
+
+The platform must copy the contents of the `meminfo` structure into a private
+variable as the original memory may be subsequently overwritten by BL2. The
+copied structure is made available to all BL2 code through the
+`bl2_plat_sec_mem_layout()` function.
+
+
+### Function : bl2_plat_arch_setup() [mandatory]
+
+    Argument : void
+    Return   : void
+
+This function executes with the MMU and data caches disabled. It is only called
+by the primary CPU.
+
+The purpose of this function is to perform any architectural initialization
+that varies across platforms, for example enabling the MMU (since the memory
+map differs across platforms).
+
+
+### Function : bl2_platform_setup() [mandatory]
+
+    Argument : void
+    Return   : void
+
+This function may execute with the MMU and data caches enabled if the platform
+port does the necessary initialization in `bl2_plat_arch_setup()`. It is only
+called by the primary CPU.
+
+The purpose of this function is to perform any platform initialization
+specific to BL2. Platform security components are configured if required.
+For the Base FVP the TZC-400 TrustZone controller is configured to only
+grant non-secure access to DRAM. This avoids aliasing between secure and
+non-secure accesses in the TLB and cache - secure execution states can use
+the NS attributes in the MMU translation tables to access the DRAM.
+
+This function is also responsible for initializing the storage abstraction layer
+which is used to load further bootloader images.
+
+
+### Function : bl2_plat_sec_mem_layout() [mandatory]
+
+    Argument : void
+    Return   : meminfo *
+
+This function should only be called on the cold boot path. It may execute with
+the MMU and data caches enabled if the platform port does the necessary
+initialization in `bl2_plat_arch_setup()`. It is only called by the primary CPU.
+
+The purpose of this function is to return a pointer to a `meminfo` structure
+populated with the extents of secure RAM available for BL2 to use. See
+`bl2_early_platform_setup()` above.
+
+
+### Function : bl2_plat_get_bl30_meminfo() [mandatory]
+
+    Argument : meminfo *
+    Return   : void
+
+This function is used to get the memory limits where BL2 can load the
+BL3-0 image. The meminfo provided by this is used by load_image() to
+validate whether the BL3-0 image can be loaded within the given
+memory from the given base.
+
+
+### Function : bl2_plat_handle_bl30() [mandatory]
+
+    Argument : image_info *
+    Return   : int
+
+This function is called after loading BL3-0 image and it is used to perform any
+platform-specific actions required to handle the SCP firmware. Typically it
+transfers the image into SCP memory using a platform-specific protocol and waits
+until SCP executes it and signals to the Application Processor (AP) for BL2
+execution to continue.
+
+This function returns 0 on success, a negative error code otherwise.
+
+
+### Function : bl2_plat_get_bl31_params() [mandatory]
+
+    Argument : void
+    Return   : bl31_params *
+
+BL2 platform code needs to return a pointer to a `bl31_params` structure it
+will use for passing information to BL3-1. The `bl31_params` structure carries
+the following information.
+    - Header describing the version information for interpreting the bl31_param
+      structure
+    - Information about executing the BL3-3 image in the `bl33_ep_info` field
+    - Information about executing the BL3-2 image in the `bl32_ep_info` field
+    - Information about the type and extents of BL3-1 image in the
+      `bl31_image_info` field
+    - Information about the type and extents of BL3-2 image in the
+      `bl32_image_info` field
+    - Information about the type and extents of BL3-3 image in the
+      `bl33_image_info` field
+
+The memory pointed by this structure and its sub-structures should be
+accessible from BL3-1 initialisation code. BL3-1 might choose to copy the
+necessary content, or maintain the structures until BL3-3 is initialised.
+
+
+### Funtion : bl2_plat_get_bl31_ep_info() [mandatory]
+
+    Argument : void
+    Return   : entry_point_info *
+
+BL2 platform code returns a pointer which is used to populate the entry point
+information for BL3-1 entry point. The location pointed by it should be
+accessible from BL1 while processing the synchronous exception to run to BL3-1.
+
+On FVP this is allocated inside an bl2_to_bl31_params_mem structure which
+is allocated at an address pointed by PARAMS_BASE.
+
+
+### Function : bl2_plat_set_bl31_ep_info() [mandatory]
+
+    Argument : image_info *, entry_point_info *
+    Return   : void
+
+This function is called after loading BL3-1 image and it can be used to
+overwrite the entry point set by loader and also set the security state
+and SPSR which represents the entry point system state for BL3-1.
+
+On FVP, we are setting the security state and the SPSR for the BL3-1
+entrypoint.
+
+### Function : bl2_plat_set_bl32_ep_info() [mandatory]
+
+    Argument : image_info *, entry_point_info *
+    Return   : void
+
+This function is called after loading BL3-2 image and it can be used to
+overwrite the entry point set by loader and also set the security state
+and SPSR which represents the entry point system state for BL3-2.
+
+On FVP, we are setting the security state and the SPSR for the BL3-2
+entrypoint
+
+### Function : bl2_plat_set_bl33_ep_info() [mandatory]
+
+    Argument : image_info *, entry_point_info *
+    Return   : void
+
+This function is called after loading BL3-3 image and it can be used to
+overwrite the entry point set by loader and also set the security state
+and SPSR which represents the entry point system state for BL3-3.
+
+On FVP, we are setting the security state and the SPSR for the BL3-3
+entrypoint
+
+### Function : bl2_plat_get_bl32_meminfo() [mandatory]
+
+    Argument : meminfo *
+    Return   : void
+
+This function is used to get the memory limits where BL2 can load the
+BL3-2 image. The meminfo provided by this is used by load_image() to
+validate whether the BL3-2 image can be loaded with in the given
+memory from the given base.
+
+### Function : bl2_plat_get_bl33_meminfo() [mandatory]
+
+    Argument : meminfo *
+    Return   : void
+
+This function is used to get the memory limits where BL2 can load the
+BL3-3 image. The meminfo provided by this is used by load_image() to
+validate whether the BL3-3 image can be loaded with in the given
+memory from the given base.
+
+### Function : bl2_plat_flush_bl31_params() [mandatory]
+
+    Argument : void
+    Return   : void
+
+Once BL2 has populated all the structures that needs to be read by BL1
+and BL3-1 including the bl31_params structures and its sub-structures,
+the bl31_ep_info structure and any platform specific data. It flushes
+all these data to the main memory so that it is available when we jump to
+later Bootloader stages with MMU off
+
+### Function : plat_get_ns_image_entrypoint() [mandatory]
+
+    Argument : void
+    Return   : unsigned long
+
+As previously described, BL2 is responsible for arranging for control to be
+passed to a normal world BL image through BL3-1. This function returns the
+entrypoint of that image, which BL3-1 uses to jump to it.
+
+BL2 is responsible for loading the normal world BL3-3 image (e.g. UEFI).
+
+
+3.2 Boot Loader Stage 3-1 (BL3-1)
+---------------------------------
+
+During cold boot, the BL3-1 stage is executed only by the primary CPU. This is
+determined in BL1 using the `platform_is_primary_cpu()` function. BL1 passes
+control to BL3-1 at `BL31_BASE`. During warm boot, BL3-1 is executed by all
+CPUs. BL3-1 executes at EL3 and is responsible for:
+
+1.  Re-initializing all architectural and platform state. Although BL1 performs
+    some of this initialization, BL3-1 remains resident in EL3 and must ensure
+    that EL3 architectural and platform state is completely initialized. It
+    should make no assumptions about the system state when it receives control.
+
+2.  Passing control to a normal world BL image, pre-loaded at a platform-
+    specific address by BL2. BL3-1 uses the `entry_point_info` structure that BL2
+    populated in memory to do this.
+
+3.  Providing runtime firmware services. Currently, BL3-1 only implements a
+    subset of the Power State Coordination Interface (PSCI) API as a runtime
+    service. See Section 3.3 below for details of porting the PSCI
+    implementation.
+
+4.  Optionally passing control to the BL3-2 image, pre-loaded at a platform-
+    specific address by BL2. BL3-1 exports a set of apis that allow runtime
+    services to specify the security state in which the next image should be
+    executed and run the corresponding image. BL3-1 uses the `entry_point_info`
+    structure populated by BL2 to do this.
+
+If BL3-1 is a reset vector, It also needs to handle the reset as specified in
+section 2.2 before the tasks described above.
+
+The following functions must be implemented by the platform port to enable BL3-1
+to perform the above tasks.
+
+
+### Function : bl31_early_platform_setup() [mandatory]
+
+    Argument : bl31_params *, void *
+    Return   : void
+
+This function executes with the MMU and data caches disabled. It is only called
+by the primary CPU. The arguments to this function are:
+
+*   The address of the `bl31_params` structure populated by BL2.
+*   An opaque pointer that the platform may use as needed.
+
+The platform can copy the contents of the `bl31_params` structure and its
+sub-structures into private variables if the original memory may be
+subsequently overwritten by BL3-1 and similarly the `void *` pointing
+to the platform data also needs to be saved.
+
+On the ARM FVP port, BL2 passes a pointer to a `bl31_params` structure populated
+in the secure DRAM at address `0x6000000` in the bl31_params * argument and it
+does not use opaque pointer mentioned earlier. BL3-1 does not copy this
+information to internal data structures as it guarantees that the secure
+DRAM memory will not be overwritten. It maintains an internal reference to this
+information in the `bl2_to_bl31_params` variable.
+
+### Function : bl31_plat_arch_setup() [mandatory]
+
+    Argument : void
+    Return   : void
+
+This function executes with the MMU and data caches disabled. It is only called
+by the primary CPU.
+
+The purpose of this function is to perform any architectural initialization
+that varies across platforms, for example enabling the MMU (since the memory
+map differs across platforms).
+
+
+### Function : bl31_platform_setup() [mandatory]
+
+    Argument : void
+    Return   : void
+
+This function may execute with the MMU and data caches enabled if the platform
+port does the necessary initialization in `bl31_plat_arch_setup()`. It is only
+called by the primary CPU.
+
+The purpose of this function is to complete platform initialization so that both
+BL3-1 runtime services and normal world software can function correctly.
+
+The ARM FVP port does the following:
+*   Initializes the generic interrupt controller.
+*   Configures the CLCD controller.
+*   Enables system-level implementation of the generic timer counter.
+*   Grants access to the system counter timer module
+*   Initializes the FVP power controller device
+*   Detects the system topology.
+
+
+### Function : bl31_get_next_image_info() [mandatory]
+
+    Argument : unsigned int
+    Return   : entry_point_info *
+
+This function may execute with the MMU and data caches enabled if the platform
+port does the necessary initializations in `bl31_plat_arch_setup()`.
+
+This function is called by `bl31_main()` to retrieve information provided by
+BL2 for the next image in the security state specified by the argument. BL3-1
+uses this information to pass control to that image in the specified security
+state. This function must return a pointer to the `entry_point_info` structure
+(that was copied during `bl31_early_platform_setup()`) if the image exists. It
+should return NULL otherwise.
+
+
+3.3 Power State Coordination Interface (in BL3-1)
+------------------------------------------------
+
+The ARM Trusted Firmware's implementation of the PSCI API is based around the
+concept of an _affinity instance_. Each _affinity instance_ can be uniquely
+identified in a system by a CPU ID (the processor `MPIDR` is used in the PSCI
+interface) and an _affinity level_. A processing element (for example, a
+CPU) is at level 0. If the CPUs in the system are described in a tree where the
+node above a CPU is a logical grouping of CPUs that share some state, then
+affinity level 1 is that group of CPUs (for example, a cluster), and affinity
+level 2 is a group of clusters (for example, the system). The implementation
+assumes that the affinity level 1 ID can be computed from the affinity level 0
+ID (for example, a unique cluster ID can be computed from the CPU ID). The
+current implementation computes this on the basis of the recommended use of
+`MPIDR` affinity fields in the ARM Architecture Reference Manual.
+
+BL3-1's platform initialization code exports a pointer to the platform-specific
+power management operations required for the PSCI implementation to function
+correctly. This information is populated in the `plat_pm_ops` structure. The
+PSCI implementation calls members of the `plat_pm_ops` structure for performing
+power management operations for each affinity instance. For example, the target
+CPU is specified by its `MPIDR` in a PSCI `CPU_ON` call. The `affinst_on()`
+handler (if present) is called for each affinity instance as the PSCI
+implementation powers up each affinity level implemented in the `MPIDR` (for
+example, CPU, cluster and system).
+
+The following functions must be implemented to initialize PSCI functionality in
+the ARM Trusted Firmware.
+
+
+### Function : plat_get_aff_count() [mandatory]
+
+    Argument : unsigned int, unsigned long
+    Return   : unsigned int
+
+This function may execute with the MMU and data caches enabled if the platform
+port does the necessary initializations in `bl31_plat_arch_setup()`. It is only
+called by the primary CPU.
+
+This function is called by the PSCI initialization code to detect the system
+topology. Its purpose is to return the number of affinity instances implemented
+at a given `affinity level` (specified by the first argument) and a given
+`MPIDR` (specified by the second argument). For example, on a dual-cluster
+system where first cluster implements 2 CPUs and the second cluster implements 4
+CPUs, a call to this function with an `MPIDR` corresponding to the first cluster
+(`0x0`) and affinity level 0, would return 2. A call to this function with an
+`MPIDR` corresponding to the second cluster (`0x100`) and affinity level 0,
+would return 4.
+
+
+### Function : plat_get_aff_state() [mandatory]
+
+    Argument : unsigned int, unsigned long
+    Return   : unsigned int
+
+This function may execute with the MMU and data caches enabled if the platform
+port does the necessary initializations in `bl31_plat_arch_setup()`. It is only
+called by the primary CPU.
+
+This function is called by the PSCI initialization code. Its purpose is to
+return the state of an affinity instance. The affinity instance is determined by
+the affinity ID at a given `affinity level` (specified by the first argument)
+and an `MPIDR` (specified by the second argument). The state can be one of
+`PSCI_AFF_PRESENT` or `PSCI_AFF_ABSENT`. The latter state is used to cater for
+system topologies where certain affinity instances are unimplemented. For
+example, consider a platform that implements a single cluster with 4 CPUs and
+another CPU implemented directly on the interconnect with the cluster. The
+`MPIDR`s of the cluster would range from `0x0-0x3`. The `MPIDR` of the single
+CPU would be 0x100 to indicate that it does not belong to cluster 0. Cluster 1
+is missing but needs to be accounted for to reach this single CPU in the
+topology tree. Hence it is marked as `PSCI_AFF_ABSENT`.
+
+
+### Function : plat_get_max_afflvl() [mandatory]
+
+    Argument : void
+    Return   : int
+
+This function may execute with the MMU and data caches enabled if the platform
+port does the necessary initializations in `bl31_plat_arch_setup()`. It is only
+called by the primary CPU.
+
+This function is called by the PSCI implementation both during cold and warm
+boot, to determine the maximum affinity level that the power management
+operations should apply to. ARMv8-A has support for 4 affinity levels. It is
+likely that hardware will implement fewer affinity levels. This function allows
+the PSCI implementation to consider only those affinity levels in the system
+that the platform implements. For example, the Base AEM FVP implements two
+clusters with a configurable number of CPUs. It reports the maximum affinity
+level as 1, resulting in PSCI power control up to the cluster level.
+
+
+### Function : platform_setup_pm() [mandatory]
+
+    Argument : const plat_pm_ops **
+    Return   : int
+
+This function may execute with the MMU and data caches enabled if the platform
+port does the necessary initializations in `bl31_plat_arch_setup()`. It is only
+called by the primary CPU.
+
+This function is called by PSCI initialization code. Its purpose is to export
+handler routines for platform-specific power management actions by populating
+the passed pointer with a pointer to BL3-1's private `plat_pm_ops` structure.
+
+A description of each member of this structure is given below. Please refer to
+the ARM FVP specific implementation of these handlers in [plat/fvp/fvp_pm.c]
+as an example. A platform port is expected to implement these handlers if the
+corresponding PSCI operation is to be supported and these handlers are expected
+to succeed if the return type is `void`.
+
+#### plat_pm_ops.affinst_standby()
+
+Perform the platform-specific setup to enter the standby state indicated by the
+passed argument. The generic code expects the handler to succeed.
+
+#### plat_pm_ops.affinst_on()
+
+Perform the platform specific setup to power on an affinity instance, specified
+by the `MPIDR` (first argument) and `affinity level` (third argument). The
+`state` (fourth argument) contains the current state of that affinity instance
+(ON or OFF). This is useful to determine whether any action must be taken. For
+example, while powering on a CPU, the cluster that contains this CPU might
+already be in the ON state. The platform decides what actions must be taken to
+transition from the current state to the target state (indicated by the power
+management operation). The generic code expects the platform to return
+E_SUCCESS on success or E_INTERN_FAIL for any failure.
+
+#### plat_pm_ops.affinst_off()
+
+Perform the platform specific setup to power off an affinity instance of the
+calling CPU. It is called by the PSCI `CPU_OFF` API implementation.
+
+The `affinity level` (first argument) and `state` (second argument) have
+a similar meaning as described in the `affinst_on()` operation. They are
+used to identify the affinity instance on which the call is made and its
+current state. This gives the platform port an indication of the
+state transition it must make to perform the requested action. For example, if
+the calling CPU is the last powered on CPU in the cluster, after powering down
+affinity level 0 (CPU), the platform port should power down affinity level 1
+(the cluster) as well. The generic code expects the handler to succeed.
+
+#### plat_pm_ops.affinst_suspend()
+
+Perform the platform specific setup to power off an affinity instance of the
+calling CPU. It is called by the PSCI `CPU_SUSPEND` API and `SYSTEM_SUSPEND`
+API implementation
+
+The `affinity level` (second argument) and `state` (third argument) have a
+similar meaning as described in the `affinst_on()` operation. They are used to
+identify the affinity instance on which the call is made and its current state.
+This gives the platform port an indication of the state transition it must
+make to perform the requested action. For example, if the calling CPU is the
+last powered on CPU in the cluster, after powering down affinity level 0 (CPU),
+the platform port should power down affinity level 1 (the cluster) as well.
+
+The difference between turning an affinity instance off versus suspending it
+is that in the former case, the affinity instance is expected to re-initialize
+its state when its next powered on (see `affinst_on_finish()`). In the latter
+case, the affinity instance is expected to save enough state so that it can
+resume execution by restoring this state when its powered on (see
+`affinst_suspend_finish()`).The generic code expects the handler to succeed.
+
+#### plat_pm_ops.affinst_on_finish()
+
+This function is called by the PSCI implementation after the calling CPU is
+powered on and released from reset in response to an earlier PSCI `CPU_ON` call.
+It performs the platform-specific setup required to initialize enough state for
+this CPU to enter the normal world and also provide secure runtime firmware
+services.
+
+The `affinity level` (first argument) and `state` (second argument) have a
+similar meaning as described in the previous operations. The generic code
+expects the handler to succeed.
+
+#### plat_pm_ops.affinst_suspend_finish()
+
+This function is called by the PSCI implementation after the calling CPU is
+powered on and released from reset in response to an asynchronous wakeup
+event, for example a timer interrupt that was programmed by the CPU during the
+`CPU_SUSPEND` call or `SYSTEM_SUSPEND` call. It performs the platform-specific
+setup required to restore the saved state for this CPU to resume execution
+in the normal world and also provide secure runtime firmware services.
+
+The `affinity level` (first argument) and `state` (second argument) have a
+similar meaning as described in the previous operations. The generic code
+expects the platform to succeed.
+
+#### plat_pm_ops.validate_power_state()
+
+This function is called by the PSCI implementation during the `CPU_SUSPEND`
+call to validate the `power_state` parameter of the PSCI API. If the
+`power_state` is known to be invalid, the platform must return
+PSCI_E_INVALID_PARAMS as error, which is propagated back to the normal
+world PSCI client.
+
+#### plat_pm_ops.validate_ns_entrypoint()
+
+This function is called by the PSCI implementation during the `CPU_SUSPEND`,
+`SYSTEM_SUSPEND` and `CPU_ON` calls to validate the non-secure `entry_point`
+parameter passed by the normal world. If the `entry_point` is known to be
+invalid, the platform must return PSCI_E_INVALID_PARAMS as error, which is
+propagated back to the normal world PSCI client.
+
+#### plat_pm_ops.get_sys_suspend_power_state()
+
+This function is called by the PSCI implementation during the `SYSTEM_SUSPEND`
+call to return the `power_state` parameter. This allows the platform to encode
+the appropriate State-ID field within the `power_state` parameter which can be
+utilized in `affinst_suspend()` to suspend to system affinity level. The
+`power_state` parameter should be in the same format as specified by the
+PSCI specification for the CPU_SUSPEND API.
+
+BL3-1 platform initialization code must also detect the system topology and
+the state of each affinity instance in the topology. This information is
+critical for the PSCI runtime service to function correctly. More details are
+provided in the description of the `plat_get_aff_count()` and
+`plat_get_aff_state()` functions above.
+
+3.4  Interrupt Management framework (in BL3-1)
+----------------------------------------------
+BL3-1 implements an Interrupt Management Framework (IMF) to manage interrupts
+generated in either security state and targeted to EL1 or EL2 in the non-secure
+state or EL3/S-EL1 in the secure state.  The design of this framework is
+described in the [IMF Design Guide]
+
+A platform should export the following APIs to support the IMF. The following
+text briefly describes each api and its implementation on the FVP port. The API
+implementation depends upon the type of interrupt controller present in the
+platform. The FVP implements an ARM Generic Interrupt Controller (ARM GIC) as
+per the version 2.0 of the [ARM GIC Architecture Specification]
+
+### Function : plat_interrupt_type_to_line() [mandatory]
+
+    Argument : uint32_t, uint32_t
+    Return   : uint32_t
+
+The ARM processor signals an interrupt exception either through the IRQ or FIQ
+interrupt line. The specific line that is signaled depends on how the interrupt
+controller (IC) reports different interrupt types from an execution context in
+either security state. The IMF uses this API to determine which interrupt line
+the platform IC uses to signal each type of interrupt supported by the framework
+from a given security state.
+
+The first parameter will be one of the `INTR_TYPE_*` values (see [IMF Design
+Guide]) indicating the target type of the interrupt, the second parameter is the
+security state of the originating execution context. The return result is the
+bit position in the `SCR_EL3` register of the respective interrupt trap: IRQ=1,
+FIQ=2.
+
+The FVP port configures the ARM GIC to signal S-EL1 interrupts as FIQs and
+Non-secure interrupts as IRQs from either security state.
+
+
+### Function : plat_ic_get_pending_interrupt_type() [mandatory]
+
+    Argument : void
+    Return   : uint32_t
+
+This API returns the type of the highest priority pending interrupt at the
+platform IC. The IMF uses the interrupt type to retrieve the corresponding
+handler function. `INTR_TYPE_INVAL` is returned when there is no interrupt
+pending. The valid interrupt types that can be returned are `INTR_TYPE_EL3`,
+`INTR_TYPE_S_EL1` and `INTR_TYPE_NS`.
+
+The FVP port reads the _Highest Priority Pending Interrupt Register_
+(`GICC_HPPIR`) to determine the id of the pending interrupt. The type of interrupt
+depends upon the id value as follows.
+
+1. id < 1022 is reported as a S-EL1 interrupt
+2. id = 1022 is reported as a Non-secure interrupt.
+3. id = 1023 is reported as an invalid interrupt type.
+
+
+### Function : plat_ic_get_pending_interrupt_id() [mandatory]
+
+    Argument : void
+    Return   : uint32_t
+
+This API returns the id of the highest priority pending interrupt at the
+platform IC. The IMF passes the id returned by this API to the registered
+handler for the pending interrupt if the `IMF_READ_INTERRUPT_ID` build time flag
+is set. INTR_ID_UNAVAILABLE is returned when there is no interrupt pending.
+
+The FVP port reads the _Highest Priority Pending Interrupt Register_
+(`GICC_HPPIR`) to determine the id of the pending interrupt. The id that is
+returned by API depends upon the value of the id read from the interrupt
+controller as follows.
+
+1. id < 1022. id is returned as is.
+2. id = 1022. The _Aliased Highest Priority Pending Interrupt Register_
+   (`GICC_AHPPIR`) is read to determine the id of the non-secure interrupt. This
+   id is returned by the API.
+3. id = 1023. `INTR_ID_UNAVAILABLE` is returned.
+
+
+### Function : plat_ic_acknowledge_interrupt() [mandatory]
+
+    Argument : void
+    Return   : uint32_t
+
+This API is used by the CPU to indicate to the platform IC that processing of
+the highest pending interrupt has begun. It should return the id of the
+interrupt which is being processed.
+
+The FVP port reads the _Interrupt Acknowledge Register_ (`GICC_IAR`). This
+changes the state of the highest priority pending interrupt from pending to
+active in the interrupt controller. It returns the value read from the
+`GICC_IAR`. This value is the id of the interrupt whose state has been changed.
+
+The TSP uses this API to start processing of the secure physical timer
+interrupt.
+
+
+### Function : plat_ic_end_of_interrupt() [mandatory]
+
+    Argument : uint32_t
+    Return   : void
+
+This API is used by the CPU to indicate to the platform IC that processing of
+the interrupt corresponding to the id (passed as the parameter) has
+finished. The id should be the same as the id returned by the
+`plat_ic_acknowledge_interrupt()` API.
+
+The FVP port writes the id to the _End of Interrupt Register_
+(`GICC_EOIR`). This deactivates the corresponding interrupt in the interrupt
+controller.
+
+The TSP uses this API to finish processing of the secure physical timer
+interrupt.
+
+
+### Function : plat_ic_get_interrupt_type() [mandatory]
+
+    Argument : uint32_t
+    Return   : uint32_t
+
+This API returns the type of the interrupt id passed as the parameter.
+`INTR_TYPE_INVAL` is returned if the id is invalid. If the id is valid, a valid
+interrupt type (one of `INTR_TYPE_EL3`, `INTR_TYPE_S_EL1` and `INTR_TYPE_NS`) is
+returned depending upon how the interrupt has been configured by the platform
+IC.
+
+The FVP port configures S-EL1 interrupts as Group0 interrupts and Non-secure
+interrupts as Group1 interrupts. It reads the group value corresponding to the
+interrupt id from the relevant _Interrupt Group Register_ (`GICD_IGROUPRn`). It
+uses the group value to determine the type of interrupt.
+
+3.5  Crash Reporting mechanism (in BL3-1)
+----------------------------------------------
+BL3-1 implements a crash reporting mechanism which prints the various registers
+of the CPU to enable quick crash analysis and debugging. It requires that a
+console is designated as the crash console by the platform which will be used to
+print the register dump.
+
+The following functions must be implemented by the platform if it wants crash
+reporting mechanism in BL3-1. The functions are implemented in assembly so that
+they can be invoked without a C Runtime stack.
+
+### Function : plat_crash_console_init
+
+    Argument : void
+    Return   : int
+
+This API is used by the crash reporting mechanism to initialize the crash
+console. It should only use the general purpose registers x0 to x2 to do the
+initialization and returns 1 on success.
+
+The FVP port designates the `PL011_UART0` as the crash console and calls the
+console_core_init() to initialize the console.
+
+### Function : plat_crash_console_putc
+
+    Argument : int
+    Return   : int
+
+This API is used by the crash reporting mechanism to print a character on the
+designated crash console. It should only use general purpose registers x1 and
+x2 to do its work. The parameter and the return value are in general purpose
+register x0.
+
+The FVP port designates the `PL011_UART0` as the crash console and calls the
+console_core_putc() to print the character on the console.
+
+4.  Build flags
+---------------
+
+There are some build flags which can be defined by the platform to control
+inclusion or exclusion of certain BL stages from the FIP image. These flags
+need to be defined in the platform makefile which will get included by the
+build system.
+
+*   **NEED_BL30**
+    This flag if defined by the platform mandates that a BL3-0 binary should
+    be included in the FIP image. The path to the BL3-0 binary can be specified
+    by the `BL30` build option (see build options in the [User Guide]).
+
+*   **NEED_BL33**
+    By default, this flag is defined `yes` by the build system and `BL33`
+    build option should be supplied as a build option. The platform has the option
+    of excluding the BL3-3 image in the `fip` image by defining this flag to
+    `no`.
+
+5.  C Library
+-------------
+
+To avoid subtle toolchain behavioral dependencies, the header files provided
+by the compiler are not used. The software is built with the `-nostdinc` flag
+to ensure no headers are included from the toolchain inadvertently. Instead the
+required headers are included in the ARM Trusted Firmware source tree. The
+library only contains those C library definitions required by the local
+implementation. If more functionality is required, the needed library functions
+will need to be added to the local implementation.
+
+Versions of [FreeBSD] headers can be found in `include/stdlib`. Some of these
+headers have been cut down in order to simplify the implementation. In order to
+minimize changes to the header files, the [FreeBSD] layout has been maintained.
+The generic C library definitions can be found in `include/stdlib` with more
+system and machine specific declarations in `include/stdlib/sys` and
+`include/stdlib/machine`.
+
+The local C library implementations can be found in `lib/stdlib`. In order to
+extend the C library these files may need to be modified. It is recommended to
+use a release version of [FreeBSD] as a starting point.
+
+The C library header files in the [FreeBSD] source tree are located in the
+`include` and `sys/sys` directories. [FreeBSD] machine specific definitions
+can be found in the `sys/<machine-type>` directories. These files define things
+like 'the size of a pointer' and 'the range of an integer'. Since an AArch64
+port for [FreeBSD] does not yet exist, the machine specific definitions are
+based on existing machine types with similar properties (for example SPARC64).
+
+Where possible, C library function implementations were taken from [FreeBSD]
+as found in the `lib/libc` directory.
+
+A copy of the [FreeBSD] sources can be downloaded with `git`.
+
+    git clone git://github.com/freebsd/freebsd.git -b origin/release/9.2.0
+
+
+6.  Storage abstraction layer
+-----------------------------
+
+In order to improve platform independence and portability an storage abstraction
+layer is used to load data from non-volatile platform storage.
+
+Each platform should register devices and their drivers via the Storage layer.
+These drivers then need to be initialized by bootloader phases as
+required in their respective `blx_platform_setup()` functions.  Currently
+storage access is only required by BL1 and BL2 phases. The `load_image()`
+function uses the storage layer to access non-volatile platform storage.
+
+It is mandatory to implement at least one storage driver. For the FVP the
+Firmware Image Package(FIP) driver is provided as the default means to load data
+from storage (see the "Firmware Image Package" section in the [User Guide]).
+The storage layer is described in the header file
+`include/drivers/io/io_storage.h`.  The implementation of the common library
+is in `drivers/io/io_storage.c` and the driver files are located in
+`drivers/io/`.
+
+Each IO driver must provide `io_dev_*` structures, as described in
+`drivers/io/io_driver.h`.  These are returned via a mandatory registration
+function that is called on platform initialization.  The semi-hosting driver
+implementation in `io_semihosting.c` can be used as an example.
+
+The Storage layer provides mechanisms to initialize storage devices before
+IO operations are called.  The basic operations supported by the layer
+include `open()`, `close()`, `read()`, `write()`, `size()` and `seek()`.
+Drivers do not have to implement all operations, but each platform must
+provide at least one driver for a device capable of supporting generic
+operations such as loading a bootloader image.
+
+The current implementation only allows for known images to be loaded by the
+firmware.  These images are specified by using their names, as defined in
+[include/plat/common/platform.h]. The platform layer (`plat_get_image_source()`)
+then returns a reference to a device and a driver-specific `spec` which will be
+understood by the driver to allow access to the image data.
+
+The layer is designed in such a way that is it possible to chain drivers with
+other drivers.  For example, file-system drivers may be implemented on top of
+physical block devices, both represented by IO devices with corresponding
+drivers.  In such a case, the file-system "binding" with the block device may
+be deferred until the file-system device is initialised.
+
+The abstraction currently depends on structures being statically allocated
+by the drivers and callers, as the system does not yet provide a means of
+dynamically allocating memory.  This may also have the affect of limiting the
+amount of open resources per driver.
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved._
+
+
+[ARM GIC Architecture Specification]: http://arminfo.emea.arm.com/help/topic/com.arm.doc.ihi0048b/IHI0048B_gic_architecture_specification.pdf
+[IMF Design Guide]:                   interrupt-framework-design.md
+[User Guide]:                         user-guide.md
+[FreeBSD]:                            http://www.freebsd.org
+[Firmware Design Guide]:              firmware-design.md
+
+[plat/common/aarch64/platform_mp_stack.S]: ../plat/common/aarch64/platform_mp_stack.S
+[plat/common/aarch64/platform_up_stack.S]: ../plat/common/aarch64/platform_up_stack.S
+[plat/fvp/include/platform_def.h]:         ../plat/fvp/include/platform_def.h
+[plat/fvp/include/plat_macros.S]:          ../plat/fvp/include/plat_macros.S
+[plat/fvp/aarch64/plat_common.c]:          ../plat/fvp/aarch64/plat_common.c
+[plat/fvp/plat_pm.c]:                      ../plat/fvp/plat_pm.c
+[include/runtime_svc.h]:                   ../include/runtime_svc.h
+[include/plat/common/platform.h]:          ../include/plat/common/platform.h
diff --git a/docs/rt-svc-writers-guide.md b/docs/rt-svc-writers-guide.md
new file mode 100644 (file)
index 0000000..13f5310
--- /dev/null
@@ -0,0 +1,309 @@
+EL3 Runtime Service Writers Guide for ARM Trusted Firmware
+==========================================================
+
+Contents
+--------
+
+1.  [Introduction](#1--introduction)
+2.  [Owning Entities, Call Types and Function IDs](#2--owning-entities-call-types-and-function-ids)
+3.  [Getting started](#3--getting-started)
+4.  [Registering a runtime service](#4--registering-a-runtime-service)
+5.  [Initializing a runtime service](#5-initializing-a-runtime-service)
+6.  [Handling runtime service requests](#6--handling-runtime-service-requests)
+7.  [Services that contain multiple sub-services](#7--services-that-contain-multiple-sub-services)
+8.  [Secure-EL1 Payload Dispatcher service (SPD)](#8--secure-el1-payload-dispatcher-service-spd)
+
+- - - - - - - - - - - - - - - - - -
+
+1.  Introduction
+----------------
+
+This document describes how to add a runtime service to the EL3 Runtime
+Firmware component of ARM Trusted Firmware (BL3-1).
+
+Software executing in the normal world and in the trusted world at exception
+levels lower than EL3 will request runtime services using the Secure Monitor
+Call (SMC) instruction. These requests will follow the convention described in
+the SMC Calling Convention PDD ([SMCCC]). The [SMCCC] assigns function
+identifiers to each SMC request and describes how arguments are passed and
+results are returned.
+
+SMC Functions are grouped together based on the implementor of the service, for
+example a subset of the Function IDs are designated as "OEM Calls" (see [SMCCC]
+for full details). The EL3 runtime services framework in BL3-1 enables the
+independent implementation of services for each group, which are then compiled
+into the BL3-1 image. This simplifies the integration of common software from
+ARM to support [PSCI], Secure Monitor for a Trusted OS and SoC specific
+software. The common runtime services framework ensures that SMC Functions are
+dispatched to their respective service implementation - the [Firmware Design]
+provides details of how this is achieved.
+
+The interface and operation of the runtime services depends heavily on the
+concepts and definitions described in the [SMCCC], in particular SMC Function
+IDs, Owning Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and
+SMC64 calling conventions. Please refer to that document for a full explanation
+of these terms.
+
+
+2.  Owning Entities, Call Types and Function IDs
+------------------------------------------------
+
+The SMC Function Identifier includes a OEN field. These values and their
+meaning are described in [SMCCC] and summarized in table 1 below. Some entities
+are allocated a range of of OENs. The OEN must be interpreted in conjunction
+with the SMC call type, which is either _Fast_ or _Standard_. Fast calls are
+uninterruptible whereas Standard calls can be pre-empted. The majority of
+Owning Entities only have allocated ranges for Fast calls: Standard calls are
+reserved exclusively for Trusted OS providers or for interoperability with
+legacy 32-bit software that predates the [SMCCC].
+
+    Type    OEN     Service
+    Fast     0      ARM Architecture calls
+    Fast     1      CPU Service calls
+    Fast     2      SiP Service calls
+    Fast     3      OEM Service calls
+    Fast     4      Standard Service calls
+    Fast    5-47    Reserved for future use
+    Fast   48-49    Trusted Application calls
+    Fast   50-63    Trusted OS calls
+
+    Std     0- 1    Reserved for existing ARMv7 calls
+    Std     2-63    Trusted OS Standard Calls
+
+_Table 1: Service types and their corresponding Owning Entity Numbers_
+
+Each individual entity can allocate the valid identifiers within the entity
+range as they need - it is not necessary to coordinate with other entities of
+the same type. For example, two SoC providers can use the same Function ID
+within the SiP Service calls OEN range to mean different things - as these
+calls should be specific to the SoC. The Standard Runtime Calls OEN is used for
+services defined by ARM standards, such as [PSCI].
+
+The SMC Function ID also indicates whether the call has followed the SMC32
+calling convention, where all parameters are 32-bit, or the SMC64 calling
+convention, where the parameters are 64-bit. The framework identifies and
+rejects invalid calls that use the SMC64 calling convention but that originate
+from an AArch32 caller.
+
+The EL3 runtime services framework uses the call type and OEN to identify a
+specific handler for each SMC call, but it is expected that an individual
+handler will be responsible for all SMC Functions within a given service type.
+
+
+3.  Getting started
+-------------------
+
+ARM Trusted Firmware has a [`services`] directory in the source tree under which
+each owning entity can place the implementation of its runtime service.  The
+[PSCI] implementation is located here in the [`services/std_svc/psci`]
+directory.
+
+Runtime service sources will need to include the [`runtime_svc.h`] header file.
+
+
+4.  Registering a runtime service
+---------------------------------
+
+A runtime service is registered using the `DECLARE_RT_SVC()` macro, specifying
+the name of the service, the range of OENs covered, the type of service and
+initialization and call handler functions.
+
+    #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch)
+
+*   `_name` is used to identify the data structure declared by this macro, and
+    is also used for diagnostic purposes
+
+*   `_start` and `_end` values must be based on the `OEN_*` values defined in
+    [`runtime_svc.h`]
+
+*   `_type` must be one of `SMC_TYPE_FAST` or `SMC_TYPE_STD`
+
+*   `_setup` is the initialization function with the `rt_svc_init` signature:
+
+        typedef int32_t (*rt_svc_init)(void);
+
+*   `_smch` is the SMC handler function with the `rt_svc_handle` signature:
+
+        typedef uint64_t (*rt_svc_handle)(uint32_t smc_fid,
+                                          uint64_t x1, uint64_t x2,
+                                          uint64_t x3, uint64_t x4,
+                                          void *reserved,
+                                          void *handle,
+                                          uint64_t flags);
+
+Details of the requirements and behavior of the two callbacks is provided in
+the following sections.
+
+During initialization the services framework validates each declared service
+to ensure that the following conditions are met:
+
+1.  The `_start` OEN is not greater than the `_end` OEN
+2.  The `_end` OEN does not exceed the maximum OEN value (63)
+3.  The `_type` is one of `SMC_TYPE_FAST` or `SMC_TYPE_STD`
+4.  `_setup` and `_smch` routines have been specified
+
+[`std_svc_setup.c`] provides an example of registering a runtime service:
+
+    /* Register Standard Service Calls as runtime service */
+    DECLARE_RT_SVC(
+            std_svc,
+            OEN_STD_START,
+            OEN_STD_END,
+            SMC_TYPE_FAST,
+            std_svc_setup,
+            std_svc_smc_handler
+    );
+
+
+5. Initializing a runtime service
+---------------------------------
+
+Runtime services are initialized once, during cold boot, by the primary CPU
+after platform and architectural initialization is complete. The framework
+performs basic validation of the declared service before calling
+the service initialization function (`_setup` in the declaration). This
+function must carry out any essential EL3 initialization prior to receiving a
+SMC Function call via the handler function.
+
+On success, the initialization function must return `0`. Any other return value
+will cause the framework to issue a diagnostic:
+
+    Error initializing runtime service <name of the service>
+
+and then ignore the service - the system will continue to boot but SMC calls
+will not be passed to the service handler and instead return the _Unknown SMC
+Function ID_ result `0xFFFFFFFF`.
+
+If the system must not be allowed to proceed without the service, the
+initialization function must itself cause the firmware boot to be halted.
+
+If the service uses per-CPU data this must either be initialized for all CPUs
+during this call, or be done lazily when a CPU first issues an SMC call to that
+service.
+
+
+6.  Handling runtime service requests
+-------------------------------------
+
+SMC calls for a service are forwarded by the framework to the service's SMC
+handler function (`_smch` in the service declaration). This function must have
+the following signature:
+
+    typedef uint64_t (*rt_svc_handle)(uint32_t smc_fid,
+                                      uint64_t x1, uint64_t x2,
+                                      uint64_t x3, uint64_t x4,
+                                      void *reserved,
+                                      void *handle,
+                                      uint64_t flags);
+
+The handler is responsible for:
+
+1.  Determining that `smc_fid` is a valid and supported SMC Function ID,
+    otherwise completing the request with the _Unknown SMC Function ID_:
+
+        SMC_RET1(handle, SMC_UNK);
+
+2.  Determining if the requested function is valid for the calling security
+    state. SMC Calls can be made from both the normal and trusted worlds and
+    the framework will forward all calls to the service handler.
+
+    The `flags` parameter to this function indicates the caller security state
+    in bit[0], where a value of `1` indicates  a non-secure caller. The
+    `is_caller_secure(flags)` and `is_caller_non_secure(flags)` can be used to
+    test this condition.
+
+    If invalid, the request should be completed with:
+
+        SMC_RET1(handle, SMC_UNK);
+
+3.  Truncating parameters for calls made using the SMC32 calling convention.
+    Such calls can be determined by checking the CC field in bit[30] of the
+    `smc_fid` parameter, for example by using:
+
+        if (GET_SMC_CC(smc_fid) == SMC_32) ...
+
+    For such calls, the upper bits of the parameters x1-x4 and the saved
+    parameters X5-X7 are UNDEFINED and must be explicitly ignored by the
+    handler. This can be done by truncating the values to a suitable 32-bit
+    integer type before use, for example by ensuring that functions defined
+    to handle individual SMC Functions use appropriate 32-bit parameters.
+
+4.  Providing the service requested by the SMC Function, utilizing the
+    immediate parameters x1-x4 and/or the additional saved parameters X5-X7.
+    The latter can be retrieved using the `SMC_GET_GP(handle, ref)` function,
+    supplying the appropriate `CTX_GPREG_Xn` reference, e.g.
+
+        uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+
+5.  Implementing the standard SMC32 Functions that provide information about
+    the implementation of the service. These are the Call Count, Implementor
+    UID and Revision Details for each service documented in section 6 of the
+    [SMCCC].
+
+    The ARM Trusted Firmware expects owning entities to follow this
+    recommendation.
+
+5.  Returning the result to the caller. The [SMCCC] allows for up to 256 bits
+    of return value in SMC64 using X0-X3 and 128 bits in SMC32 using W0-W3. The
+    framework provides a family of macros to set the multi-register return
+    value and complete the handler:
+
+        SMC_RET1(handle, x0);
+        SMC_RET2(handle, x0, x1);
+        SMC_RET3(handle, x0, x1, x2);
+        SMC_RET4(handle, x0, x1, x2, x3);
+
+The `reserved` parameter to the handler is reserved for future use and can be
+ignored. The value returned by a SMC handler is also reserved for future use -
+completion of the handler function must always be via one of the `SMC_RETn()`
+macros.
+
+NOTE: The PSCI and Test Secure-EL1 Payload Dispatcher services do not follow
+all of the above requirements yet.
+
+
+7.  Services that contain multiple sub-services
+-----------------------------------------------
+
+It is possible that a single owning entity implements multiple sub-services. For
+example, the Standard calls service handles `0x84000000`-`0x8400FFFF` and
+`0xC4000000`-`0xC400FFFF` functions. Within that range, the [PSCI] service
+handles the `0x84000000`-`0x8400001F` and `0xC4000000`-`0xC400001F` functions.
+In that respect, [PSCI] is a 'sub-service' of the Standard calls service. In
+future, there could be additional such sub-services in the Standard calls
+service which perform independent functions.
+
+In this situation it may be valuable to introduce a second level framework to
+enable independent implementation of sub-services. Such a framework might look
+very similar to the current runtime services framework, but using a different
+part of the SMC Function ID to identify the sub-service. Trusted Firmware does
+not provide such a framework at present.
+
+
+8.  Secure-EL1 Payload Dispatcher service (SPD)
+-----------------------------------------------
+
+Services that handle SMC Functions targeting a Trusted OS, Trusted Application,
+or other Secure-EL1 Payload are special. These services need to manage the
+Secure-EL1 context, provide the _Secure Monitor_ functionality of switching
+between the normal and secure worlds, deliver SMC Calls through to Secure-EL1
+and generally manage the Secure-EL1 Payload through CPU power-state transitions.
+
+TODO: Provide details of the additional work required to implement a SPD and
+the BL3-1 support for these services. Or a reference to the document that will
+provide this information....
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._
+
+
+[Firmware Design]:  ./firmware-design.md
+
+[`services`]:               ../services
+[`services/std_svc/psci`]:  ../services/std_svc/psci
+[`std_svc_setup.c`]:        ../services/std_svc/std_svc_setup.c
+[`runtime_svc.h`]:          ../include/runtime_svc.h
+[PSCI]:                     http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf "Power State Coordination Interface PDD (ARM DEN 0022C)"
+[SMCCC]:                    http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html "SMC Calling Convention PDD (ARM DEN 0028A)"
diff --git a/docs/trusted-board-boot.md b/docs/trusted-board-boot.md
new file mode 100644 (file)
index 0000000..abba030
--- /dev/null
@@ -0,0 +1,261 @@
+Trusted Board Boot Design Guide
+===============================
+
+Contents :
+
+1.  [Introduction](#1--introduction)
+2.  [Chain of Trust](#2--chain-of-trust)
+3.  [Trusted Board Boot Sequence](#3--trusted-board-boot-sequence)
+4.  [Authentication Module](#4--authentication-module)
+5.  [Certificate Generation Tool](#5--certificate-generation-tool)
+
+
+1.  Introduction
+----------------
+
+The Trusted Board Boot (TBB) feature prevents malicious firmware from running on
+the platform by authenticating all firmware images up to and including the
+normal world bootloader. It does this by establishing a Chain of Trust using
+Public-Key-Cryptography Standards (PKCS).
+
+This document describes the design of the ARM Trusted Firmware TBB
+implementation. The current implementation is a proof of concept; future
+versions will provide stronger architectural interfaces and implement the
+missing functionality required in a production TBB-enabled system.
+
+
+2.  Chain of Trust
+------------------
+
+A Chain of Trust (CoT) starts with a set of implicitly trusted components. On
+the ARM development platforms, these components are:
+
+*   A SHA-256 hash of the Root of Trust Public Key (ROTPK). It is stored in the
+    trusted root-key storage registers.
+
+*   The BL1 image, on the assumption that it resides in ROM so cannot be
+    tampered with.
+
+The remaining components in the CoT are either certificates or boot loader
+images. The certificates follow the [X.509 v3] standard. This standard
+enables adding custom extensions to the certificates, which are used to store
+essential information to establish the CoT.
+
+In the TBB CoT all certificates are self-signed. There is no need for a
+Certificate Authority (CA) because the CoT is not established by verifying the
+validity of a certificate's issuer but by the content of the certificate
+extensions. To sign the certificates, the PKCS#1 SHA-1 with RSA Encryption
+signature scheme is used with a RSA key length of 2048 bits. Future version of
+Trusted Firmware will replace SHA-1 usage with SHA-256 and support additional
+cryptographic algorithms.
+
+The certificates are categorised as "Key" and "Content" certificates. Key
+certificates are used to verify public keys which have been used to sign content
+certificates. Content certificates are used to store the hash of a boot loader
+image. An image can be authenticated by calculating its hash and matching it
+with the hash extracted from the content certificate. The SHA-256 function is
+used to calculate all hashes. The public keys and hashes are included as
+non-standard extension fields in the [X.509 v3] certificates.
+
+The keys used to establish the CoT are:
+
+*   **Root of trust key**
+
+    The private part of this key is used to sign the BL2 content certificate and
+    the trusted key certificate. The public part is the ROTPK.
+
+*   **Trusted world key**
+
+    The private part is used to sign the key certificates corresponding to the
+    secure world images (BL3-0, BL3-1 and BL3-2). The public part is stored in
+    one of the extension fields in the trusted world certificate.
+
+*   **Non-trusted world key**
+
+    The private part is used to sign the key certificate corresponding to the
+    non secure world image (BL3-3). The public part is stored in one of the
+    extension fields in the trusted world certificate.
+
+*   **BL3-X keys**
+
+    For each of BL3-0, BL3-1, BL3-2 and BL3-3, the private part is used to sign
+    the content certificate for the BL3-X image. The public part is stored in
+    one of the extension fields in the corresponding key certificate.
+
+The following images are included in the CoT:
+
+*   BL1
+*   BL2
+*   BL3-0 (optional)
+*   BL3-1
+*   BL3-3
+*   BL3-2 (optional)
+
+The following certificates are used to authenticate the images.
+
+*   **BL2 content certificate**
+
+    It is self-signed with the private part of the ROT key. It contains a hash
+    of the BL2 image.
+
+*   **Trusted key certificate**
+
+    It is self-signed with the private part of the ROT key. It contains the
+    public part of the trusted world key and the public part of the non-trusted
+    world key.
+
+*   **BL3-0 key certificate**
+
+    It is self-signed with the trusted world key. It contains the public part of
+    the BL3-0 key.
+
+*   **BL3-0 content certificate**
+
+    It is self-signed with the BL3-0 key. It contains a hash of the BL3-0 image.
+
+*   **BL3-1 key certificate**
+
+    It is self-signed with the trusted world key. It contains the public part of
+    the BL3-1 key.
+
+*   **BL3-1 content certificate**
+
+    It is self-signed with the BL3-1 key. It contains a hash of the BL3-1 image.
+
+*   **BL3-2 key certificate**
+
+    It is self-signed with the trusted world key. It contains the public part of
+    the BL3-2 key.
+
+*   **BL3-2 content certificate**
+
+    It is self-signed with the BL3-2 key. It contains a hash of the BL3-2 image.
+
+*   **BL3-3 key certificate**
+
+    It is self-signed with the non-trusted world key. It contains the public
+    part of the BL3-3 key.
+
+*   **BL3-3 content certificate**
+
+    It is self-signed with the BL3-3 key. It contains a hash of the BL3-3 image.
+
+The BL3-0 and BL3-2 certificates are optional, but they must be present if the
+corresponding BL3-0 or BL3-2 images are present.
+
+
+3.  Trusted Board Boot Sequence
+-------------------------------
+
+The CoT is verified through the following sequence of steps. The system panics
+if any of the steps fail.
+
+*   BL1 loads and verifies the BL2 content certificate. The issuer public key is
+    read from the verified certificate. A hash of that key is calculated and
+    compared with the hash of the ROTPK read from the trusted root-key storage
+    registers. If they match, the BL2 hash is read from the certificate.
+
+    Note: the matching operation is platform specific and is currently
+    unimplemented on the ARM development platforms.
+
+*   BL1 loads the BL2 image. Its hash is calculated and compared with the hash
+    read from the certificate. Control is transferred to the BL2 image if all
+    the comparisons succeed.
+
+*   BL2 loads and verifies the trusted key certificate. The issuer public key is
+    read from the verified certificate. A hash of that key is calculated and
+    compared with the hash of the ROTPK read from the trusted root-key storage
+    registers. If the comparison succeeds, BL2 reads and saves the trusted and
+    non-trusted world public keys from the verified certificate.
+
+The next two steps are executed for each of the BL3-0, BL3-1 & BL3-2 images. The
+steps for the optional BL3-0 and BL3-2 images are skipped if these images are
+not present.
+
+*   BL2 loads and verifies the BL3-x key certificate. The certificate signature
+    is verified using the trusted world public key. If the signature
+    verification succeeds, BL2 reads and saves the BL3-x public key from the
+    certificate.
+
+*   BL2 loads and verifies the BL3-x content certificate. The signature is
+    verified using the BL3-x public key. If the signature verification succeeds,
+    BL2 reads and saves the BL3-x image hash from the certificate.
+
+The next two steps are executed only for the BL3-3 image.
+
+*   BL2 loads and verifies the BL3-3 key certificate. If the signature
+    verification succeeds, BL2 reads and saves the BL3-3 public key from the
+    certificate.
+
+*   BL2 loads and verifies the BL3-3 content certificate. If the signature
+    verification succeeds, BL2 reads and saves the BL3-3 image hash from the
+    certificate.
+
+The next step is executed for all the boot loader images.
+
+*   BL2 calculates the hash of each image. It compares it with the hash obtained
+    from the corresponding content certificate. The image authentication succeeds
+    if the hashes match.
+
+The Trusted Board Boot implementation spans both generic and platform-specific
+BL1 and BL2 code, and in tool code on the host build machine. The feature is
+enabled through use of specific build flags as described in the [User Guide].
+
+On the host machine, a tool generates the certificates, which are included in
+the FIP along with the boot loader images. These certificates are loaded in
+Trusted SRAM using the IO storage framework. They are then verified by an
+Authentication module included in the Trusted Firmware.
+
+The mechanism used for generating the FIP and the Authentication module are
+described in the following sections.
+
+
+4.  Authentication Module
+-------------------------
+
+The authentication module implements the required support to authenticate the
+corresponding certificates or images at each step in the Trusted Board Boot
+sequence. The module relies on the PolarSSL library (v1.3.9) to perform the
+following operations:
+
+*   Parsing X.509 certificates and verifying them using SHA-1 with RSA
+    Encryption.
+*   Extracting public keys and hashes from the certificates.
+*   Generating hashes (SHA-256) of boot loader images
+
+At each step, the module is responsible for allocating memory to store the
+public keys or hashes that will be used in later steps. The step identifier is
+used to determine what information must be saved, according to the CoT model
+detailed in the previous sections.
+
+The authentication module resides in the `common/auth/polarssl` directory.
+Instructions for including the necessary modules of the PolarSSL SSL library and
+building the authentication module can be found in the [User Guide].
+
+
+5.  Certificate Generation Tool
+-------------------------------
+
+The `cert_create` tool is built and runs on the host machine as part of the
+Trusted Firmware build process when `GENERATE_COT=1`. It takes the boot loader
+images and keys as inputs (keys must be in PEM format) and generates the
+certificates (in DER format) required to establish the CoT. New keys can be
+generated by the tool in case they are not provided. The certificates are then
+passed as inputs to the `fip_create` tool for creating the FIP.
+
+The certificates are also stored individually in the in the output build
+directory.
+
+The tool resides in the `tools/cert_create` directory. It uses OpenSSL SSL
+library version 1.0.1 or later to generate the X.509 certificates. Instructions
+for building and using the tool can be found in the [User Guide].
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2015, ARM Limited and Contributors. All rights reserved._
+
+
+[X.509 v3]:          http://www.ietf.org/rfc/rfc5280.txt
+[X.690]:             http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+[User Guide]:        user-guide.md
diff --git a/docs/user-guide.md b/docs/user-guide.md
new file mode 100644 (file)
index 0000000..1badc0c
--- /dev/null
@@ -0,0 +1,1102 @@
+ARM Trusted Firmware User Guide
+===============================
+
+Contents :
+
+1.  [Introduction](#1--introduction)
+2.  [Host machine requirements](#2--host-machine-requirements)
+3.  [Tools](#3--tools)
+4.  [Building the Trusted Firmware](#4--building-the-trusted-firmware)
+5.  [Obtaining the normal world software](#5--obtaining-the-normal-world-software)
+6.  [Preparing the images to run on FVP](#6--preparing-the-images-to-run-on-fvp)
+7.  [Running the software on FVP](#7--running-the-software-on-fvp)
+8.  [Running the software on Juno](#8--running-the-software-on-juno)
+
+
+1.  Introduction
+----------------
+This document describes how to build ARM Trusted Firmware and run it with a
+tested set of other software components using defined configurations on the Juno
+ARM development platform and ARM Fixed Virtual Platform (FVP) models. It is
+possible to use other software components, configurations and platforms but that
+is outside the scope of this document.
+
+This document should be used in conjunction with the [Firmware Design].
+
+
+2.  Host machine requirements
+-----------------------------
+
+The minimum recommended machine specification for building the software and
+running the FVP models is a dual-core processor running at 2GHz with 12GB of
+RAM.  For best performance, use a machine with a quad-core processor running at
+2.6GHz with 16GB of RAM.
+
+The software has been tested on Ubuntu 12.04.04 (64-bit).  Packages used
+for building the software were installed from that distribution unless
+otherwise specified.
+
+
+3.  Tools
+---------
+
+The following tools are required to use the ARM Trusted Firmware:
+
+*   `git` package to obtain source code.
+
+*   `build-essential`, `uuid-dev` and `iasl` packages for building UEFI and the
+    Firmware Image Package (FIP) tool.
+
+*   `bc` and `ncurses-dev` packages for building Linux.
+
+*   `device-tree-compiler` package for building the Flattened Device Tree (FDT)
+    source files (`.dts` files) provided with this software.
+
+*   Baremetal GNU GCC tools. Verified packages can be downloaded from [Linaro]
+    [Linaro Toolchain]. The rest of this document assumes that the
+    `gcc-linaro-aarch64-none-elf-4.9-2014.07_linux.tar.xz` tools are used.
+
+        wget http://releases.linaro.org/14.07/components/toolchain/binaries/gcc-linaro-aarch64-none-elf-4.9-2014.07_linux.tar.xz
+        tar -xf gcc-linaro-aarch64-none-elf-4.9-2014.07_linux.tar.xz
+
+*   (Optional) For debugging, ARM [Development Studio 5 (DS-5)][DS-5] v5.20.
+
+
+4.  Building the Trusted Firmware
+---------------------------------
+
+To build the Trusted Firmware images, follow these steps:
+
+1.  Clone the ARM Trusted Firmware repository from GitHub:
+
+        git clone https://github.com/ARM-software/arm-trusted-firmware.git
+
+2.  Change to the trusted firmware directory:
+
+        cd arm-trusted-firmware
+
+3.  Set the compiler path, specify a Non-trusted Firmware image (BL3-3) and
+    a valid platform, and then build:
+
+        CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+        BL33=<path-to>/<bl33_image>                               \
+        make PLAT=<platform> all fip
+
+    If `PLAT` is not specified, `fvp` is assumed by default. See the "Summary of
+    build options" for more information on available build options.
+
+    The BL3-3 image corresponds to the software that is executed after switching
+    to the non-secure world. UEFI can be used as the BL3-3 image. Refer to the
+    "Obtaining the normal world software" section below.
+
+    The TSP (Test Secure Payload), corresponding to the BL3-2 image, is not
+    compiled in by default. Refer to the "Building the Test Secure Payload"
+    section below.
+
+    By default this produces a release version of the build. To produce a debug
+    version instead, refer to the "Debugging options" section below.
+
+    The build process creates products in a `build` directory tree, building
+    the objects and binaries for each boot loader stage in separate
+    sub-directories.  The following boot loader binary files are created from
+    the corresponding ELF files:
+
+    *   `build/<platform>/<build-type>/bl1.bin`
+    *   `build/<platform>/<build-type>/bl2.bin`
+    *   `build/<platform>/<build-type>/bl31.bin`
+
+    where `<platform>` is the name of the chosen platform and `<build-type>` is
+    either `debug` or `release`. A Firmare Image Package (FIP) will be created
+    as part of the build. It contains all boot loader images except for
+    `bl1.bin`.
+
+    *   `build/<platform>/<build-type>/fip.bin`
+
+    For more information on FIPs, see the "Firmware Image Package" section in
+    the [Firmware Design].
+
+4.  (Optional) Some platforms may require a BL3-0 image to boot. This image can
+    be included in the FIP when building the Trusted Firmware by specifying the
+    `BL30` build option:
+
+        BL30=<path-to>/<bl30_image>
+
+5.  Output binary files `bl1.bin` and `fip.bin` are both required to boot the
+    system. How these files are used is platform specific. Refer to the
+    platform documentation on how to use the firmware images.
+
+6.  (Optional) Build products for a specific build variant can be removed using:
+
+        make DEBUG=<D> PLAT=<platform> clean
+
+    ... where `<D>` is `0` or `1`, as specified when building.
+
+    The build tree can be removed completely using:
+
+        make realclean
+
+7.  (Optional) Path to binary for certain BL stages (BL2, BL3-1 and BL3-2) can be
+    provided by specifying the BLx=<path-to>/<blx_image> where BLx is the BL stage.
+    This will bypass the build of the BL component from source, but will include
+    the specified binary in the final FIP image. Please note that BL3-2 will be
+    included in the build, only if the `SPD` build option is specified.
+
+    For example, specifying BL2=<path-to>/<bl2_image> in the build option, will
+    skip compilation of BL2 source in trusted firmware, but include the BL2
+    binary specified in the final FIP image.
+
+### Summary of build options
+
+ARM Trusted Firmware build system supports the following build options. Unless
+mentioned otherwise, these options are expected to be specified at the build
+command line and are not to be modified in any component makefiles. Note that
+the build system doesn't track dependency for build options. Therefore, if any
+of the build options are changed from a previous build, a clean build must be
+performed.
+
+#### Common build options
+
+*   `BL30`: Path to BL3-0 image in the host file system. This image is optional.
+    If a BL3-0 image is present then this option must be passed for the `fip`
+    target.
+
+*   `BL33`: Path to BL3-3 image in the host file system. This is mandatory for
+    `fip` target in case the BL2 from ARM Trusted Firmware is used.
+
+*   `BL2`: This is an optional build option which specifies the path to BL2
+    image for the `fip` target. In this case, the BL2 in the ARM Trusted
+    Firmware will not be built.
+
+*   `BL31`:  This is an optional build option which specifies the path to
+    BL3-1 image for the `fip` target. In this case, the BL3-1 in the ARM
+    Trusted Firmware will not be built.
+
+*   `BL32`:  This is an optional build option which specifies the path to
+    BL3-2 image for the `fip` target. In this case, the BL3-2 in the ARM
+    Trusted Firmware will not be built.
+
+*   `FIP_NAME`: This is an optional build option which specifies the FIP
+    filename for the `fip` target. Default is `fip.bin`.
+
+*   `CROSS_COMPILE`: Prefix to toolchain binaries. Please refer to examples in
+    this document for usage.
+
+*   `DEBUG`: Chooses between a debug and release build. It can take either 0
+    (release) or 1 (debug) as values. 0 is the default.
+
+*   `LOG_LEVEL`: Chooses the log level, which controls the amount of console log
+    output compiled into the build. This should be one of the following:
+
+        0  (LOG_LEVEL_NONE)
+        10 (LOG_LEVEL_NOTICE)
+        20 (LOG_LEVEL_ERROR)
+        30 (LOG_LEVEL_WARNING)
+        40 (LOG_LEVEL_INFO)
+        50 (LOG_LEVEL_VERBOSE)
+
+    All log output up to and including the log level is compiled into the build.
+    The default value is 40 in debug builds and 20 in release builds.
+
+*   `NS_TIMER_SWITCH`: Enable save and restore for non-secure timer register
+    contents upon world switch. It can take either 0 (don't save and restore) or
+    1 (do save and restore). 0 is the default. An SPD may set this to 1 if it
+    wants the timer registers to be saved and restored.
+
+*   `PLAT`: Choose a platform to build ARM Trusted Firmware for. The chosen
+    platform name must be the name of one of the directories under the `plat/`
+    directory other than `common`.
+
+*   `SPD`: Choose a Secure Payload Dispatcher component to be built into the
+    Trusted Firmware. The value should be the path to the directory containing
+    the SPD source, relative to `services/spd/`; the directory is expected to
+    contain a makefile called `<spd-value>.mk`.
+
+*   `V`: Verbose build. If assigned anything other than 0, the build commands
+    are printed. Default is 0.
+
+*   `ARM_GIC_ARCH`: Choice of ARM GIC architecture version used by the ARM GIC
+    driver for implementing the platform GIC API. This API is used
+    by the interrupt management framework. Default is 2 (that is, version 2.0).
+
+*   `IMF_READ_INTERRUPT_ID`: Boolean flag used by the interrupt management
+    framework to enable passing of the interrupt id to its handler. The id is
+    read using a platform GIC API. `INTR_ID_UNAVAILABLE` is passed instead if
+    this option set to 0. Default is 0.
+
+*   `RESET_TO_BL31`: Enable BL3-1 entrypoint as the CPU reset vector instead
+    of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1
+    entrypoint) or 1 (CPU reset to BL3-1 entrypoint).
+    The default value is 0.
+
+*   `CRASH_REPORTING`: A non-zero value enables a console dump of processor
+    register state when an unexpected exception occurs during execution of
+    BL3-1. This option defaults to the value of `DEBUG` - i.e. by default
+    this is only enabled for a debug build of the firmware.
+
+*   `ASM_ASSERTION`: This flag determines whether the assertion checks within
+    assembly source files are enabled or not. This option defaults to the
+    value of `DEBUG` - that is, by default this is only enabled for a debug
+    build of the firmware.
+
+*   `TSP_INIT_ASYNC`: Choose BL3-2 initialization method as asynchronous or
+    synchronous, (see "Initializing a BL3-2 Image" section in [Firmware
+    Design]). It can take the value 0 (BL3-2 is initialized using
+    synchronous method) or 1 (BL3-2 is initialized using asynchronous method).
+    Default is 0.
+
+*   `USE_COHERENT_MEM`: This flag determines whether to include the coherent
+    memory region in the BL memory map or not (see "Use of Coherent memory in
+    Trusted Firmware" section in [Firmware Design]). It can take the value 1
+    (Coherent memory region is included) or 0 (Coherent memory region is
+    excluded). Default is 1.
+
+*   `TSPD_ROUTE_IRQ_TO_EL3`: A non zero value enables the routing model
+    for non-secure interrupts in which they are routed to EL3 (TSPD). The
+    default model (when the value is 0) is to route non-secure interrupts
+    to S-EL1 (TSP).
+
+*   `TRUSTED_BOARD_BOOT`: Boolean flag to include support for the Trusted Board
+    Boot feature. When set to '1', BL1 and BL2 images include support to load
+    and verify the certificates and images in a FIP. The default value is '0'.
+    A successful build, when `TRUSTED_BOARD_BOOT=1`, depends upon the correct
+    initialization of the `AUTH_MOD` option. Generation and inclusion of
+    certificates in the FIP depends upon the value of the `GENERATE_COT` option.
+
+*   `AUTH_MOD`: This option is used when `TRUSTED_BOARD_BOOT=1`. It specifies
+    the name of the authentication module that will be used in the Trusted Board
+    Boot sequence. The module must be located in `common/auth/<module name>`
+    directory. The directory must contain a makefile `<module name>.mk` which
+    will be used to build the module. More information can be found in
+    [Trusted Board Boot]. The default module name is 'none'.
+
+*   `GENERATE_COT`: Boolean flag used to build and execute the `cert_create`
+    tool to create certificates as per the Chain of Trust described in
+    [Trusted Board Boot].  The build system then calls the `fip_create` tool to
+    include the certificates in the FIP. Default value is '0'.
+
+    Specify `TRUSTED_BOARD_BOOT=1` and `GENERATE_COT=1` to include support for
+    the Trusted Board Boot Sequence in the BL1 and BL2 images and the FIP.
+
+    Note that if `TRUSTED_BOARD_BOOT=0` and `GENERATE_COT=1`, the BL1 and BL2
+    images will not include support for Trusted Board Boot. The FIP will still
+    include the key and content certificates. This FIP can be used to verify the
+    Chain of Trust on the host machine through other mechanisms.
+
+    Note that if `TRUSTED_BOARD_BOOT=1` and `GENERATE_COT=0`, the BL1 and BL2
+    images will include support for Trusted Board Boot, but the FIP will not
+    include the key and content certificates, causing a boot failure.
+
+*   `CREATE_KEYS`: This option is used when `GENERATE_COT=1`. It tells the
+    certificate generation tool to create new keys in case no valid keys are
+    present or specified. Allowed options are '0' or '1'. Default is '1'.
+
+*   `ROT_KEY`: This option is used when `GENERATE_COT=1`. It specifies the
+    file that contains the ROT private key in PEM format.
+
+*   `TRUSTED_WORLD_KEY`: This option is used when `GENERATE_COT=1`. It
+    specifies the file that contains the Trusted World private key in PEM
+    format.
+
+*   `NON_TRUSTED_WORLD_KEY`: This option is used when `GENERATE_COT=1`. It
+    specifies the file that contains the Non-Trusted World private key in PEM
+    format.
+
+*   `BL30_KEY`: This option is used when `GENERATE_COT=1`. It specifies the
+    file that contains the BL3-0 private key in PEM format.
+
+*   `BL31_KEY`: This option is used when `GENERATE_COT=1`. It specifies the
+    file that contains the BL3-1 private key in PEM format.
+
+*   `BL32_KEY`: This option is used when `GENERATE_COT=1`. It specifies the
+    file that contains the BL3-2 private key in PEM format.
+
+*   `BL33_KEY`: This option is used when `GENERATE_COT=1`. It specifies the
+    file that contains the BL3-3 private key in PEM format.
+
+#### FVP specific build options
+
+*   `FVP_TSP_RAM_LOCATION`: location of the TSP binary. Options:
+    -   `tsram` : Trusted SRAM (default option)
+    -   `tdram` : Trusted DRAM
+    -   `dram`  : Secure region in DRAM (configured by the TrustZone controller)
+
+For a better understanding of FVP options, the FVP memory map is explained in
+the [Firmware Design].
+
+#### Juno specific build options
+
+*   `PLAT_TSP_LOCATION`: location of the TSP binary. Options:
+    -   `tsram` : Trusted SRAM (default option)
+    -   `dram`  : Secure region in DRAM (set by the TrustZone controller)
+
+### Creating a Firmware Image Package
+
+FIPs are automatically created as part of the build instructions described in
+the previous section. It is also possible to independently build the FIP
+creation tool and FIPs if required. To do this, follow these steps:
+
+Build the tool:
+
+    make -C tools/fip_create
+
+It is recommended to remove the build artifacts before rebuilding:
+
+    make -C tools/fip_create clean
+
+Create a Firmware package that contains existing BL2 and BL3-1 images:
+
+    # fip_create --help to print usage information
+    # fip_create <fip_name> <images to add> [--dump to show result]
+    ./tools/fip_create/fip_create fip.bin --dump \
+       --bl2 build/<platform>/debug/bl2.bin --bl31 build/<platform>/debug/bl31.bin
+
+     Firmware Image Package ToC:
+    ---------------------------
+    - Trusted Boot Firmware BL2: offset=0x88, size=0x81E8
+      file: 'build/<platform>/debug/bl2.bin'
+    - EL3 Runtime Firmware BL3-1: offset=0x8270, size=0xC218
+      file: 'build/<platform>/debug/bl31.bin'
+    ---------------------------
+    Creating "fip.bin"
+
+View the contents of an existing Firmware package:
+
+    ./tools/fip_create/fip_create fip.bin --dump
+
+     Firmware Image Package ToC:
+    ---------------------------
+    - Trusted Boot Firmware BL2: offset=0x88, size=0x81E8
+    - EL3 Runtime Firmware BL3-1: offset=0x8270, size=0xC218
+    ---------------------------
+
+Existing package entries can be individially updated:
+
+    # Change the BL2 from Debug to Release version
+    ./tools/fip_create/fip_create fip.bin --dump \
+      --bl2 build/<platform>/release/bl2.bin
+
+    Firmware Image Package ToC:
+    ---------------------------
+    - Trusted Boot Firmware BL2: offset=0x88, size=0x7240
+      file: 'build/<platform>/release/bl2.bin'
+    - EL3 Runtime Firmware BL3-1: offset=0x72C8, size=0xC218
+    ---------------------------
+    Updating "fip.bin"
+
+
+### Debugging options
+
+To compile a debug version and make the build more verbose use
+
+    CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+    BL33=<path-to>/<bl33_image>                               \
+    make PLAT=<platform> DEBUG=1 V=1 all fip
+
+AArch64 GCC uses DWARF version 4 debugging symbols by default. Some tools (for
+example DS-5) might not support this and may need an older version of DWARF
+symbols to be emitted by GCC. This can be achieved by using the
+`-gdwarf-<version>` flag, with the version being set to 2 or 3. Setting the
+version to 2 is recommended for DS-5 versions older than 5.16.
+
+When debugging logic problems it might also be useful to disable all compiler
+optimizations by using `-O0`.
+
+NOTE: Using `-O0` could cause output images to be larger and base addresses
+might need to be recalculated (see the "Memory layout of BL images" section in
+the [Firmware Design]).
+
+Extra debug options can be passed to the build system by setting `CFLAGS`:
+
+    CFLAGS='-O0 -gdwarf-2'                                    \
+    CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+    BL33=<path-to>/<bl33_image>                               \
+    make PLAT=<platform> DEBUG=1 V=1 all fip
+
+
+### Building the Test Secure Payload
+
+The TSP is coupled with a companion runtime service in the BL3-1 firmware,
+called the TSPD. Therefore, if you intend to use the TSP, the BL3-1 image
+must be recompiled as well. For more information on SPs and SPDs, see the
+"Secure-EL1 Payloads and Dispatchers" section in the [Firmware Design].
+
+First clean the Trusted Firmware build directory to get rid of any previous
+BL3-1 binary. Then to build the TSP image and include it into the FIP use:
+
+    CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+    BL33=<path-to>/<bl33_image>                               \
+    make PLAT=<platform> SPD=tspd all fip
+
+An additional boot loader binary file is created in the `build` directory:
+
+*   `build/<platform>/<build-type>/bl32.bin`
+
+The FIP will now contain the additional BL3-2 image. Here is an example
+output from an FVP build in release mode including BL3-2 and using
+FVP_AARCH64_EFI.fd as BL3-3 image:
+
+    Firmware Image Package ToC:
+    ---------------------------
+    - Trusted Boot Firmware BL2: offset=0xD8, size=0x6000
+      file: './build/fvp/release/bl2.bin'
+    - EL3 Runtime Firmware BL3-1: offset=0x60D8, size=0x9000
+      file: './build/fvp/release/bl31.bin'
+    - Secure Payload BL3-2 (Trusted OS): offset=0xF0D8, size=0x3000
+      file: './build/fvp/release/bl32.bin'
+    - Non-Trusted Firmware BL3-3: offset=0x120D8, size=0x280000
+      file: '../FVP_AARCH64_EFI.fd'
+    ---------------------------
+    Creating "build/fvp/release/fip.bin"
+
+
+### Building the Certificate Generation Tool
+
+The `cert_create` tool can be built separately through the following commands:
+
+    $ cd tools/cert_create
+    $ make [DEBUG=1] [V=1]
+
+`DEBUG=1` builds the tool in debug mode. `V=1` makes the build process more
+verbose. The following command should be used to obtain help about the tool:
+
+    $ ./cert_create -h
+
+The `cert_create` tool is automatically built with the `fip` target when
+`GENERATE_COT=1`.
+
+
+### Building a FIP image with support for Trusted Board Boot
+
+The Trusted Board Boot feature is described in [Trusted Board Boot]. The
+following steps should be followed to build a FIP image with support for this
+feature.
+
+1.  Fulfill the dependencies of the `polarssl` authentication module by checking
+    out the tag `polarssl-1.3.9` from the [PolarSSL Repository].
+
+    The `common/auth/polarssl/polarssl.mk` contains the list of PolarSSL source
+    files the module depends upon. `common/auth/polarssl/polarssl_config.h`
+    contains the configuration options required to build the PolarSSL sources.
+
+    Note that the PolarSSL SSL library is licensed under the GNU GPL version 2
+    or later license. Using PolarSSL source code will affect the licensing of
+    Trusted Firmware binaries that are built using this library.
+
+2.  Ensure that the following command line variables are set while invoking
+    `make` to build Trusted Firmware:
+
+    *   `POLARSSL_DIR=<path of the directory containing PolarSSL sources>`
+    *   `AUTH_MOD=polarssl`
+    *   `TRUSTED_BOARD_BOOT=1`
+    *   `GENERATE_COT=1`
+
+
+### Checking source code style
+
+When making changes to the source for submission to the project, the source
+must be in compliance with the Linux style guide, and to assist with this check
+the project Makefile contains two targets, which both utilise the
+`checkpatch.pl` script that ships with the Linux source tree.
+
+To check the entire source tree, you must first download a copy of
+`checkpatch.pl` (or the full Linux source), set the `CHECKPATCH` environment
+variable to point to the script and build the target checkcodebase:
+
+    make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkcodebase
+
+To just check the style on the files that differ between your local branch and
+the remote master, use:
+
+    make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkpatch
+
+If you wish to check your patch against something other than the remote master,
+set the `BASE_COMMIT` variable to your desired branch. By default, `BASE_COMMIT`
+is set to `origin/master`.
+
+
+5.  Obtaining the normal world software
+---------------------------------------
+
+### Obtaining EDK2
+
+Potentially any kind of non-trusted firmware may be used with the ARM Trusted
+Firmware but the software has only been tested with the EFI Development Kit 2
+(EDK2) open source implementation of the UEFI specification.
+
+To build the software to be compatible with the Foundation and Base FVPs, or the
+Juno platform, follow these steps:
+
+1.  Clone the [EDK2 source code][EDK2] from GitHub:
+
+        git clone -n https://github.com/tianocore/edk2.git
+
+    Not all required features are available in the EDK2 mainline yet. These can
+    be obtained from the ARM-software EDK2 repository instead:
+
+        cd edk2
+        git remote add -f --tags arm-software https://github.com/ARM-software/edk2.git
+        git checkout --detach v2.1-rc0
+
+2.  Copy build config templates to local workspace
+
+        # in edk2/
+        . edksetup.sh
+
+3.  Build the EDK2 host tools
+
+        make -C BaseTools clean
+        make -C BaseTools
+
+4.  Build the EDK2 software
+
+    1.  Build for FVP
+
+            GCC49_AARCH64_PREFIX=<absolute-path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+            make -f ArmPlatformPkg/Scripts/Makefile EDK2_ARCH=AARCH64 \
+            EDK2_DSC=ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-FVP-AArch64.dsc \
+            EDK2_TOOLCHAIN=GCC49 EDK2_BUILD=RELEASE \
+            EDK2_MACROS="-n 6 -D ARM_FOUNDATION_FVP=1"
+
+        The EDK2 binary for use with the ARM Trusted Firmware can then be found
+        here:
+
+             Build/ArmVExpress-FVP-AArch64/RELEASE_GCC49/FV/FVP_AARCH64_EFI.fd
+
+    2.  Build for Juno
+
+            GCC49_AARCH64_PREFIX=<absolute-path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+            make -f ArmPlatformPkg/ArmJunoPkg/Makefile EDK2_ARCH=AARCH64 \
+            EDK2_TOOLCHAIN=GCC49 EDK2_BUILD=RELEASE
+
+        The EDK2 binary for use with the ARM Trusted Firmware can then be found
+        here:
+
+            Build/ArmJuno/RELEASE_GCC49/FV/BL33_AP_UEFI.fd
+
+    The EDK2 binary should be specified as `BL33` in in the `make` command line
+    when building the Trusted Firmware. See the "Building the Trusted Firmware"
+    section above.
+
+5.  (Optional) To build EDK2 in debug mode, remove `EDK2_BUILD=RELEASE` from the
+    command line.
+
+6.  (Optional) To boot Linux using a VirtioBlock file-system, the command line
+    passed from EDK2 to the Linux kernel must be modified as described in the
+    "Obtaining a root file-system" section below.
+
+7.  (Optional) If legacy GICv2 locations are used, the EDK2 platform description
+    must be updated. This is required as EDK2 does not support probing for the
+    GIC location. To do this, first clean the EDK2 build directory.
+
+        make -f ArmPlatformPkg/Scripts/Makefile EDK2_ARCH=AARCH64          \
+        EDK2_DSC=ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-FVP-AArch64.dsc \
+        EDK2_TOOLCHAIN=ARMGCC clean
+
+    Then rebuild EDK2 as described in step 3, using the following flag:
+
+        -D ARM_FVP_LEGACY_GICV2_LOCATION=1
+
+    Finally rebuild the Trusted Firmware to generate a new FIP using the
+    instructions in the "Building the Trusted Firmware" section.
+
+
+### Obtaining a Linux kernel
+
+Preparing a Linux kernel for use on the FVPs can be done as follows
+(GICv2 support only):
+
+1.  Clone Linux:
+
+        git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+    Not all required features are available in the kernel mainline yet. These
+    can be obtained from the ARM-software Linux repository instead:
+
+        cd linux
+        git remote add -f --tags arm-software https://github.com/ARM-software/linux.git
+        git checkout --detach 1.3-Juno
+
+2.  Build with the Linaro GCC tools.
+
+        # in linux/
+        make mrproper
+        make ARCH=arm64 defconfig
+
+        CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- \
+        make -j6 ARCH=arm64
+
+The compiled Linux image will now be found at `arch/arm64/boot/Image`.
+
+
+6.  Preparing the images to run on FVP
+--------------------------------------
+
+### Obtaining the Flattened Device Trees
+
+Depending on the FVP configuration and Linux configuration used, different
+FDT files are required. FDTs for the Foundation and Base FVPs can be found in
+the Trusted Firmware source directory under `fdts/`. The Foundation FVP has a
+subset of the Base FVP components. For example, the Foundation FVP lacks CLCD
+and MMC support, and has only one CPU cluster.
+
+*   `fvp-base-gicv2-psci.dtb`
+
+    (Default) For use with both AEMv8 and Cortex-A57-A53 Base FVPs with
+    Base memory map configuration.
+
+*   `fvp-base-gicv2legacy-psci.dtb`
+
+    For use with AEMv8 Base FVP with legacy VE GIC memory map configuration.
+
+*   `fvp-base-gicv3-psci.dtb`
+
+    For use with both AEMv8 and Cortex-A57-A53 Base FVPs with Base memory map
+    configuration and Linux GICv3 support.
+
+*   `fvp-foundation-gicv2-psci.dtb`
+
+    (Default) For use with Foundation FVP with Base memory map configuration.
+
+*   `fvp-foundation-gicv2legacy-psci.dtb`
+
+    For use with Foundation FVP with legacy VE GIC memory map configuration.
+
+*   `fvp-foundation-gicv3-psci.dtb`
+
+    For use with Foundation FVP with Base memory map configuration and Linux
+    GICv3 support.
+
+
+Copy the chosen FDT blob as `fdt.dtb` to the directory from which the FVP
+is launched. Alternatively a symbolic link may be used.
+
+### Preparing the kernel image
+
+Copy the kernel image file `arch/arm64/boot/Image` to the directory from which
+the FVP is launched. Alternatively a symbolic link may be used.
+
+### Obtaining a root file-system
+
+To prepare a Linaro LAMP based Open Embedded file-system, the following
+instructions can be used as a guide. The file-system can be provided to Linux
+via VirtioBlock or as a RAM-disk. Both methods are described below.
+
+#### Prepare VirtioBlock
+
+To prepare a VirtioBlock file-system, do the following:
+
+1.  Download and unpack the disk image.
+
+    NOTE: The unpacked disk image grows to 3 GiB in size.
+
+        wget http://releases.linaro.org/14.12/openembedded/aarch64/vexpress64-openembedded_lamp-armv8-gcc-4.9_20141211-701.img.gz
+        gunzip vexpress64-openembedded_lamp-armv8-gcc-4.9_20141211-701.img.gz
+
+2.  Make sure the Linux kernel has Virtio support enabled using
+    `make ARCH=arm64 menuconfig`.
+
+        Device Drivers  ---> Virtio drivers  ---> <*> Platform bus driver for memory mapped virtio devices
+        Device Drivers  ---> [*] Block devices  --->  <*> Virtio block driver
+        File systems    ---> <*> The Extended 4 (ext4) filesystem
+
+    If some of these configurations are missing, enable them, save the kernel
+    configuration, then rebuild the kernel image using the instructions
+    provided in the section "Obtaining a Linux kernel".
+
+3.  Change the Kernel command line to include `root=/dev/vda2`. This can either
+    be done in the EDK2 boot menu or in the platform file. Editing the platform
+    file and rebuilding EDK2 will make the change persist. To do this:
+
+    1.  In EDK2, edit the following file:
+
+            ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-FVP-AArch64.dsc
+
+    2.  Add `root=/dev/vda2` to:
+
+            gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|"<Other default options>"
+
+    3.  Remove the entry:
+
+            gArmPlatformTokenSpaceGuid.PcdDefaultBootInitrdPath|""
+
+    4.  Rebuild EDK2 (see "Obtaining UEFI" section above).
+
+4.  The file-system image file should be provided to the model environment by
+    passing it the correct command line option. In the FVPs the following
+    option should be provided in addition to the ones described in the
+    "Running the software on FVP" section below.
+
+    NOTE: A symbolic link to this file cannot be used with the FVP; the path
+    to the real file must be provided.
+
+    On the Base FVPs:
+
+        -C bp.virtioblockdevice.image_path="<path-to>/<file-system-image>"
+
+    On the Foundation FVP:
+
+        --block-device="<path-to>/<file-system-image>"
+
+5.  Ensure that the FVP doesn't output any error messages. If the following
+    error message is displayed:
+
+        ERROR: BlockDevice: Failed to open "<path-to>/<file-system-image>"!
+
+    then make sure the path to the file-system image in the model parameter is
+    correct and that read permission is correctly set on the file-system image
+    file.
+
+#### Prepare RAM-disk
+
+To prepare a RAM-disk root file-system, do the following:
+
+1.  Download the file-system image:
+
+        wget http://releases.linaro.org/14.12/openembedded/aarch64/linaro-image-lamp-genericarmv8-20141212-729.rootfs.tar.gz
+
+2.  Modify the Linaro image:
+
+        # Prepare for use as RAM-disk. Normally use MMC, NFS or VirtioBlock.
+        # Be careful, otherwise you could damage your host file-system.
+        mkdir tmp; cd tmp
+        sudo sh -c "zcat ../linaro-image-lamp-genericarmv8-20141212-729.rootfs.tar.gz | cpio -id"
+        sudo ln -s sbin/init .
+        sudo sh -c "echo 'devtmpfs /dev devtmpfs mode=0755,nosuid 0 0' >> etc/fstab"
+        sudo sh -c "find . | cpio --quiet -H newc -o | gzip -3 -n > ../filesystem.cpio.gz"
+        cd ..
+
+3.  Copy the resultant `filesystem.cpio.gz` to the directory where the FVP is
+    launched from. Alternatively a symbolic link may be used.
+
+
+7.  Running the software on FVP
+-------------------------------
+
+This version of the ARM Trusted Firmware has been tested on the following ARM
+FVPs (64-bit versions only).
+
+*   `Foundation_Platform` (Version 9.1, Build 9.1.33)
+*   `FVP_Base_AEMv8A-AEMv8A` (Version 6.2, Build 0.8.6202)
+*   `FVP_Base_Cortex-A57x4-A53x4` (Version 6.2, Build 0.8.6202)
+*   `FVP_Base_Cortex-A57x1-A53x1` (Version 6.2, Build 0.8.6202)
+*   `FVP_Base_Cortex-A57x2-A53x4` (Version 6.2, Build 0.8.6202)
+
+NOTE: The build numbers quoted above are those reported by launching the FVP
+with the `--version` parameter.
+
+NOTE: The software will not work on Version 1.0 of the Foundation FVP.
+The commands below would report an `unhandled argument` error in this case.
+
+NOTE: The Foundation FVP does not provide a debugger interface.
+
+Please refer to the FVP documentation for a detailed description of the model
+parameter options. A brief description of the important ones that affect the
+ARM Trusted Firmware and normal world software behavior is provided below.
+
+The Foundation FVP is a cut down version of the AArch64 Base FVP. It can be
+downloaded for free from [ARM's website][ARM FVP website].
+
+
+### Running on the Foundation FVP with reset to BL1 entrypoint
+
+The following `Foundation_Platform` parameters should be used to boot Linux with
+4 CPUs using the ARM Trusted Firmware.
+
+NOTE: Using the `--block-device` parameter is not necessary if a Linux RAM-disk
+file-system is used (see the "Obtaining a File-system" section above).
+
+NOTE: The `--data="<path to FIP binary>"@0x8000000` parameter is used to load a
+Firmware Image Package at the start of NOR FLASH0 (see the "Building the
+Trusted Firmware" section above).
+
+    <path-to>/Foundation_Platform             \
+    --cores=4                                 \
+    --secure-memory                           \
+    --visualization                           \
+    --gicv3                                   \
+    --data="<path-to>/<bl1-binary>"@0x0       \
+    --data="<path-to>/<FIP-binary>"@0x8000000 \
+    --block-device="<path-to>/<file-system-image>"
+
+The default use-case for the Foundation FVP is to enable the GICv3 device in
+the model but use the GICv2 FDT, in order for Linux to drive the GIC in GICv2
+emulation mode.
+
+The memory mapped addresses `0x0` and `0x8000000` correspond to the start of
+trusted ROM and NOR FLASH0 respectively.
+
+### Notes regarding Base FVP configuration options
+
+Please refer to these notes in the subsequent "Running on the Base FVP"
+sections.
+
+1.  The `-C bp.flashloader0.fname` parameter is used to load a Firmware Image
+    Package at the start of NOR FLASH0 (see the "Building the Trusted Firmware"
+    section above).
+
+2.  Using `cache_state_modelled=1` makes booting very slow. The software will
+    still work (and run much faster) without this option but this will hide any
+    cache maintenance defects in the software.
+
+3.  Using the `-C bp.virtioblockdevice.image_path` parameter is not necessary
+    if a Linux RAM-disk file-system is used (see the "Obtaining a root
+    file-system" section above).
+
+4.  Setting the `-C bp.secure_memory` parameter to `1` is only supported on
+    Base FVP versions 5.4 and newer. Setting this parameter to `0` is also
+    supported. The `-C bp.tzc_400.diagnostics=1` parameter is optional. It
+    instructs the FVP to provide some helpful information if a secure memory
+    violation occurs.
+
+5.  This and the following notes only apply when the firmware is built with
+    the `RESET_TO_BL31` option.
+
+    The `--data="<path-to><bl31|bl32|bl33-binary>"@<base-address-of-binary>`
+    parameter is used to load bootloader images into Base FVP memory (see the
+    "Building the Trusted Firmware" section above). The base addresses used
+    should match the image base addresses in `platform_def.h` used while linking
+    the images. The BL3-2 image is only needed if BL3-1 has been built to expect
+    a Secure-EL1 Payload.
+
+6.  The `-C cluster<X>.cpu<Y>.RVBAR=@<base-address-of-bl31>` parameter, where
+    X and Y are the cluster and CPU numbers respectively, is used to set the
+    reset vector for each core.
+
+7.  Changing the default value of `FVP_SHARED_DATA_LOCATION` will also require
+    changing the value of
+    `--data="<path-to><bl31-binary>"@<base-address-of-bl31>` and
+    `-C cluster<X>.cpu<X>.RVBAR=@<base-address-of-bl31>`, to the new value of
+    `BL31_BASE` in `platform_def.h`.
+
+8.  Changing the default value of `FVP_TSP_RAM_LOCATION` will also require
+    changing the value of
+    `--data="<path-to><bl32-binary>"@<base-address-of-bl32>` to the new value of
+    `BL32_BASE` in `platform_def.h`.
+
+
+### Running on the AEMv8 Base FVP with reset to BL1 entrypoint
+
+Please read "Notes regarding Base FVP configuration options" section above for
+information about some of the options to run the software.
+
+The following `FVP_Base_AEMv8A-AEMv8A` parameters should be used to boot Linux
+with 8 CPUs using the ARM Trusted Firmware.
+
+    <path-to>/FVP_Base_AEMv8A-AEMv8A                       \
+    -C pctl.startup=0.0.0.0                                \
+    -C bp.secure_memory=1                                  \
+    -C bp.tzc_400.diagnostics=1                            \
+    -C cluster0.NUM_CORES=4                                \
+    -C cluster1.NUM_CORES=4                                \
+    -C cache_state_modelled=1                              \
+    -C bp.secureflashloader.fname="<path-to>/<bl1-binary>" \
+    -C bp.flashloader0.fname="<path-to>/<FIP-binary>"      \
+    -C bp.virtioblockdevice.image_path="<path-to>/<file-system-image>"
+
+### Running on the Cortex-A57-A53 Base FVP with reset to BL1 entrypoint
+
+Please read "Notes regarding Base FVP configuration options" section above for
+information about some of the options to run the software.
+
+The following `FVP_Base_Cortex-A57x4-A53x4` model parameters should be used to
+boot Linux with 8 CPUs using the ARM Trusted Firmware.
+
+    <path-to>/FVP_Base_Cortex-A57x4-A53x4                  \
+    -C pctl.startup=0.0.0.0                                \
+    -C bp.secure_memory=1                                  \
+    -C bp.tzc_400.diagnostics=1                            \
+    -C cache_state_modelled=1                              \
+    -C bp.secureflashloader.fname="<path-to>/<bl1-binary>" \
+    -C bp.flashloader0.fname="<path-to>/<FIP-binary>"      \
+    -C bp.virtioblockdevice.image_path="<path-to>/<file-system-image>"
+
+### Running on the AEMv8 Base FVP with reset to BL3-1 entrypoint
+
+Please read "Notes regarding Base FVP configuration options" section above for
+information about some of the options to run the software.
+
+The following `FVP_Base_AEMv8A-AEMv8A` parameters should be used to boot Linux
+with 8 CPUs using the ARM Trusted Firmware.
+
+    <path-to>/FVP_Base_AEMv8A-AEMv8A                             \
+    -C pctl.startup=0.0.0.0                                      \
+    -C bp.secure_memory=1                                        \
+    -C bp.tzc_400.diagnostics=1                                  \
+    -C cluster0.NUM_CORES=4                                      \
+    -C cluster1.NUM_CORES=4                                      \
+    -C cache_state_modelled=1                                    \
+    -C cluster0.cpu0.RVBAR=0x04023000                            \
+    -C cluster0.cpu1.RVBAR=0x04023000                            \
+    -C cluster0.cpu2.RVBAR=0x04023000                            \
+    -C cluster0.cpu3.RVBAR=0x04023000                            \
+    -C cluster1.cpu0.RVBAR=0x04023000                            \
+    -C cluster1.cpu1.RVBAR=0x04023000                            \
+    -C cluster1.cpu2.RVBAR=0x04023000                            \
+    -C cluster1.cpu3.RVBAR=0x04023000                            \
+    --data cluster0.cpu0="<path-to>/<bl31-binary>"@0x04023000    \
+    --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04001000    \
+    --data cluster0.cpu0="<path-to>/<bl33-binary>"@0x88000000    \
+    -C bp.virtioblockdevice.image_path="<path-to>/<file-system-image>"
+
+### Running on the Cortex-A57-A53 Base FVP with reset to BL3-1 entrypoint
+
+Please read "Notes regarding Base FVP configuration options" section above for
+information about some of the options to run the software.
+
+The following `FVP_Base_Cortex-A57x4-A53x4` model parameters should be used to
+boot Linux with 8 CPUs using the ARM Trusted Firmware.
+
+    <path-to>/FVP_Base_Cortex-A57x4-A53x4                        \
+    -C pctl.startup=0.0.0.0                                      \
+    -C bp.secure_memory=1                                        \
+    -C bp.tzc_400.diagnostics=1                                  \
+    -C cache_state_modelled=1                                    \
+    -C cluster0.cpu0.RVBARADDR=0x04023000                        \
+    -C cluster0.cpu1.RVBARADDR=0x04023000                        \
+    -C cluster0.cpu2.RVBARADDR=0x04023000                        \
+    -C cluster0.cpu3.RVBARADDR=0x04023000                        \
+    -C cluster1.cpu0.RVBARADDR=0x04023000                        \
+    -C cluster1.cpu1.RVBARADDR=0x04023000                        \
+    -C cluster1.cpu2.RVBARADDR=0x04023000                        \
+    -C cluster1.cpu3.RVBARADDR=0x04023000                        \
+    --data cluster0.cpu0="<path-to>/<bl31-binary>"@0x04023000    \
+    --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04001000    \
+    --data cluster0.cpu0="<path-to>/<bl33-binary>"@0x88000000    \
+    -C bp.virtioblockdevice.image_path="<path-to>/<file-system-image>"
+
+### Configuring the GICv2 memory map
+
+The Base FVP models support GICv2 with the default model parameters at the
+following addresses. The Foundation FVP also supports these addresses when
+configured for GICv3 in GICv2 emulation mode.
+
+    GICv2 Distributor Interface     0x2f000000
+    GICv2 CPU Interface             0x2c000000
+    GICv2 Virtual CPU Interface     0x2c010000
+    GICv2 Hypervisor Interface      0x2c02f000
+
+The AEMv8 Base FVP can be configured to support GICv2 at addresses
+corresponding to the legacy (Versatile Express) memory map as follows. These are
+the default addresses when using the Foundation FVP in GICv2 mode.
+
+    GICv2 Distributor Interface     0x2c001000
+    GICv2 CPU Interface             0x2c002000
+    GICv2 Virtual CPU Interface     0x2c004000
+    GICv2 Hypervisor Interface      0x2c006000
+
+The choice of memory map is reflected in the build variant field (bits[15:12])
+in the `SYS_ID` register (Offset `0x0`) in the Versatile Express System
+registers memory map (`0x1c010000`).
+
+*   `SYS_ID.Build[15:12]`
+
+    `0x1` corresponds to the presence of the Base GIC memory map. This is the
+    default value on the Base FVPs.
+
+*   `SYS_ID.Build[15:12]`
+
+    `0x0` corresponds to the presence of the Legacy VE GIC memory map. This is
+    the default value on the Foundation FVP.
+
+This register can be configured as described in the following sections.
+
+NOTE: If the legacy VE GIC memory map is used, then the corresponding FDT and
+BL3-3 images should be used.
+
+#### Configuring AEMv8 Foundation FVP GIC for legacy VE memory map
+
+The following parameters configure the Foundation FVP to use GICv2 with the
+legacy VE memory map:
+
+    <path-to>/Foundation_Platform             \
+    --cores=4                                 \
+    --secure-memory                           \
+    --visualization                           \
+    --no-gicv3                                \
+    --data="<path-to>/<bl1-binary>"@0x0       \
+    --data="<path-to>/<FIP-binary>"@0x8000000 \
+    --block-device="<path-to>/<file-system-image>"
+
+Explicit configuration of the `SYS_ID` register is not required.
+
+#### Configuring AEMv8 Base FVP GIC for legacy VE memory map
+
+The following parameters configure the AEMv8 Base FVP to use GICv2 with the
+legacy VE memory map. They must added to the parameters described in the
+"Running on the AEMv8 Base FVP" section above:
+
+    -C cluster0.gic.GICD-offset=0x1000                  \
+    -C cluster0.gic.GICC-offset=0x2000                  \
+    -C cluster0.gic.GICH-offset=0x4000                  \
+    -C cluster0.gic.GICH-other-CPU-offset=0x5000        \
+    -C cluster0.gic.GICV-offset=0x6000                  \
+    -C cluster0.gic.PERIPH-size=0x8000                  \
+    -C cluster1.gic.GICD-offset=0x1000                  \
+    -C cluster1.gic.GICC-offset=0x2000                  \
+    -C cluster1.gic.GICH-offset=0x4000                  \
+    -C cluster1.gic.GICH-other-CPU-offset=0x5000        \
+    -C cluster1.gic.GICV-offset=0x6000                  \
+    -C cluster1.gic.PERIPH-size=0x8000                  \
+    -C gic_distributor.GICD-alias=0x2c001000            \
+    -C gicv3.gicv2-only=1                               \
+    -C bp.variant=0x0
+
+The `bp.variant` parameter corresponds to the build variant field of the
+`SYS_ID` register.  Setting this to `0x0` allows the ARM Trusted Firmware to
+detect the legacy VE memory map while configuring the GIC.
+
+
+8.  Running the software on Juno
+--------------------------------
+
+### Preparing Trusted Firmware images
+
+To execute the versions of software components on Juno referred to in this
+document, the latest [Juno Board Recovery Image] must be installed. If you
+have an earlier version installed or are unsure which version is installed,
+follow the recovery image update instructions in the [Juno Software Guide]
+on the [ARM Connected Community] website.
+
+The Juno platform requires a BL3-0 image to boot up. This image contains the
+runtime firmware that runs on the SCP (System Control Processor). This image is
+embedded within the [Juno Board Recovery Image] but can also be
+[downloaded directly][Juno SCP Firmware].
+
+Rebuild the Trusted Firmware specifying the BL3-0 image. Refer to the section
+"Building the Trusted Firmware". Alternatively, the FIP image can be updated
+manually with the BL3-0 image:
+
+    fip_create --dump --bl30 <path-to>/<bl30-binary> <path-to>/<FIP-binary>
+
+### Obtaining the Flattened Device Tree
+
+Juno's device tree blob is built along with the kernel. It is located in:
+
+    <path-to-linux>/arch/arm64/boot/dts/juno.dtb
+
+### Other Juno software information
+
+Please refer to the [Juno Software Guide] to:
+
+*   Deploy a root filesystem
+*   Install and run the Juno binaries on the board
+*   Obtain any other Juno software information
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved._
+
+
+[Firmware Design]:  ./firmware-design.md
+
+[ARM FVP website]:             http://www.arm.com/fvp
+[ARM Connected Community]:     http://community.arm.com
+[Juno Software Guide]:         http://community.arm.com/docs/DOC-8396
+[Juno Board Recovery Image]:   http://community.arm.com/servlet/JiveServlet/download/9427-1-15432/board_recovery_image_0.10.1.zip
+[Juno SCP Firmware]:           http://community.arm.com/servlet/JiveServlet/download/9427-1-15422/bl30.bin.zip
+[Linaro Toolchain]:            http://releases.linaro.org/14.07/components/toolchain/binaries/
+[EDK2]:                        http://github.com/tianocore/edk2
+[DS-5]:                        http://www.arm.com/products/tools/software-tools/ds-5/index.php
+[Polarssl Repository]:         https://github.com/polarssl/polarssl.git
+[Trusted Board Boot]:          trusted-board-boot.md
diff --git a/drivers/arm/cci400/cci400.c b/drivers/arm/cci400/cci400.c
new file mode 100644 (file)
index 0000000..6a8737a
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <cci400.h>
+#include <mmio.h>
+
+#define MAX_CLUSTERS           2
+
+static unsigned long cci_base_addr;
+static unsigned int cci_cluster_ix_to_iface[MAX_CLUSTERS];
+
+
+void cci_init(unsigned long cci_base,
+               int slave_iface3_cluster_ix,
+               int slave_iface4_cluster_ix)
+{
+       /*
+        * Check the passed arguments are valid. The cluster indices must be
+        * less than MAX_CLUSTERS, not the same as each other and at least one
+        * of them must be refer to a valid cluster index.
+        */
+       assert(cci_base);
+       assert(slave_iface3_cluster_ix < MAX_CLUSTERS);
+       assert(slave_iface4_cluster_ix < MAX_CLUSTERS);
+       assert(slave_iface3_cluster_ix != slave_iface4_cluster_ix);
+       assert((slave_iface3_cluster_ix >= 0) ||
+               (slave_iface3_cluster_ix >= 0));
+
+       cci_base_addr = cci_base;
+       if (slave_iface3_cluster_ix >= 0)
+               cci_cluster_ix_to_iface[slave_iface3_cluster_ix] =
+                       SLAVE_IFACE3_OFFSET;
+       if (slave_iface4_cluster_ix >= 0)
+               cci_cluster_ix_to_iface[slave_iface4_cluster_ix] =
+                       SLAVE_IFACE4_OFFSET;
+}
+
+static inline unsigned long get_slave_iface_base(unsigned long mpidr)
+{
+       /*
+        * We assume the TF topology code allocates affinity instances
+        * consecutively from zero.
+        * It is a programming error if this is called without initializing
+        * the slave interface to use for this cluster.
+        */
+       unsigned int cluster_id =
+               (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+
+       assert(cluster_id < MAX_CLUSTERS);
+       assert(cci_cluster_ix_to_iface[cluster_id] != 0);
+
+       return cci_base_addr + cci_cluster_ix_to_iface[cluster_id];
+}
+
+void cci_enable_cluster_coherency(unsigned long mpidr)
+{
+       assert(cci_base_addr);
+       /* Enable Snoops and DVM messages */
+       mmio_write_32(get_slave_iface_base(mpidr) + SNOOP_CTRL_REG,
+                     DVM_EN_BIT | SNOOP_EN_BIT);
+
+       /* Wait for the dust to settle down */
+       while (mmio_read_32(cci_base_addr + STATUS_REG) & CHANGE_PENDING_BIT)
+               ;
+}
+
+void cci_disable_cluster_coherency(unsigned long mpidr)
+{
+       assert(cci_base_addr);
+       /* Disable Snoops and DVM messages */
+       mmio_write_32(get_slave_iface_base(mpidr) + SNOOP_CTRL_REG,
+                     ~(DVM_EN_BIT | SNOOP_EN_BIT));
+
+       /* Wait for the dust to settle down */
+       while (mmio_read_32(cci_base_addr + STATUS_REG) & CHANGE_PENDING_BIT)
+               ;
+}
+
diff --git a/drivers/arm/gic/arm_gic.c b/drivers/arm/gic/arm_gic.c
new file mode 100644 (file)
index 0000000..58fbc89
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <gic_v2.h>
+#include <gic_v3.h>
+#include <interrupt_mgmt.h>
+#include <platform.h>
+#include <stdint.h>
+
+/* Value used to initialize Non-Secure IRQ priorities four at a time */
+#define GICD_IPRIORITYR_DEF_VAL \
+       (GIC_HIGHEST_NS_PRIORITY | \
+       (GIC_HIGHEST_NS_PRIORITY << 8) | \
+       (GIC_HIGHEST_NS_PRIORITY << 16) | \
+       (GIC_HIGHEST_NS_PRIORITY << 24))
+
+static unsigned int g_gicc_base;
+static unsigned int g_gicd_base;
+static unsigned long g_gicr_base;
+static const unsigned int *g_irq_sec_ptr;
+static unsigned int g_num_irqs;
+
+
+/*******************************************************************************
+ * This function does some minimal GICv3 configuration. The Firmware itself does
+ * not fully support GICv3 at this time and relies on GICv2 emulation as
+ * provided by GICv3. This function allows software (like Linux) in later stages
+ * to use full GICv3 features.
+ ******************************************************************************/
+static void gicv3_cpuif_setup(void)
+{
+       unsigned int scr_val, val;
+       uintptr_t base;
+
+       /*
+        * When CPUs come out of reset they have their GICR_WAKER.ProcessorSleep
+        * bit set. In order to allow interrupts to get routed to the CPU we
+        * need to clear this bit if set and wait for GICR_WAKER.ChildrenAsleep
+        * to clear (GICv3 Architecture specification 5.4.23).
+        * GICR_WAKER is NOT banked per CPU, compute the correct base address
+        * per CPU.
+        */
+       assert(g_gicr_base);
+       base = gicv3_get_rdist(g_gicr_base, read_mpidr());
+       if (base == (uintptr_t)NULL) {
+               /* No re-distributor base address. This interface cannot be
+                * configured.
+                */
+               panic();
+       }
+
+       val = gicr_read_waker(base);
+
+       val &= ~WAKER_PS;
+       gicr_write_waker(base, val);
+       dsb();
+
+       /* We need to wait for ChildrenAsleep to clear. */
+       val = gicr_read_waker(base);
+       while (val & WAKER_CA)
+               val = gicr_read_waker(base);
+
+       /*
+        * We need to set SCR_EL3.NS in order to see GICv3 non-secure state.
+        * Restore SCR_EL3.NS again before exit.
+        */
+       scr_val = read_scr();
+       write_scr(scr_val | SCR_NS_BIT);
+       isb();  /* ensure NS=1 takes effect before accessing ICC_SRE_EL2 */
+
+       /*
+        * By default EL2 and NS-EL1 software should be able to enable GICv3
+        * System register access without any configuration at EL3. But it turns
+        * out that GICC PMR as set in GICv2 mode does not affect GICv3 mode. So
+        * we need to set it here again. In order to do that we need to enable
+        * register access. We leave it enabled as it should be fine and might
+        * prevent problems with later software trying to access GIC System
+        * Registers.
+        */
+       val = read_icc_sre_el3();
+       write_icc_sre_el3(val | ICC_SRE_EN | ICC_SRE_SRE);
+
+       val = read_icc_sre_el2();
+       write_icc_sre_el2(val | ICC_SRE_EN | ICC_SRE_SRE);
+
+       write_icc_pmr_el1(GIC_PRI_MASK);
+       isb();  /* commit ICC_* changes before setting NS=0 */
+
+       /* Restore SCR_EL3 */
+       write_scr(scr_val);
+       isb();  /* ensure NS=0 takes effect immediately */
+}
+
+/*******************************************************************************
+ * This function does some minimal GICv3 configuration when cores go
+ * down.
+ ******************************************************************************/
+static void gicv3_cpuif_deactivate(void)
+{
+       unsigned int val;
+       uintptr_t base;
+
+       /*
+        * When taking CPUs down we need to set GICR_WAKER.ProcessorSleep and
+        * wait for GICR_WAKER.ChildrenAsleep to get set.
+        * (GICv3 Architecture specification 5.4.23).
+        * GICR_WAKER is NOT banked per CPU, compute the correct base address
+        * per CPU.
+        */
+       assert(g_gicr_base);
+       base = gicv3_get_rdist(g_gicr_base, read_mpidr());
+       if (base == (uintptr_t)NULL) {
+               /* No re-distributor base address. This interface cannot be
+                * configured.
+                */
+               panic();
+       }
+
+       val = gicr_read_waker(base);
+       val |= WAKER_PS;
+       gicr_write_waker(base, val);
+       dsb();
+
+       /* We need to wait for ChildrenAsleep to set. */
+       val = gicr_read_waker(base);
+       while ((val & WAKER_CA) == 0)
+               val = gicr_read_waker(base);
+}
+
+
+/*******************************************************************************
+ * Enable secure interrupts and use FIQs to route them. Disable legacy bypass
+ * and set the priority mask register to allow all interrupts to trickle in.
+ ******************************************************************************/
+void arm_gic_cpuif_setup(void)
+{
+       unsigned int val;
+
+       assert(g_gicc_base);
+       val = gicc_read_iidr(g_gicc_base);
+
+       /*
+        * If GICv3 we need to do a bit of additional setup. We want to
+        * allow default GICv2 behaviour but allow the next stage to
+        * enable full gicv3 features.
+        */
+       if (((val >> GICC_IIDR_ARCH_SHIFT) & GICC_IIDR_ARCH_MASK) >= 3)
+               gicv3_cpuif_setup();
+
+       val = ENABLE_GRP0 | FIQ_EN | FIQ_BYP_DIS_GRP0;
+       val |= IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1;
+
+       gicc_write_pmr(g_gicc_base, GIC_PRI_MASK);
+       gicc_write_ctlr(g_gicc_base, val);
+}
+
+/*******************************************************************************
+ * Place the cpu interface in a state where it can never make a cpu exit wfi as
+ * as result of an asserted interrupt. This is critical for powering down a cpu
+ ******************************************************************************/
+void arm_gic_cpuif_deactivate(void)
+{
+       unsigned int val;
+
+       /* Disable secure, non-secure interrupts and disable their bypass */
+       assert(g_gicc_base);
+       val = gicc_read_ctlr(g_gicc_base);
+       val &= ~(ENABLE_GRP0 | ENABLE_GRP1);
+       val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0;
+       val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1;
+       gicc_write_ctlr(g_gicc_base, val);
+
+       val = gicc_read_iidr(g_gicc_base);
+
+       /*
+        * If GICv3 we need to do a bit of additional setup. Make sure the
+        * RDIST is put to sleep.
+        */
+       if (((val >> GICC_IIDR_ARCH_SHIFT) & GICC_IIDR_ARCH_MASK) >= 3)
+               gicv3_cpuif_deactivate();
+}
+
+/*******************************************************************************
+ * Per cpu gic distributor setup which will be done by all cpus after a cold
+ * boot/hotplug. This marks out the secure interrupts & enables them.
+ ******************************************************************************/
+void arm_gic_pcpu_distif_setup(void)
+{
+       unsigned int index, irq_num;
+
+       assert(g_gicd_base);
+
+       /* Mark all 32 SGI+PPI interrupts as Group 1 (non-secure) */
+       gicd_write_igroupr(g_gicd_base, 0, ~0);
+
+       /* Setup PPI priorities doing four at a time */
+       for (index = 0; index < 32; index += 4) {
+               gicd_write_ipriorityr(g_gicd_base, index,
+                               GICD_IPRIORITYR_DEF_VAL);
+       }
+
+       assert(g_irq_sec_ptr);
+       for (index = 0; index < g_num_irqs; index++) {
+               irq_num = g_irq_sec_ptr[index];
+               if (irq_num < MIN_SPI_ID) {
+                       /* We have an SGI or a PPI */
+                       gicd_clr_igroupr(g_gicd_base, irq_num);
+                       gicd_set_ipriorityr(g_gicd_base, irq_num,
+                               GIC_HIGHEST_SEC_PRIORITY);
+                       gicd_set_isenabler(g_gicd_base, irq_num);
+               }
+       }
+}
+
+/*******************************************************************************
+ * Get the current CPU bit mask from GICD_ITARGETSR0
+ ******************************************************************************/
+static unsigned int arm_gic_get_cpuif_id(void)
+{
+       unsigned int val;
+
+       val = gicd_read_itargetsr(g_gicd_base, 0);
+       return val & GIC_TARGET_CPU_MASK;
+}
+
+/*******************************************************************************
+ * Global gic distributor setup which will be done by the primary cpu after a
+ * cold boot. It marks out the secure SPIs, PPIs & SGIs and enables them. It
+ * then enables the secure GIC distributor interface.
+ ******************************************************************************/
+static void arm_gic_distif_setup(void)
+{
+       unsigned int num_ints, ctlr, index, irq_num;
+       uint8_t target_cpu;
+
+       /* Disable the distributor before going further */
+       assert(g_gicd_base);
+       ctlr = gicd_read_ctlr(g_gicd_base);
+       ctlr &= ~(ENABLE_GRP0 | ENABLE_GRP1);
+       gicd_write_ctlr(g_gicd_base, ctlr);
+
+       /*
+        * Mark out non-secure SPI interrupts. The number of interrupts is
+        * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
+        */
+       num_ints = gicd_read_typer(g_gicd_base) & IT_LINES_NO_MASK;
+       num_ints = (num_ints + 1) << 5;
+       for (index = MIN_SPI_ID; index < num_ints; index += 32)
+               gicd_write_igroupr(g_gicd_base, index, ~0);
+
+       /* Setup SPI priorities doing four at a time */
+       for (index = MIN_SPI_ID; index < num_ints; index += 4) {
+               gicd_write_ipriorityr(g_gicd_base, index,
+                               GICD_IPRIORITYR_DEF_VAL);
+       }
+
+       /* Read the target CPU mask */
+       target_cpu = arm_gic_get_cpuif_id();
+
+       /* Configure SPI secure interrupts now */
+       assert(g_irq_sec_ptr);
+       for (index = 0; index < g_num_irqs; index++) {
+               irq_num = g_irq_sec_ptr[index];
+               if (irq_num >= MIN_SPI_ID) {
+                       /* We have an SPI */
+                       gicd_clr_igroupr(g_gicd_base, irq_num);
+                       gicd_set_ipriorityr(g_gicd_base, irq_num,
+                               GIC_HIGHEST_SEC_PRIORITY);
+                       gicd_set_itargetsr(g_gicd_base, irq_num, target_cpu);
+                       gicd_set_isenabler(g_gicd_base, irq_num);
+               }
+       }
+
+       /*
+        * Configure the SGI and PPI. This is done in a separated function
+        * because each CPU is responsible for initializing its own private
+        * interrupts.
+        */
+       arm_gic_pcpu_distif_setup();
+
+       gicd_write_ctlr(g_gicd_base, ctlr | ENABLE_GRP0);
+}
+
+/*******************************************************************************
+ * Initialize the ARM GIC driver with the provided platform inputs
+******************************************************************************/
+void arm_gic_init(unsigned int gicc_base,
+               unsigned int gicd_base,
+               unsigned long gicr_base,
+               const unsigned int *irq_sec_ptr,
+               unsigned int num_irqs
+               )
+{
+       unsigned int val;
+
+       assert(gicc_base);
+       assert(gicd_base);
+       assert(irq_sec_ptr);
+
+       g_gicc_base = gicc_base;
+       g_gicd_base = gicd_base;
+
+       val = gicc_read_iidr(g_gicc_base);
+
+       if (((val >> GICC_IIDR_ARCH_SHIFT) & GICC_IIDR_ARCH_MASK) >= 3) {
+               assert(gicr_base);
+               g_gicr_base = gicr_base;
+       }
+
+       g_irq_sec_ptr = irq_sec_ptr;
+       g_num_irqs = num_irqs;
+}
+
+/*******************************************************************************
+ * Setup the ARM GIC CPU and distributor interfaces.
+******************************************************************************/
+void arm_gic_setup(void)
+{
+       arm_gic_cpuif_setup();
+       arm_gic_distif_setup();
+}
+
+/*******************************************************************************
+ * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
+ * The interrupt controller knows which pin/line it uses to signal a type of
+ * interrupt. This function provides a common implementation of
+ * plat_interrupt_type_to_line() in an ARM GIC environment for optional re-use
+ * across platforms. It lets the interrupt management framework determine
+ * for a type of interrupt and security state, which line should be used in the
+ * SCR_EL3 to control its routing to EL3. The interrupt line is represented as
+ * the bit position of the IRQ or FIQ bit in the SCR_EL3.
+ ******************************************************************************/
+uint32_t arm_gic_interrupt_type_to_line(uint32_t type,
+                               uint32_t security_state)
+{
+       assert(type == INTR_TYPE_S_EL1 ||
+              type == INTR_TYPE_EL3 ||
+              type == INTR_TYPE_NS);
+
+       assert(sec_state_is_valid(security_state));
+
+       /*
+        * We ignore the security state parameter under the assumption that
+        * both normal and secure worlds are using ARM GICv2. This parameter
+        * will be used when the secure world starts using GICv3.
+        */
+#if ARM_GIC_ARCH == 2
+       return gicv2_interrupt_type_to_line(g_gicc_base, type);
+#else
+#error "Invalid ARM GIC architecture version specified for platform port"
+#endif /* ARM_GIC_ARCH */
+}
+
+#if ARM_GIC_ARCH == 2
+/*******************************************************************************
+ * This function returns the type of the highest priority pending interrupt at
+ * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+uint32_t arm_gic_get_pending_interrupt_type(void)
+{
+       uint32_t id;
+
+       assert(g_gicc_base);
+       id = gicc_read_hppir(g_gicc_base);
+
+       /* Assume that all secure interrupts are S-EL1 interrupts */
+       if (id < 1022)
+               return INTR_TYPE_S_EL1;
+
+       if (id == GIC_SPURIOUS_INTERRUPT)
+               return INTR_TYPE_INVAL;
+
+       return INTR_TYPE_NS;
+}
+
+/*******************************************************************************
+ * This function returns the id of the highest priority pending interrupt at
+ * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+uint32_t arm_gic_get_pending_interrupt_id(void)
+{
+       uint32_t id;
+
+       assert(g_gicc_base);
+       id = gicc_read_hppir(g_gicc_base);
+
+       if (id < 1022)
+               return id;
+
+       if (id == 1023)
+               return INTR_ID_UNAVAILABLE;
+
+       /*
+        * Find out which non-secure interrupt it is under the assumption that
+        * the GICC_CTLR.AckCtl bit is 0.
+        */
+       return gicc_read_ahppir(g_gicc_base);
+}
+
+/*******************************************************************************
+ * This functions reads the GIC cpu interface Interrupt Acknowledge register
+ * to start handling the pending interrupt. It returns the contents of the IAR.
+ ******************************************************************************/
+uint32_t arm_gic_acknowledge_interrupt(void)
+{
+       assert(g_gicc_base);
+       return gicc_read_IAR(g_gicc_base);
+}
+
+/*******************************************************************************
+ * This functions writes the GIC cpu interface End Of Interrupt register with
+ * the passed value to finish handling the active interrupt
+ ******************************************************************************/
+void arm_gic_end_of_interrupt(uint32_t id)
+{
+       assert(g_gicc_base);
+       gicc_write_EOIR(g_gicc_base, id);
+}
+
+/*******************************************************************************
+ * This function returns the type of the interrupt id depending upon the group
+ * this interrupt has been configured under by the interrupt controller i.e.
+ * group0 or group1.
+ ******************************************************************************/
+uint32_t arm_gic_get_interrupt_type(uint32_t id)
+{
+       uint32_t group;
+
+       assert(g_gicd_base);
+       group = gicd_get_igroupr(g_gicd_base, id);
+
+       /* Assume that all secure interrupts are S-EL1 interrupts */
+       if (group == GRP0)
+               return INTR_TYPE_S_EL1;
+       else
+               return INTR_TYPE_NS;
+}
+
+#else
+#error "Invalid ARM GIC architecture version specified for platform port"
+#endif /* ARM_GIC_ARCH */
diff --git a/drivers/arm/gic/gic_v2.c b/drivers/arm/gic/gic_v2.c
new file mode 100644 (file)
index 0000000..41603a9
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <gic_v2.h>
+#include <interrupt_mgmt.h>
+#include <mmio.h>
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+
+unsigned int gicd_read_igroupr(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> IGROUPR_SHIFT;
+       return mmio_read_32(base + GICD_IGROUPR + (n << 2));
+}
+
+unsigned int gicd_read_isenabler(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> ISENABLER_SHIFT;
+       return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+unsigned int gicd_read_icenabler(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> ICENABLER_SHIFT;
+       return mmio_read_32(base + GICD_ICENABLER + (n << 2));
+}
+
+unsigned int gicd_read_ispendr(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> ISPENDR_SHIFT;
+       return mmio_read_32(base + GICD_ISPENDR + (n << 2));
+}
+
+unsigned int gicd_read_icpendr(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> ICPENDR_SHIFT;
+       return mmio_read_32(base + GICD_ICPENDR + (n << 2));
+}
+
+unsigned int gicd_read_isactiver(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> ISACTIVER_SHIFT;
+       return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
+}
+
+unsigned int gicd_read_icactiver(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> ICACTIVER_SHIFT;
+       return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
+}
+
+unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> IPRIORITYR_SHIFT;
+       return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+}
+
+unsigned int gicd_read_itargetsr(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> ITARGETSR_SHIFT;
+       return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
+}
+
+unsigned int gicd_read_icfgr(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> ICFGR_SHIFT;
+       return mmio_read_32(base + GICD_ICFGR + (n << 2));
+}
+
+unsigned int gicd_read_cpendsgir(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> CPENDSGIR_SHIFT;
+       return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
+}
+
+unsigned int gicd_read_spendsgir(unsigned int base, unsigned int id)
+{
+       unsigned n = id >> SPENDSGIR_SHIFT;
+       return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+
+void gicd_write_igroupr(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> IGROUPR_SHIFT;
+       mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
+}
+
+void gicd_write_isenabler(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> ISENABLER_SHIFT;
+       mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
+}
+
+void gicd_write_icenabler(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> ICENABLER_SHIFT;
+       mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
+}
+
+void gicd_write_ispendr(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> ISPENDR_SHIFT;
+       mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
+}
+
+void gicd_write_icpendr(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> ICPENDR_SHIFT;
+       mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
+}
+
+void gicd_write_isactiver(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> ISACTIVER_SHIFT;
+       mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
+}
+
+void gicd_write_icactiver(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> ICACTIVER_SHIFT;
+       mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
+}
+
+void gicd_write_ipriorityr(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> IPRIORITYR_SHIFT;
+       mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
+}
+
+void gicd_write_itargetsr(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> ITARGETSR_SHIFT;
+       mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
+}
+
+void gicd_write_icfgr(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> ICFGR_SHIFT;
+       mmio_write_32(base + GICD_ICFGR + (n << 2), val);
+}
+
+void gicd_write_cpendsgir(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> CPENDSGIR_SHIFT;
+       mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
+}
+
+void gicd_write_spendsgir(unsigned int base, unsigned int id, unsigned int val)
+{
+       unsigned n = id >> SPENDSGIR_SHIFT;
+       mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for individual interrupt manipulation
+ ******************************************************************************/
+unsigned int gicd_get_igroupr(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+       unsigned int reg_val = gicd_read_igroupr(base, id);
+
+       return (reg_val >> bit_num) & 0x1;
+}
+
+void gicd_set_igroupr(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+       unsigned int reg_val = gicd_read_igroupr(base, id);
+
+       gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
+}
+
+void gicd_clr_igroupr(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+       unsigned int reg_val = gicd_read_igroupr(base, id);
+
+       gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
+}
+
+void gicd_set_isenabler(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
+
+       gicd_write_isenabler(base, id, (1 << bit_num));
+}
+
+void gicd_set_icenabler(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
+
+       gicd_write_icenabler(base, id, (1 << bit_num));
+}
+
+void gicd_set_ispendr(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
+
+       gicd_write_ispendr(base, id, (1 << bit_num));
+}
+
+void gicd_set_icpendr(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
+
+       gicd_write_icpendr(base, id, (1 << bit_num));
+}
+
+void gicd_set_isactiver(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
+
+       gicd_write_isactiver(base, id, (1 << bit_num));
+}
+
+void gicd_set_icactiver(unsigned int base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
+
+       gicd_write_icactiver(base, id, (1 << bit_num));
+}
+
+/*
+ * Make sure that the interrupt's group is set before expecting
+ * this function to do its job correctly.
+ */
+void gicd_set_ipriorityr(unsigned int base, unsigned int id, unsigned int pri)
+{
+       unsigned int reg = base + GICD_IPRIORITYR + (id & ~3);
+       unsigned int shift = (id & 3) << 3;
+       unsigned int reg_val = mmio_read_32(reg);
+
+       /*
+        * Enforce ARM recommendation to manage priority values such
+        * that group1 interrupts always have a lower priority than
+        * group0 interrupts.
+        * Note, lower numerical values are higher priorities so the comparison
+        * checks below are reversed from what might be expected.
+        */
+       assert(gicd_get_igroupr(base, id) == GRP1 ?
+               pri >= GIC_HIGHEST_NS_PRIORITY &&
+                       pri <= GIC_LOWEST_NS_PRIORITY :
+               pri >= GIC_HIGHEST_SEC_PRIORITY &&
+                       pri <= GIC_LOWEST_SEC_PRIORITY);
+
+       reg_val &= ~(GIC_PRI_MASK << shift);
+       reg_val |= (pri & GIC_PRI_MASK) << shift;
+       mmio_write_32(reg, reg_val);
+}
+
+void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int target)
+{
+       unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
+       unsigned int reg_val = gicd_read_itargetsr(base, id);
+
+       gicd_write_itargetsr(base, id, reg_val | (target << (byte_off << 3)));
+}
+
+/*******************************************************************************
+ * This function allows the interrupt management framework to determine (through
+ * the platform) which interrupt line (IRQ/FIQ) to use for an interrupt type to
+ * route it to EL3. The interrupt line is represented as the bit position of the
+ * IRQ or FIQ bit in the SCR_EL3.
+ ******************************************************************************/
+uint32_t gicv2_interrupt_type_to_line(uint32_t cpuif_base, uint32_t type)
+{
+       uint32_t gicc_ctlr;
+
+       /* Non-secure interrupts are signalled on the IRQ line always */
+       if (type == INTR_TYPE_NS)
+               return __builtin_ctz(SCR_IRQ_BIT);
+
+       /*
+        * Secure interrupts are signalled using the IRQ line if the FIQ_EN
+        * bit is not set else they are signalled using the FIQ line.
+        */
+       gicc_ctlr = gicc_read_ctlr(cpuif_base);
+       if (gicc_ctlr & FIQ_EN)
+               return __builtin_ctz(SCR_FIQ_BIT);
+       else
+               return __builtin_ctz(SCR_IRQ_BIT);
+}
diff --git a/drivers/arm/gic/gic_v3.c b/drivers/arm/gic/gic_v3.c
new file mode 100644 (file)
index 0000000..f429662
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <debug.h>
+#include <gic_v3.h>
+
+uintptr_t gicv3_get_rdist(uintptr_t gicr_base, uint64_t mpidr)
+{
+       uint32_t  cpu_aff, gicr_aff;
+       uint64_t  gicr_typer;
+       uintptr_t addr;
+
+       /* Construct the affinity as used by GICv3. MPIDR and GIC affinity level
+        * mask is the same.
+        */
+       cpu_aff  = ((mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK) <<
+                       GICV3_AFF0_SHIFT;
+       cpu_aff |= ((mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK) <<
+                       GICV3_AFF1_SHIFT;
+       cpu_aff |= ((mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK) <<
+                       GICV3_AFF2_SHIFT;
+       cpu_aff |= ((mpidr >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK) <<
+                       GICV3_AFF3_SHIFT;
+
+       addr = gicr_base;
+       do {
+               gicr_typer = gicr_read_typer(addr);
+
+               gicr_aff = (gicr_typer >> GICR_TYPER_AFF_SHIFT) &
+                               GICR_TYPER_AFF_MASK;
+               if (cpu_aff == gicr_aff) {
+                       /* Disable this print for now as it appears every time
+                        * when using PSCI CPU_SUSPEND.
+                        * TODO: Print this only the first time for each CPU.
+                        * INFO("GICv3 - Found RDIST for MPIDR(0x%lx) at 0x%lx\n",
+                        *      mpidr, addr);
+                        */
+                       return addr;
+               }
+
+               /* TODO:
+                * For GICv4 we need to adjust the Base address based on
+                * GICR_TYPER.VLPIS
+                */
+               addr += (1 << GICR_PCPUBASE_SHIFT);
+
+       } while (!(gicr_typer & GICR_TYPER_LAST));
+
+       /* If we get here we did not find a match. */
+       ERROR("GICv3 - Did not find RDIST for CPU with MPIDR 0x%lx\n", mpidr);
+       return (uintptr_t)NULL;
+}
diff --git a/drivers/arm/gpio/gpio.c b/drivers/arm/gpio/gpio.c
new file mode 100644 (file)
index 0000000..a38db94
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * GPIO driver for PL061
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <gpio.h>
+#include <mmio.h>
+
+#define MAX_GPIO_DEVICES       32
+#define GPIOS_PER_DEV          8
+#define GPIO_DIR               0x400
+
+#define BIT(nr)                        (1UL << (nr))
+
+struct gpio_device_t {
+       unsigned int    base[MAX_GPIO_DEVICES];
+       unsigned int    count;
+};
+
+static struct gpio_device_t gpio_dev;
+
+/* return 0 for failure */
+static unsigned int find_gc_base(unsigned int gpio)
+{
+       int gc;
+
+       gc = gpio / GPIOS_PER_DEV;
+       if (gc >= gpio_dev.count)
+               return 0;
+       return gpio_dev.base[gc];
+}
+
+int gpio_direction_input(unsigned int gpio)
+{
+       unsigned int gc_base, offset, data;
+
+       gc_base = find_gc_base(gpio);
+       if (!gc_base)
+               return -EINVAL;
+       offset = gpio % GPIOS_PER_DEV;
+
+       data = mmio_read_8(gc_base + GPIO_DIR);
+       data &= ~(1 << offset);
+       mmio_write_8(gc_base + GPIO_DIR, data);
+       return 0;
+}
+
+int gpio_direction_output(unsigned int gpio)
+{
+       unsigned int gc_base, offset, data;
+
+       gc_base = find_gc_base(gpio);
+       if (!gc_base)
+               return -EINVAL;
+       offset = gpio % 8;
+
+       data = mmio_read_8(gc_base + GPIO_DIR);
+       data |= 1 << offset;
+       mmio_write_8(gc_base + GPIO_DIR, data);
+       return 0;
+}
+
+int gpio_get_value(unsigned int gpio)
+{
+       unsigned int gc_base, offset;
+
+       gc_base = find_gc_base(gpio);
+       if (!gc_base)
+               return -EINVAL;
+       offset = gpio % 8;
+
+       return !!mmio_read_8(gc_base + (BIT(offset + 2)));
+}
+
+int gpio_set_value(unsigned int gpio, unsigned int value)
+{
+       unsigned int gc_base, offset;
+
+       gc_base = find_gc_base(gpio);
+       if (!gc_base)
+               return -EINVAL;
+       offset = gpio % 8;
+       mmio_write_8(gc_base + (BIT(offset + 2)), !!value << offset); 
+       return 0;
+}
+
+int gpio_register_device(unsigned int base)
+{
+       int i;
+       if (gpio_dev.count > MAX_GPIO_DEVICES)
+               return -EINVAL;
+       for (i = 0; i < gpio_dev.count; i++) {
+               if (gpio_dev.base[i] == base) {
+                       WARN("%s: duplicated gpio base\n", __func__);
+                       return -EINVAL;
+               }
+       }
+       gpio_dev.base[gpio_dev.count] = base;
+       gpio_dev.count++;
+       return 0;
+}
diff --git a/drivers/arm/pl011/pl011_console.S b/drivers/arm/pl011/pl011_console.S
new file mode 100644 (file)
index 0000000..5ff1582
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <pl011.h>
+
+       .globl  console_init
+       .globl  console_putc
+       .globl  console_core_init
+       .globl  console_core_putc
+       .globl  console_getc
+
+       /*
+        *  The console base is in the data section and not in .bss
+        *  even though it is zero-init. In particular, this allows
+        *  the console functions to start using this variable before
+        *  the runtime memory is initialized for images which do not
+        *  need to copy the .data section from ROM to RAM.
+        */
+.section .data.console_base ; .align 3
+       console_base: .quad 0x0
+
+       /* -----------------------------------------------
+        * int console_init(unsigned long base_addr,
+        * unsigned int uart_clk, unsigned int baud_rate)
+        * Function to initialize the console without a
+        * C Runtime to print debug information. It saves
+        * the console base to the data section.
+        * In: x0 - console base address
+        *     w1 - Uart clock in Hz
+        *     w2 - Baud rate
+        * out: return 1 on success.
+        * Clobber list : x1 - x3
+        * -----------------------------------------------
+        */
+func console_init
+       adrp    x3, console_base
+       str     x0, [x3, :lo12:console_base]
+       b       console_core_init
+
+       /* -----------------------------------------------
+        * int console_core_init(unsigned long base_addr,
+        * unsigned int uart_clk, unsigned int baud_rate)
+        * Function to initialize the console without a
+        * C Runtime to print debug information. This
+        * function will be accessed by console_init and
+        * crash reporting.
+        * In: x0 - console base address
+        *     w1 - Uart clock in Hz
+        *     w2 - Baud rate
+        * Out: return 1 on success
+        * Clobber list : x1, x2
+        * -----------------------------------------------
+        */
+func console_core_init
+       /* Check the input base address */
+       cbz     x0, init_fail
+       /* Check baud rate and uart clock for sanity */
+       cbz     w1, init_fail
+       cbz     w2, init_fail
+       /* Program the baudrate */
+       /* Divisor =  (Uart clock * 4) / baudrate */
+       lsl     w1, w1, #2
+       udiv    w2, w1, w2
+       /* IBRD = Divisor >> 6 */
+       lsr     w1, w2, #6
+       /* Write the IBRD */
+       str     w1, [x0, #UARTIBRD]
+       /* FBRD = Divisor & 0x3F */
+       and     w1, w2, #0x3f
+       /* Write the FBRD */
+       str     w1, [x0, #UARTFBRD]
+       mov     w1, #PL011_LINE_CONTROL
+       str     w1, [x0, #UARTLCR_H]
+       /* Clear any pending errors */
+       str     wzr, [x0, #UARTECR]
+       /* Enable tx, rx, and uart overall */
+       mov     w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
+       str     w1, [x0, #UARTCR]
+       mov     w0, #1
+init_fail:
+       ret
+
+       /* ---------------------------------------------
+        * int console_putc(int c)
+        * Function to output a character over the
+        * console. It returns the character printed on
+        * success or -1 on error.
+        * In : x0 - character to be printed
+        * Out : return -1 on error else return character.
+        * Clobber list : x1, x2
+        * ---------------------------------------------
+        */
+func console_putc
+       adrp    x2, console_base
+       ldr     x1, [x2, :lo12:console_base]
+       b       console_core_putc
+
+       /* --------------------------------------------------------
+        * int console_core_putc(int c, unsigned int base_addr)
+        * Function to output a character over the console. It
+        * returns the character printed on success or -1 on error.
+        * In : w0 - character to be printed
+        *      x1 - console base address
+        * Out : return -1 on error else return character.
+        * Clobber list : x2
+        * --------------------------------------------------------
+        */
+func console_core_putc
+       /* Check the input parameter */
+       cbz     x1, putc_error
+       /* Prepend '\r' to '\n' */
+       cmp     w0, #0xA
+       b.ne    2f
+1:
+       /* Check if the transmit FIFO is full */
+       ldr     w2, [x1, #UARTFR]
+       tbnz    w2, #PL011_UARTFR_TXFF_BIT, 1b
+       mov     w2, #0xD
+       str     w2, [x1, #UARTDR]
+2:
+       /* Check if the transmit FIFO is full */
+       ldr     w2, [x1, #UARTFR]
+       tbnz    w2, #PL011_UARTFR_TXFF_BIT, 2b
+       str     w0, [x1, #UARTDR]
+       ret
+putc_error:
+       mov     w0, #-1
+       ret
+
+       /* ---------------------------------------------
+        * int console_getc(void)
+        * Function to get a character from the console.
+        * It returns the character grabbed on success
+        * or -1 on error.
+        * Clobber list : x0, x1
+        * ---------------------------------------------
+        */
+func console_getc
+       adrp    x0, console_base
+       ldr     x1, [x0, :lo12:console_base]
+       cbz     x1, getc_error
+1:
+       /* Check if the receive FIFO is empty */
+       ldr     w0, [x1, #UARTFR]
+       tbnz    w0, #PL011_UARTFR_RXFE_BIT, 1b
+       ldr     w0, [x1, #UARTDR]
+       ret
+getc_error:
+       mov     w0, #-1
+       ret
diff --git a/drivers/arm/tzc400/tzc400.c b/drivers/arm/tzc400/tzc400.c
new file mode 100644 (file)
index 0000000..df52c9c
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <stddef.h>
+#include <tzc400.h>
+
+/*
+ * Implementation defined values used to validate inputs later.
+ * Filters : max of 4 ; 0 to 3
+ * Regions : max of 9 ; 0 to 8
+ * Address width : Values between 32 to 64
+ */
+typedef struct tzc_instance {
+       uint64_t base;
+       uint8_t addr_width;
+       uint8_t num_filters;
+       uint8_t num_regions;
+} tzc_instance_t;
+
+tzc_instance_t tzc;
+
+
+static inline uint32_t tzc_read_build_config(uint64_t base)
+{
+       return mmio_read_32(base + BUILD_CONFIG_OFF);
+}
+
+static inline uint32_t tzc_read_gate_keeper(uint64_t base)
+{
+       return mmio_read_32(base + GATE_KEEPER_OFF);
+}
+
+static inline void tzc_write_gate_keeper(uint64_t base, uint32_t val)
+{
+       mmio_write_32(base + GATE_KEEPER_OFF, val);
+}
+
+static inline void tzc_write_action(uint64_t base, tzc_action_t action)
+{
+       mmio_write_32(base + ACTION_OFF, action);
+}
+
+static inline void tzc_write_region_base_low(uint64_t base,
+                                       uint32_t region,
+                                       uint32_t val)
+{
+       mmio_write_32(base + REGION_BASE_LOW_OFF +
+               REGION_NUM_OFF(region), val);
+}
+
+static inline void tzc_write_region_base_high(uint64_t base,
+                                       uint32_t region,
+                                       uint32_t val)
+{
+       mmio_write_32(base + REGION_BASE_HIGH_OFF +
+               REGION_NUM_OFF(region), val);
+}
+
+static inline void tzc_write_region_top_low(uint64_t base,
+                                       uint32_t region,
+                                       uint32_t val)
+{
+       mmio_write_32(base + REGION_TOP_LOW_OFF +
+               REGION_NUM_OFF(region), val);
+}
+
+static inline void tzc_write_region_top_high(uint64_t base,
+                                       uint32_t region,
+                                       uint32_t val)
+{
+       mmio_write_32(base + REGION_TOP_HIGH_OFF +
+               REGION_NUM_OFF(region), val);
+}
+
+static inline void tzc_write_region_attributes(uint64_t base,
+                                       uint32_t region,
+                                       uint32_t val)
+{
+       mmio_write_32(base + REGION_ATTRIBUTES_OFF +
+               REGION_NUM_OFF(region), val);
+}
+
+static inline void tzc_write_region_id_access(uint64_t base,
+                                       uint32_t region,
+                                       uint32_t val)
+{
+       mmio_write_32(base + REGION_ID_ACCESS_OFF +
+               REGION_NUM_OFF(region), val);
+}
+
+static uint32_t tzc_read_component_id(uint64_t base)
+{
+       uint32_t id;
+
+       id = mmio_read_8(base + CID0_OFF);
+       id |= (mmio_read_8(base + CID1_OFF) << 8);
+       id |= (mmio_read_8(base + CID2_OFF) << 16);
+       id |= (mmio_read_8(base + CID3_OFF) << 24);
+
+       return id;
+}
+
+static uint32_t tzc_get_gate_keeper(uint64_t base, uint8_t filter)
+{
+       uint32_t tmp;
+
+       tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
+               GATE_KEEPER_OS_MASK;
+
+       return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
+}
+
+/* This function is not MP safe. */
+static void tzc_set_gate_keeper(uint64_t base, uint8_t filter, uint32_t val)
+{
+       uint32_t tmp;
+
+       /* Upper half is current state. Lower half is requested state. */
+       tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
+               GATE_KEEPER_OS_MASK;
+
+       if (val)
+               tmp |=  (1 << filter);
+       else
+               tmp &= ~(1 << filter);
+
+       tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
+                             GATE_KEEPER_OR_SHIFT);
+
+       /* Wait here until we see the change reflected in the TZC status. */
+       while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
+               GATE_KEEPER_OS_MASK) != tmp)
+         ;
+}
+
+
+void tzc_init(uint64_t base)
+{
+       uint32_t tzc_id, tzc_build;
+
+       assert(base);
+       tzc.base = base;
+
+       /*
+        * We expect to see a tzc400. Check component ID. The TZC-400 TRM shows
+        * component ID is expected to be "0xB105F00D".
+        */
+       tzc_id = tzc_read_component_id(tzc.base);
+       if (tzc_id != TZC400_COMPONENT_ID) {
+               ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
+               panic();
+       }
+
+       /* Save values we will use later. */
+       tzc_build = tzc_read_build_config(tzc.base);
+       tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
+                          BUILD_CONFIG_NF_MASK) + 1;
+       tzc.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
+                          BUILD_CONFIG_AW_MASK) + 1;
+       tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
+                          BUILD_CONFIG_NR_MASK) + 1;
+}
+
+
+/*
+ * `tzc_configure_region` is used to program regions into the TrustZone
+ * controller. A region can be associated with more than one filter. The
+ * associated filters are passed in as a bitmap (bit0 = filter0).
+ * NOTE:
+ * The region 0 covers the whole address space and is enabled on all filters,
+ * this cannot be changed. It is, however, possible to change some region 0
+ * permissions.
+ */
+void tzc_configure_region(uint32_t filters,
+                         uint8_t  region,
+                         uint64_t region_base,
+                         uint64_t region_top,
+                         tzc_region_attributes_t sec_attr,
+                         uint32_t ns_device_access)
+{
+       assert(tzc.base);
+
+       /* Do range checks on filters and regions. */
+       assert(((filters >> tzc.num_filters) == 0) &&
+              (region < tzc.num_regions));
+
+       /*
+        * Do address range check based on TZC configuration. A 64bit address is
+        * the max and expected case.
+        */
+       assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
+               (region_base < region_top)));
+
+       /* region_base and (region_top + 1) must be 4KB aligned */
+       assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+       assert(sec_attr <= TZC_REGION_S_RDWR);
+
+       /*
+        * Inputs look ok, start programming registers.
+        * All the address registers are 32 bits wide and have a LOW and HIGH
+        * component used to construct a up to a 64bit address.
+        */
+       tzc_write_region_base_low(tzc.base, region,
+                               (uint32_t)(region_base));
+       tzc_write_region_base_high(tzc.base, region,
+                               (uint32_t)(region_base >> 32));
+
+       tzc_write_region_top_low(tzc.base, region,
+                               (uint32_t)(region_top));
+       tzc_write_region_top_high(tzc.base, region,
+                               (uint32_t)(region_top >> 32));
+
+       /* Assign the region to a filter and set secure attributes */
+       tzc_write_region_attributes(tzc.base, region,
+               (sec_attr << REG_ATTR_SEC_SHIFT) | filters);
+
+       /*
+        * Specify which non-secure devices have permission to access this
+        * region.
+        */
+       tzc_write_region_id_access(tzc.base, region, ns_device_access);
+}
+
+
+void tzc_set_action(tzc_action_t action)
+{
+       assert(tzc.base);
+
+       /*
+        * - Currently no handler is provided to trap an error via interrupt
+        *   or exception.
+        * - The interrupt action has not been tested.
+        */
+       tzc_write_action(tzc.base, action);
+}
+
+
+void tzc_enable_filters(void)
+{
+       uint32_t state;
+       uint32_t filter;
+
+       assert(tzc.base);
+
+       for (filter = 0; filter < tzc.num_filters; filter++) {
+               state = tzc_get_gate_keeper(tzc.base, filter);
+               if (state) {
+                       /* The TZC filter is already configured. Changing the
+                        * programmer's view in an active system can cause
+                        * unpredictable behavior therefore panic for now rather
+                        * than try to determine whether this is safe in this
+                        * instance. See:
+                        * http://infocenter.arm.com/help/index.jsp?\
+                        * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
+                       ERROR("TZC : Filter %d Gatekeeper already enabled.\n",
+                               filter);
+                       panic();
+               }
+               tzc_set_gate_keeper(tzc.base, filter, 1);
+       }
+}
+
+
+void tzc_disable_filters(void)
+{
+       uint32_t filter;
+
+       assert(tzc.base);
+
+       /*
+        * We don't do the same state check as above as the Gatekeepers are
+        * disabled after reset.
+        */
+       for (filter = 0; filter < tzc.num_filters; filter++)
+               tzc_set_gate_keeper(tzc.base, filter, 0);
+}
diff --git a/drivers/io/io_block.c b/drivers/io/io_block.c
new file mode 100644 (file)
index 0000000..4047227
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <errno.h>
+#include <io_block.h>
+#include <io_driver.h>
+#include <io_storage.h>
+#include <mmio.h>
+#include <stdint.h>
+#include <string.h>
+
+/* As we need to be able to keep state for seek, only one file can be open
+ * at a time. Make this a structure and point to the entity->info. When we
+ * can malloc memory we can change this to support more open files.
+ */
+typedef struct {
+       /* Use the 'in_use' flag as any value for base and file_pos could be
+        * valid.
+        */
+       int             in_use;
+       uintptr_t       base;
+       size_t          file_pos;
+       uint32_t        flags;
+} file_state_t;
+
+struct block_info {
+       struct block_ops        ops;
+       int                     init;
+       uint32_t                flags;
+};
+
+static file_state_t current_file = {0};
+
+static struct block_info block_info;
+
+static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+                     io_entity_t *entity);
+static int block_seek(io_entity_t *entity, int mode, ssize_t offset);
+static int block_read(io_entity_t *entity, uintptr_t buffer,
+                     size_t length, size_t *length_read);
+static int block_write(io_entity_t *entity, uintptr_t buffer,
+                      size_t length, size_t *length_written);
+static int block_close(io_entity_t *entity);
+
+static int blk_dev_init(io_dev_info_t *dev_info,
+                       const uintptr_t init_params);
+static int blk_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
+static int blk_dev_close(io_dev_info_t *dev_info);
+
+/* Identify the device type as block */
+io_type_t device_type_block(void)
+{
+       return IO_TYPE_BLOCK;
+}
+
+static const io_dev_connector_t blk_dev_connector = {
+       .dev_open = blk_dev_open
+};
+
+static const io_dev_funcs_t blk_dev_funcs = {
+       .type = device_type_block,
+       .open = block_open,
+       .seek = block_seek,
+       .size = NULL,
+       .read = block_read,
+       .write = block_write,
+       .close = block_close,
+       .dev_init = blk_dev_init,
+       .dev_close = blk_dev_close,
+};
+
+
+/* No state associated with this device so structure can be const */
+static const io_dev_info_t blk_dev_info = {
+       .funcs = &blk_dev_funcs,
+       .info = (uintptr_t)&block_info,
+};
+
+/* Open a connection to the block device */
+static int blk_dev_open(const uintptr_t dev_spec __attribute__((unused)),
+                          io_dev_info_t **dev_info)
+{
+       struct block_ops        *funcs, *block_spec;
+
+       assert(dev_info != NULL);
+       *dev_info = (io_dev_info_t *)&blk_dev_info; /* cast away const */
+
+       if (dev_spec) {
+               funcs = &block_info.ops;
+               block_spec = (struct block_ops *)dev_spec;
+               funcs->init = block_spec->init;
+               funcs->read = block_spec->read;
+               funcs->write = block_spec->write;
+       }
+
+       return IO_SUCCESS;
+}
+
+/* Close a connection to the block device */
+static int blk_dev_close(io_dev_info_t *dev_info)
+{
+       /* NOP */
+       /* TODO: Consider tracking open files and cleaning them up here */
+       return IO_SUCCESS;
+}
+
+
+/* Open a file on the block device */
+/* TODO: Can we do any sensible limit checks on requested memory */
+static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+                            io_entity_t *entity)
+{
+       int result = IO_FAIL;
+       const io_block_spec_t *block_spec = (io_block_spec_t *)spec;
+       struct block_info *info = (struct block_info *)(dev_info->info);
+
+       /* Since we need to track open state for seek() we only allow one open
+        * spec at a time. When we have dynamic memory we can malloc and set
+        * entity->info.
+        */
+       if (current_file.in_use == 0) {
+               assert(block_spec != NULL);
+               assert(entity != NULL);
+
+               current_file.in_use = 1;
+               current_file.base = block_spec->offset;
+               /* File cursor offset for seek and incremental reads etc. */
+               current_file.file_pos = 0;
+               current_file.flags = info->flags;
+               entity->info = (uintptr_t)&current_file;
+               result = IO_SUCCESS;
+       } else {
+               WARN("A block device is already active. Close first.\n");
+               result = IO_RESOURCES_EXHAUSTED;
+       }
+
+       return result;
+}
+
+/* Seek to a particular file offset on the block device */
+static int block_seek(io_entity_t *entity, int mode, ssize_t offset)
+{
+       int result = IO_FAIL;
+
+       /* We only support IO_SEEK_SET for the moment. */
+       if (mode == IO_SEEK_SET) {
+               assert(entity != NULL);
+
+               /* TODO: can we do some basic limit checks on seek? */
+               ((file_state_t *)entity->info)->file_pos = offset;
+               result = IO_SUCCESS;
+       } else {
+               result = IO_FAIL;
+       }
+
+       return result;
+}
+
+
+/* Read data from a file on the block device */
+static int block_read(io_entity_t *entity, uintptr_t buffer,
+                     size_t length, size_t *length_read)
+{
+       file_state_t *fp;
+       int result;
+
+       assert(entity != NULL);
+       assert(buffer != (uintptr_t)NULL);
+       assert(length_read != NULL);
+
+       fp = (file_state_t *)entity->info;
+
+       if (!block_info.ops.read) {
+               ERROR("There's no read function on the block device.\n");
+               return IO_NOT_SUPPORTED;
+       }
+       result = block_info.ops.read(fp->base + fp->file_pos, length,
+                                    buffer, fp->flags);
+       if (result) {
+               WARN("Failed to read block offset 0x%x\n",
+                    fp->base + fp->file_pos);
+               return result;
+       }
+
+       *length_read = length;
+       /* advance the file 'cursor' for incremental reads */
+       fp->file_pos += length;
+
+       return IO_SUCCESS;
+}
+
+static int block_write(io_entity_t *entity, uintptr_t buffer,
+                      size_t length, size_t *length_written)
+{
+       file_state_t *fp;
+       int result;
+
+       assert(entity != NULL);
+       assert(buffer != (uintptr_t)NULL);
+       assert(length_written != NULL);
+
+       fp = (file_state_t *)entity->info;
+
+       if (!block_info.ops.write) {
+               ERROR("There's no write function on the block device.\n");
+               return IO_NOT_SUPPORTED;
+       }
+       result = block_info.ops.write(fp->base + fp->file_pos, length,
+                                     buffer, fp->flags);
+       if (result) {
+               WARN("Failed to write block offset 0x%x\n",
+                    fp->base + fp->file_pos);
+               return result;
+       }
+
+       *length_written = length;
+       /* advance the file 'cursor' for incremental reads */
+       fp->file_pos += length;
+
+       return IO_SUCCESS;
+}
+
+/* Close a file on the BLOCK device */
+static int block_close(io_entity_t *entity)
+{
+       assert(entity != NULL);
+
+       entity->info = 0;
+
+       /* This would be a mem free() if we had malloc.*/
+       memset((void *)&current_file, 0, sizeof(current_file));
+
+       return IO_SUCCESS;
+}
+
+static int blk_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+       struct block_info *info = (struct block_info *)(dev_info->info);
+
+       if (!info->init) {
+               if (block_info.ops.init)
+                       block_info.ops.init();
+               info->init = 1;
+       }
+       info->flags = init_params;
+       return IO_SUCCESS;
+}
+
+/* Exported functions */
+
+/* Register the block driver with the IO abstraction */
+int register_io_dev_block(const io_dev_connector_t **dev_con)
+{
+       int result = IO_FAIL;
+       assert(dev_con != NULL);
+
+       result = io_register_device(&blk_dev_info);
+       if (result == IO_SUCCESS)
+               *dev_con = &blk_dev_connector;
+
+       return result;
+}
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
new file mode 100644 (file)
index 0000000..0cec804
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <errno.h>
+#include <firmware_image_package.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <string.h>
+#include <uuid.h>
+
+/* Useful for printing UUIDs when debugging.*/
+#define PRINT_UUID2(x)                                                         \
+       "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",   \
+               x.time_low, x.time_mid, x.time_hi_and_version,                  \
+               x.clock_seq_hi_and_reserved, x.clock_seq_low,                   \
+               x.node[0], x.node[1], x.node[2], x.node[3],                     \
+               x.node[4], x.node[5]
+
+typedef struct {
+       const char      *name;
+       const uuid_t     uuid;
+} plat_fip_name_uuid_t;
+
+typedef struct {
+       /* Put file_pos above the struct to allow {0} on static init.
+        * It is a workaround for a known bug in GCC
+        * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
+        */
+       unsigned int file_pos;
+       fip_toc_entry_t entry;
+} file_state_t;
+
+static const plat_fip_name_uuid_t name_uuid[] = {
+       {BL2_IMAGE_NAME, UUID_TRUSTED_BOOT_FIRMWARE_BL2},
+#ifdef BL30_IMAGE_NAME
+       /* BL3-0 is optional in the platform */
+       {BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30},
+#endif /* BL30_IMAGE_NAME */
+       {BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31},
+#ifdef BL32_IMAGE_NAME
+       /* BL3-2 is optional in the platform */
+       {BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32},
+#endif /* BL32_IMAGE_NAME */
+       {BL33_IMAGE_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33},
+#if TRUSTED_BOARD_BOOT
+       /* Certificates */
+       {BL2_CERT_NAME, UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT},
+       {TRUSTED_KEY_CERT_NAME, UUID_TRUSTED_KEY_CERT},
+#ifdef BL30_KEY_CERT_NAME
+       {BL30_KEY_CERT_NAME, UUID_SCP_FIRMWARE_BL30_KEY_CERT},
+#endif
+       {BL31_KEY_CERT_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT},
+       {BL32_KEY_CERT_NAME, UUID_SECURE_PAYLOAD_BL32_KEY_CERT},
+       {BL33_KEY_CERT_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT},
+#ifdef BL30_CERT_NAME
+       {BL30_CERT_NAME, UUID_SCP_FIRMWARE_BL30_CERT},
+#endif
+       {BL31_CERT_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT},
+       {BL32_CERT_NAME, UUID_SECURE_PAYLOAD_BL32_CERT},
+       {BL33_CERT_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33_CERT},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+static const uuid_t uuid_null = {0};
+static file_state_t current_file = {0};
+static uintptr_t backend_dev_handle;
+static uintptr_t backend_image_spec;
+
+
+/* Firmware Image Package driver functions */
+static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
+static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
+                         io_entity_t *entity);
+static int fip_file_len(io_entity_t *entity, size_t *length);
+static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
+                         size_t *length_read);
+static int fip_file_close(io_entity_t *entity);
+static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
+static int fip_dev_close(io_dev_info_t *dev_info);
+
+
+static inline int copy_uuid(uuid_t *dst, const uuid_t *src)
+{
+       memcpy(dst, src, sizeof(uuid_t));
+       return 0;
+}
+
+
+/* Return 0 for equal uuids. */
+static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2)
+{
+       return memcmp(uuid1, uuid2, sizeof(uuid_t));
+}
+
+
+/* TODO: We could check version numbers or do a package checksum? */
+static inline int is_valid_header(fip_toc_header_t *header)
+{
+       if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0)) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+
+static int file_to_uuid(const char *filename, uuid_t *uuid)
+{
+       int i;
+       int status = -EINVAL;
+
+       for (i = 0; i < (sizeof(name_uuid) / sizeof(name_uuid[0])); i++) {
+               if (strcmp(filename, name_uuid[i].name) == 0) {
+                       copy_uuid(uuid, &name_uuid[i].uuid);
+                       status = 0;
+                       break;
+               }
+       }
+       return status;
+}
+
+
+/* Identify the device type as a virtual driver */
+io_type_t device_type_fip(void)
+{
+       return IO_TYPE_FIRMWARE_IMAGE_PACKAGE;
+}
+
+
+static const io_dev_connector_t fip_dev_connector = {
+       .dev_open = fip_dev_open
+};
+
+
+static const io_dev_funcs_t fip_dev_funcs = {
+       .type = device_type_fip,
+       .open = fip_file_open,
+       .seek = NULL,
+       .size = fip_file_len,
+       .read = fip_file_read,
+       .write = NULL,
+       .close = fip_file_close,
+       .dev_init = fip_dev_init,
+       .dev_close = fip_dev_close,
+};
+
+
+/* No state associated with this device so structure can be const */
+static const io_dev_info_t fip_dev_info = {
+       .funcs = &fip_dev_funcs,
+       .info = (uintptr_t)NULL
+};
+
+
+/* Open a connection to the FIP device */
+static int fip_dev_open(const uintptr_t dev_spec __attribute__((unused)),
+                        io_dev_info_t **dev_info)
+{
+       assert(dev_info != NULL);
+       *dev_info = (io_dev_info_t *)&fip_dev_info; /* cast away const */
+
+       return IO_SUCCESS;
+}
+
+
+/* Do some basic package checks. */
+static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+       int result = IO_FAIL;
+       char *image_name = (char *)init_params;
+       uintptr_t backend_handle;
+       fip_toc_header_t header;
+       size_t bytes_read;
+
+       /* Obtain a reference to the image by querying the platform layer */
+       result = plat_get_image_source(image_name, &backend_dev_handle,
+                                      &backend_image_spec);
+       if (result != IO_SUCCESS) {
+               WARN("Failed to obtain reference to image '%s' (%i)\n",
+                       image_name, result);
+               result = IO_FAIL;
+               goto fip_dev_init_exit;
+       }
+
+       /* Attempt to access the FIP image */
+       result = io_open(backend_dev_handle, backend_image_spec,
+                        &backend_handle);
+       if (result != IO_SUCCESS) {
+               WARN("Failed to access image '%s' (%i)\n", image_name, result);
+               result = IO_FAIL;
+               goto fip_dev_init_exit;
+       }
+
+       result = io_read(backend_handle, (uintptr_t)&header, sizeof(header),
+                       &bytes_read);
+       if (result == IO_SUCCESS) {
+               if (!is_valid_header(&header)) {
+                       WARN("Firmware Image Package header check failed.\n");
+                       result = IO_FAIL;
+               } else {
+                       VERBOSE("FIP header looks OK.\n");
+               }
+       }
+
+       io_close(backend_handle);
+
+ fip_dev_init_exit:
+       return result;
+}
+
+/* Close a connection to the FIP device */
+static int fip_dev_close(io_dev_info_t *dev_info)
+{
+       /* TODO: Consider tracking open files and cleaning them up here */
+
+       /* Clear the backend. */
+       backend_dev_handle = (uintptr_t)NULL;
+       backend_image_spec = (uintptr_t)NULL;
+
+       return IO_SUCCESS;
+}
+
+
+/* Open a file for access from package. */
+static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
+                        io_entity_t *entity)
+{
+       int result = IO_FAIL;
+       uintptr_t backend_handle;
+       uuid_t file_uuid;
+       const io_file_spec_t *file_spec = (io_file_spec_t *)spec;
+       size_t bytes_read;
+       int found_file = 0;
+
+       assert(file_spec != NULL);
+       assert(entity != NULL);
+
+       /* Can only have one file open at a time for the moment. We need to
+        * track state like file cursor position. We know the header lives at
+        * offset zero, so this entry should never be zero for an active file.
+        * When the system supports dynamic memory allocation we can allow more
+        * than one open file at a time if needed.
+        */
+       if (current_file.entry.offset_address != 0) {
+               WARN("fip_file_open : Only one open file at a time.\n");
+               return IO_RESOURCES_EXHAUSTED;
+       }
+
+       /* Attempt to access the FIP image */
+       result = io_open(backend_dev_handle, backend_image_spec,
+                        &backend_handle);
+       if (result != IO_SUCCESS) {
+               WARN("Failed to open Firmware Image Package (%i)\n", result);
+               result = IO_FAIL;
+               goto fip_file_open_exit;
+       }
+
+       /* Seek past the FIP header into the Table of Contents */
+       result = io_seek(backend_handle, IO_SEEK_SET, sizeof(fip_toc_header_t));
+       if (result != IO_SUCCESS) {
+               WARN("fip_file_open: failed to seek\n");
+               result = IO_FAIL;
+               goto fip_file_open_close;
+       }
+
+       file_to_uuid(file_spec->path, &file_uuid);
+
+       found_file = 0;
+       do {
+               result = io_read(backend_handle,
+                                (uintptr_t)&current_file.entry,
+                                sizeof(current_file.entry),
+                                &bytes_read);
+               if (result == IO_SUCCESS) {
+                       if (compare_uuids(&current_file.entry.uuid,
+                                         &file_uuid) == 0) {
+                               found_file = 1;
+                               break;
+                       }
+               } else {
+                       WARN("Failed to read FIP (%i)\n", result);
+                       goto fip_file_open_close;
+               }
+       } while (compare_uuids(&current_file.entry.uuid, &uuid_null) != 0);
+
+       if (found_file == 1) {
+               /* All fine. Update entity info with file state and return. Set
+                * the file position to 0. The 'current_file.entry' holds the
+                * base and size of the file.
+                */
+               current_file.file_pos = 0;
+               entity->info = (uintptr_t)&current_file;
+       } else {
+               /* Did not find the file in the FIP. */
+               current_file.entry.offset_address = 0;
+               result = IO_FAIL;
+       }
+
+ fip_file_open_close:
+       io_close(backend_handle);
+
+ fip_file_open_exit:
+       return result;
+}
+
+
+/* Return the size of a file in package */
+static int fip_file_len(io_entity_t *entity, size_t *length)
+{
+       assert(entity != NULL);
+       assert(length != NULL);
+
+       *length =  ((file_state_t *)entity->info)->entry.size;
+
+       return IO_SUCCESS;
+}
+
+
+/* Read data from a file in package */
+static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
+                         size_t *length_read)
+{
+       int result = IO_FAIL;
+       file_state_t *fp;
+       size_t file_offset;
+       size_t bytes_read;
+       uintptr_t backend_handle;
+
+       assert(entity != NULL);
+       assert(buffer != (uintptr_t)NULL);
+       assert(length_read != NULL);
+       assert(entity->info != (uintptr_t)NULL);
+
+       /* Open the backend, attempt to access the blob image */
+       result = io_open(backend_dev_handle, backend_image_spec,
+                        &backend_handle);
+       if (result != IO_SUCCESS) {
+               WARN("Failed to open FIP (%i)\n", result);
+               result = IO_FAIL;
+               goto fip_file_read_exit;
+       }
+
+       fp = (file_state_t *)entity->info;
+
+       /* Seek to the position in the FIP where the payload lives */
+       file_offset = fp->entry.offset_address + fp->file_pos;
+       result = io_seek(backend_handle, IO_SEEK_SET, file_offset);
+       if (result != IO_SUCCESS) {
+               WARN("fip_file_read: failed to seek\n");
+               result = IO_FAIL;
+               goto fip_file_read_close;
+       }
+
+       result = io_read(backend_handle, buffer, length, &bytes_read);
+       if (result != IO_SUCCESS) {
+               /* We cannot read our data. Fail. */
+               WARN("Failed to read payload (%i)\n", result);
+               result = IO_FAIL;
+               goto fip_file_read_close;
+       } else {
+               /* Set caller length and new file position. */
+               *length_read = bytes_read;
+               fp->file_pos += bytes_read;
+       }
+
+/* Close the backend. */
+ fip_file_read_close:
+       io_close(backend_handle);
+
+ fip_file_read_exit:
+       return result;
+}
+
+
+/* Close a file in package */
+static int fip_file_close(io_entity_t *entity)
+{
+       /* Clear our current file pointer.
+        * If we had malloc() we would free() here.
+        */
+       if (current_file.entry.offset_address != 0) {
+               memset(&current_file, 0, sizeof(current_file));
+       }
+
+       /* Clear the Entity info. */
+       entity->info = 0;
+
+       return IO_SUCCESS;
+}
+
+/* Exported functions */
+
+/* Register the Firmware Image Package driver with the IO abstraction */
+int register_io_dev_fip(const io_dev_connector_t **dev_con)
+{
+       int result = IO_FAIL;
+       assert(dev_con != NULL);
+
+       result = io_register_device(&fip_dev_info);
+       if (result == IO_SUCCESS)
+               *dev_con = &fip_dev_connector;
+
+       return result;
+}
diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c
new file mode 100644 (file)
index 0000000..fc06fbb
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_storage.h>
+#include <string.h>
+
+/* As we need to be able to keep state for seek, only one file can be open
+ * at a time. Make this a structure and point to the entity->info. When we
+ * can malloc memory we can change this to support more open files.
+ */
+typedef struct {
+       /* Use the 'in_use' flag as any value for base and file_pos could be
+        * valid.
+        */
+       int             in_use;
+       uintptr_t       base;
+       size_t          file_pos;
+} file_state_t;
+
+static file_state_t current_file = {0};
+
+/* Identify the device type as memmap */
+io_type_t device_type_memmap(void)
+{
+       return IO_TYPE_MEMMAP;
+}
+
+/* Memmap device functions */
+static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
+static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+                            io_entity_t *entity);
+static int memmap_block_seek(io_entity_t *entity, int mode,
+                            ssize_t offset);
+static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
+                            size_t length, size_t *length_read);
+static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
+                             size_t length, size_t *length_written);
+static int memmap_block_close(io_entity_t *entity);
+static int memmap_dev_close(io_dev_info_t *dev_info);
+
+
+static const io_dev_connector_t memmap_dev_connector = {
+       .dev_open = memmap_dev_open
+};
+
+
+static const io_dev_funcs_t memmap_dev_funcs = {
+       .type = device_type_memmap,
+       .open = memmap_block_open,
+       .seek = memmap_block_seek,
+       .size = NULL,
+       .read = memmap_block_read,
+       .write = memmap_block_write,
+       .close = memmap_block_close,
+       .dev_init = NULL,
+       .dev_close = memmap_dev_close,
+};
+
+
+/* No state associated with this device so structure can be const */
+static const io_dev_info_t memmap_dev_info = {
+       .funcs = &memmap_dev_funcs,
+       .info = (uintptr_t)NULL
+};
+
+
+/* Open a connection to the memmap device */
+static int memmap_dev_open(const uintptr_t dev_spec __attribute__((unused)),
+                          io_dev_info_t **dev_info)
+{
+       assert(dev_info != NULL);
+       *dev_info = (io_dev_info_t *)&memmap_dev_info; /* cast away const */
+
+       return IO_SUCCESS;
+}
+
+
+
+/* Close a connection to the memmap device */
+static int memmap_dev_close(io_dev_info_t *dev_info)
+{
+       /* NOP */
+       /* TODO: Consider tracking open files and cleaning them up here */
+       return IO_SUCCESS;
+}
+
+
+/* Open a file on the memmap device */
+/* TODO: Can we do any sensible limit checks on requested memory */
+static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+                            io_entity_t *entity)
+{
+       int result = IO_FAIL;
+       const io_block_spec_t *block_spec = (io_block_spec_t *)spec;
+
+       /* Since we need to track open state for seek() we only allow one open
+        * spec at a time. When we have dynamic memory we can malloc and set
+        * entity->info.
+        */
+       if (current_file.in_use == 0) {
+               assert(block_spec != NULL);
+               assert(entity != NULL);
+
+               current_file.in_use = 1;
+               current_file.base = block_spec->offset;
+               /* File cursor offset for seek and incremental reads etc. */
+               current_file.file_pos = 0;
+               entity->info = (uintptr_t)&current_file;
+               result = IO_SUCCESS;
+       } else {
+               WARN("A Memmap device is already active. Close first.\n");
+               result = IO_RESOURCES_EXHAUSTED;
+       }
+
+       return result;
+}
+
+
+/* Seek to a particular file offset on the memmap device */
+static int memmap_block_seek(io_entity_t *entity, int mode, ssize_t offset)
+{
+       int result = IO_FAIL;
+
+       /* We only support IO_SEEK_SET for the moment. */
+       if (mode == IO_SEEK_SET) {
+               assert(entity != NULL);
+
+               /* TODO: can we do some basic limit checks on seek? */
+               ((file_state_t *)entity->info)->file_pos = offset;
+               result = IO_SUCCESS;
+       } else {
+               result = IO_FAIL;
+       }
+
+       return result;
+}
+
+
+/* Read data from a file on the memmap device */
+static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
+                            size_t length, size_t *length_read)
+{
+       file_state_t *fp;
+
+       assert(entity != NULL);
+       assert(buffer != (uintptr_t)NULL);
+       assert(length_read != NULL);
+
+       fp = (file_state_t *)entity->info;
+
+       memcpy((void *)buffer, (void *)(fp->base + fp->file_pos), length);
+
+       *length_read = length;
+       /* advance the file 'cursor' for incremental reads */
+       fp->file_pos += length;
+
+       return IO_SUCCESS;
+}
+
+
+/* Write data to a file on the memmap device */
+static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
+                             size_t length, size_t *length_written)
+{
+       file_state_t *fp;
+
+       assert(entity != NULL);
+       assert(buffer != (uintptr_t)NULL);
+       assert(length_written != NULL);
+
+       fp = (file_state_t *)entity->info;
+
+       memcpy((void *)(fp->base + fp->file_pos), (void *)buffer, length);
+
+       *length_written = length;
+
+       /* advance the file 'cursor' for incremental writes */
+       fp->file_pos += length;
+
+       return IO_SUCCESS;
+}
+
+
+/* Close a file on the memmap device */
+static int memmap_block_close(io_entity_t *entity)
+{
+       assert(entity != NULL);
+
+       entity->info = 0;
+
+       /* This would be a mem free() if we had malloc.*/
+       memset((void *)&current_file, 0, sizeof(current_file));
+
+       return IO_SUCCESS;
+}
+
+
+/* Exported functions */
+
+/* Register the memmap driver with the IO abstraction */
+int register_io_dev_memmap(const io_dev_connector_t **dev_con)
+{
+       int result = IO_FAIL;
+       assert(dev_con != NULL);
+
+       result = io_register_device(&memmap_dev_info);
+       if (result == IO_SUCCESS)
+               *dev_con = &memmap_dev_connector;
+
+       return result;
+}
diff --git a/drivers/io/io_semihosting.c b/drivers/io/io_semihosting.c
new file mode 100644 (file)
index 0000000..3c92c6d
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <io_driver.h>
+#include <io_storage.h>
+#include <semihosting.h>
+
+
+
+/* Identify the device type as semihosting */
+static io_type_t device_type_sh(void)
+{
+       return IO_TYPE_SEMIHOSTING;
+}
+
+
+/* Semi-hosting functions, device info and handle */
+
+static int sh_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
+static int sh_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
+               io_entity_t *entity);
+static int sh_file_seek(io_entity_t *entity, int mode, ssize_t offset);
+static int sh_file_len(io_entity_t *entity, size_t *length);
+static int sh_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
+               size_t *length_read);
+static int sh_file_write(io_entity_t *entity, const uintptr_t buffer,
+               size_t length, size_t *length_written);
+static int sh_file_close(io_entity_t *entity);
+
+static const io_dev_connector_t sh_dev_connector = {
+       .dev_open = sh_dev_open
+};
+
+
+static const io_dev_funcs_t sh_dev_funcs = {
+       .type = device_type_sh,
+       .open = sh_file_open,
+       .seek = sh_file_seek,
+       .size = sh_file_len,
+       .read = sh_file_read,
+       .write = sh_file_write,
+       .close = sh_file_close,
+       .dev_init = NULL,       /* NOP */
+       .dev_close = NULL,      /* NOP */
+};
+
+
+/* No state associated with this device so structure can be const */
+static const io_dev_info_t sh_dev_info = {
+       .funcs = &sh_dev_funcs,
+       .info = (uintptr_t)NULL
+};
+
+
+/* Open a connection to the semi-hosting device */
+static int sh_dev_open(const uintptr_t dev_spec __unused,
+               io_dev_info_t **dev_info)
+{
+       int result = IO_SUCCESS;
+       assert(dev_info != NULL);
+       *dev_info = (io_dev_info_t *)&sh_dev_info; /* cast away const */
+       return result;
+}
+
+
+/* Open a file on the semi-hosting device */
+static int sh_file_open(io_dev_info_t *dev_info __attribute__((unused)),
+               const uintptr_t spec, io_entity_t *entity)
+{
+       int result = IO_FAIL;
+       long sh_result = -1;
+       const io_file_spec_t *file_spec = (const io_file_spec_t *)spec;
+
+       assert(file_spec != NULL);
+       assert(entity != NULL);
+
+       sh_result = semihosting_file_open(file_spec->path, file_spec->mode);
+
+       if (sh_result > 0) {
+               entity->info = (uintptr_t)sh_result;
+               result = IO_SUCCESS;
+       } else {
+               result = IO_FAIL;
+       }
+       return result;
+}
+
+
+/* Seek to a particular file offset on the semi-hosting device */
+static int sh_file_seek(io_entity_t *entity, int mode, ssize_t offset)
+{
+       int result = IO_FAIL;
+       long file_handle, sh_result;
+
+       assert(entity != NULL);
+
+       file_handle = (long)entity->info;
+
+       sh_result = semihosting_file_seek(file_handle, offset);
+
+       result = (sh_result == 0) ? IO_SUCCESS : IO_FAIL;
+
+       return result;
+}
+
+
+/* Return the size of a file on the semi-hosting device */
+static int sh_file_len(io_entity_t *entity, size_t *length)
+{
+       int result = IO_FAIL;
+
+       assert(entity != NULL);
+       assert(length != NULL);
+
+       long sh_handle = (long)entity->info;
+       long sh_result = semihosting_file_length(sh_handle);
+
+       if (sh_result >= 0) {
+               result = IO_SUCCESS;
+               *length = (size_t)sh_result;
+       }
+
+       return result;
+}
+
+
+/* Read data from a file on the semi-hosting device */
+static int sh_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
+               size_t *length_read)
+{
+       int result = IO_FAIL;
+       long sh_result = -1;
+       size_t bytes = length;
+       long file_handle;
+
+       assert(entity != NULL);
+       assert(buffer != (uintptr_t)NULL);
+       assert(length_read != NULL);
+
+       file_handle = (long)entity->info;
+
+       sh_result = semihosting_file_read(file_handle, &bytes, buffer);
+
+       if (sh_result >= 0) {
+               *length_read = (bytes != length) ? bytes : length;
+               result = IO_SUCCESS;
+       } else
+               result = IO_FAIL;
+
+       return result;
+}
+
+
+/* Write data to a file on the semi-hosting device */
+static int sh_file_write(io_entity_t *entity, const uintptr_t buffer,
+               size_t length, size_t *length_written)
+{
+       int result = IO_FAIL;
+       long sh_result = -1;
+       long file_handle;
+       size_t bytes = length;
+
+       assert(entity != NULL);
+       assert(buffer != (uintptr_t)NULL);
+       assert(length_written != NULL);
+
+       file_handle = (long)entity->info;
+
+       sh_result = semihosting_file_write(file_handle, &bytes, buffer);
+
+       if (sh_result >= 0) {
+               *length_written = sh_result;
+               result = IO_SUCCESS;
+       } else
+               result = IO_FAIL;
+
+       return result;
+}
+
+
+/* Close a file on the semi-hosting device */
+static int sh_file_close(io_entity_t *entity)
+{
+       int result = IO_FAIL;
+       long sh_result = -1;
+       long file_handle;
+
+       assert(entity != NULL);
+
+       file_handle = (long)entity->info;
+
+       sh_result = semihosting_file_close(file_handle);
+
+       result = (sh_result >= 0) ? IO_SUCCESS : IO_FAIL;
+
+       return result;
+}
+
+
+/* Exported functions */
+
+/* Register the semi-hosting driver with the IO abstraction */
+int register_io_dev_sh(const io_dev_connector_t **dev_con)
+{
+       int result = IO_FAIL;
+       assert(dev_con != NULL);
+
+       result = io_register_device(&sh_dev_info);
+       if (result == IO_SUCCESS)
+               *dev_con = &sh_dev_connector;
+
+       return result;
+}
diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c
new file mode 100644 (file)
index 0000000..a3a8186
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <io_driver.h>
+#include <io_storage.h>
+#include <platform_def.h>
+#include <stddef.h>
+
+
+/* Storage for a fixed maximum number of IO entities, definable by platform */
+static io_entity_t entity_pool[MAX_IO_HANDLES];
+
+/* Simple way of tracking used storage - each entry is NULL or a pointer to an
+ * entity */
+static io_entity_t *entity_map[MAX_IO_HANDLES];
+
+/* Track number of allocated entities */
+static unsigned int entity_count;
+
+/* Array of fixed maximum of registered devices, definable by platform */
+static const io_dev_info_t *devices[MAX_IO_DEVICES];
+
+/* Number of currently registered devices */
+static unsigned int dev_count;
+
+
+#if DEBUG      /* Extra validation functions only used in debug builds */
+
+/* Return a boolean value indicating whether a device connector is valid */
+static int is_valid_dev_connector(const io_dev_connector_t *dev_con)
+{
+       int result = (dev_con != NULL) && (dev_con->dev_open != NULL);
+       return result;
+}
+
+
+/* Return a boolean value indicating whether a device handle is valid */
+static int is_valid_dev(const uintptr_t dev_handle)
+{
+       const io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
+       int result = (dev != NULL) && (dev->funcs != NULL) &&
+                       (dev->funcs->type != NULL) &&
+                       (dev->funcs->type() < IO_TYPE_MAX);
+       return result;
+}
+
+
+/* Return a boolean value indicating whether an IO entity is valid */
+static int is_valid_entity(const uintptr_t handle)
+{
+       const io_entity_t *entity = (io_entity_t *)handle;
+       int result = (entity != NULL) &&
+                       (is_valid_dev((uintptr_t)entity->dev_handle));
+       return result;
+}
+
+
+/* Return a boolean value indicating whether a seek mode is valid */
+static int is_valid_seek_mode(io_seek_mode_t mode)
+{
+       return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX));
+}
+
+#endif /* End of debug-only validation functions */
+
+
+/* Open a connection to a specific device */
+static int dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
+               io_dev_info_t **dev_info)
+{
+       int result = IO_FAIL;
+       assert(dev_info != NULL);
+       assert(is_valid_dev_connector(dev_con));
+
+       result = dev_con->dev_open(dev_spec, dev_info);
+       return result;
+}
+
+
+/* Set a handle to track an entity */
+static void set_handle(uintptr_t *handle, io_entity_t *entity)
+{
+       assert(handle != NULL);
+       *handle = (uintptr_t)entity;
+}
+
+
+/* Locate an entity in the pool, specified by address */
+static int find_first_entity(const io_entity_t *entity, unsigned int *index_out)
+{
+       int result = IO_FAIL;
+       for (int index = 0; index < MAX_IO_HANDLES; ++index) {
+               if (entity_map[index] == entity) {
+                       result = IO_SUCCESS;
+                       *index_out = index;
+                       break;
+               }
+       }
+       return result;
+}
+
+
+/* Allocate an entity from the pool and return a pointer to it */
+static int allocate_entity(io_entity_t **entity)
+{
+       int result = IO_FAIL;
+       assert(entity != NULL);
+
+       if (entity_count < MAX_IO_HANDLES) {
+               unsigned int index = 0;
+               result = find_first_entity(NULL, &index);
+               assert(result == IO_SUCCESS);
+               *entity = entity_map[index] = &entity_pool[index];
+               ++entity_count;
+       } else
+               result = IO_RESOURCES_EXHAUSTED;
+
+       return result;
+}
+
+
+/* Release an entity back to the pool */
+static int free_entity(const io_entity_t *entity)
+{
+       int result = IO_FAIL;
+       unsigned int index = 0;
+       assert(entity != NULL);
+
+       result = find_first_entity(entity, &index);
+       if (result ==  IO_SUCCESS) {
+               entity_map[index] = NULL;
+               --entity_count;
+       }
+
+       return result;
+}
+
+
+/* Exported API */
+
+/* Register a device driver */
+int io_register_device(const io_dev_info_t *dev_info)
+{
+       int result = IO_FAIL;
+       assert(dev_info != NULL);
+
+       if (dev_count < MAX_IO_DEVICES) {
+               devices[dev_count] = dev_info;
+               dev_count++;
+               result = IO_SUCCESS;
+       } else {
+               result = IO_RESOURCES_EXHAUSTED;
+       }
+
+       return result;
+}
+
+
+/* Open a connection to an IO device */
+int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
+               uintptr_t *handle)
+{
+       int result = IO_FAIL;
+       assert(handle != NULL);
+
+       result = dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
+       return result;
+}
+
+
+/* Initialise an IO device explicitly - to permit lazy initialisation or
+ * re-initialisation */
+int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params)
+{
+       int result = IO_FAIL;
+       assert(dev_handle != (uintptr_t)NULL);
+       assert(is_valid_dev(dev_handle));
+
+       io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
+
+       if (dev->funcs->dev_init != NULL) {
+               result = dev->funcs->dev_init(dev, init_params);
+       } else {
+               /* Absence of registered function implies NOP here */
+               result = IO_SUCCESS;
+       }
+       return result;
+}
+
+
+/* TODO: Consider whether an explicit "shutdown" API should be included */
+
+/* Close a connection to a device */
+int io_dev_close(uintptr_t dev_handle)
+{
+       int result = IO_FAIL;
+       assert(dev_handle != (uintptr_t)NULL);
+       assert(is_valid_dev(dev_handle));
+
+       io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
+
+       if (dev->funcs->dev_close != NULL) {
+               result = dev->funcs->dev_close(dev);
+       } else {
+               /* Absence of registered function implies NOP here */
+               result = IO_SUCCESS;
+       }
+
+       return result;
+}
+
+
+/* Synchronous operations */
+
+
+/* Open an IO entity */
+int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle)
+{
+       int result = IO_FAIL;
+       assert((spec != (uintptr_t)NULL) && (handle != NULL));
+       assert(is_valid_dev(dev_handle));
+
+       io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
+       io_entity_t *entity;
+
+       result = allocate_entity(&entity);
+
+       if (result == IO_SUCCESS) {
+               assert(dev->funcs->open != NULL);
+               result = dev->funcs->open(dev, spec, entity);
+
+               if (result == IO_SUCCESS) {
+                       entity->dev_handle = dev;
+                       set_handle(handle, entity);
+               } else
+                       free_entity(entity);
+       }
+       return result;
+}
+
+
+/* Seek to a specific position in an IO entity */
+int io_seek(uintptr_t handle, io_seek_mode_t mode, ssize_t offset)
+{
+       int result = IO_FAIL;
+       assert(is_valid_entity(handle) && is_valid_seek_mode(mode));
+
+       io_entity_t *entity = (io_entity_t *)handle;
+
+       io_dev_info_t *dev = entity->dev_handle;
+
+       if (dev->funcs->seek != NULL)
+               result = dev->funcs->seek(entity, mode, offset);
+       else
+               result = IO_NOT_SUPPORTED;
+
+       return result;
+}
+
+
+/* Determine the length of an IO entity */
+int io_size(uintptr_t handle, size_t *length)
+{
+       int result = IO_FAIL;
+       assert(is_valid_entity(handle) && (length != NULL));
+
+       io_entity_t *entity = (io_entity_t *)handle;
+
+       io_dev_info_t *dev = entity->dev_handle;
+
+       if (dev->funcs->size != NULL)
+               result = dev->funcs->size(entity, length);
+       else
+               result = IO_NOT_SUPPORTED;
+
+       return result;
+}
+
+
+/* Read data from an IO entity */
+int io_read(uintptr_t handle,
+               uintptr_t buffer,
+               size_t length,
+               size_t *length_read)
+{
+       int result = IO_FAIL;
+       assert(is_valid_entity(handle) && (buffer != (uintptr_t)NULL));
+
+       io_entity_t *entity = (io_entity_t *)handle;
+
+       io_dev_info_t *dev = entity->dev_handle;
+
+       if (dev->funcs->read != NULL)
+               result = dev->funcs->read(entity, buffer, length, length_read);
+       else
+               result = IO_NOT_SUPPORTED;
+
+       return result;
+}
+
+
+/* Write data to an IO entity */
+int io_write(uintptr_t handle,
+               const uintptr_t buffer,
+               size_t length,
+               size_t *length_written)
+{
+       int result = IO_FAIL;
+       assert(is_valid_entity(handle) && (buffer != (uintptr_t)NULL));
+
+       io_entity_t *entity = (io_entity_t *)handle;
+
+       io_dev_info_t *dev = entity->dev_handle;
+
+       if (dev->funcs->write != NULL) {
+               result = dev->funcs->write(entity, buffer, length,
+                               length_written);
+       } else
+               result = IO_NOT_SUPPORTED;
+
+       return result;
+}
+
+
+/* Close an IO entity */
+int io_close(uintptr_t handle)
+{
+       int result = IO_FAIL;
+       assert(is_valid_entity(handle));
+
+       io_entity_t *entity = (io_entity_t *)handle;
+
+       io_dev_info_t *dev = entity->dev_handle;
+
+       if (dev->funcs->close != NULL)
+               result = dev->funcs->close(entity);
+       else {
+               /* Absence of registered function implies NOP here */
+               result = IO_SUCCESS;
+       }
+       /* Ignore improbable free_entity failure */
+       (void)free_entity(entity);
+
+       return result;
+}
diff --git a/fdts/fvp-base-gicv2-psci.dtb b/fdts/fvp-base-gicv2-psci.dtb
new file mode 100644 (file)
index 0000000..b8a31ce
Binary files /dev/null and b/fdts/fvp-base-gicv2-psci.dtb differ
diff --git a/fdts/fvp-base-gicv2-psci.dts b/fdts/fvp-base-gicv2-psci.dts
new file mode 100644 (file)
index 0000000..c1c9efb
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+};
+
+/ {
+       model = "FVP Base";
+       compatible = "arm,vfp-base", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+       };
+
+       psci {
+               compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+               method = "smc";
+               cpu_suspend = <0xc4000001>;
+               cpu_off = <0x84000002>;
+               cpu_on = <0xc4000003>;
+               sys_poweroff = <0x84000008>;
+               sys_reset = <0x84000009>;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+                               core2 {
+                                       cpu = <&CPU2>;
+                               };
+                               core3 {
+                                       cpu = <&CPU3>;
+                               };
+                       };
+
+                       cluster1 {
+                               core0 {
+                                       cpu = <&CPU4>;
+                               };
+                               core1 {
+                                       cpu = <&CPU5>;
+                               };
+                               core2 {
+                                       cpu = <&CPU6>;
+                               };
+                               core3 {
+                                       cpu = <&CPU7>;
+                               };
+                       };
+               };
+
+               idle-states {
+                       entry-method = "arm,psci";
+
+                       CPU_SLEEP_0: cpu-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x0010000>;
+                               entry-latency-us = <40>;
+                               exit-latency-us = <100>;
+                               min-residency-us = <150>;
+                       };
+
+                       CLUSTER_SLEEP_0: cluster-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x1010000>;
+                               entry-latency-us = <500>;
+                               exit-latency-us = <1000>;
+                               min-residency-us = <2500>;
+                       };
+               };
+
+               CPU0:cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU1:cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU2:cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU3:cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU4:cpu@100 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x100>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU5:cpu@101 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x101>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU6:cpu@102 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x102>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU7:cpu@103 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x103>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x7F000000>,
+                     <0x00000008 0x80000000 0 0x80000000>;
+       };
+
+       gic: interrupt-controller@2f000000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0x0 0x2f000000 0 0x10000>,
+                     <0x0 0x2c000000 0 0x2000>,
+                     <0x0 0x2c010000 0 0x2000>,
+                     <0x0 0x2c02F000 0 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xff01>,
+                            <1 14 0xff01>,
+                            <1 11 0xff01>,
+                            <1 10 0xff01>;
+               clock-frequency = <100000000>;
+       };
+
+       timer@2a810000 {
+                       compatible = "arm,armv7-timer-mem";
+                       reg = <0x0 0x2a810000 0x0 0x10000>;
+                       clock-frequency = <100000000>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       frame@2a830000 {
+                               frame-number = <1>;
+                               interrupts = <0 26 4>;
+                               reg = <0x0 0x2a830000 0x0 0x10000>;
+                       };
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 60 4>,
+                            <0 61 4>,
+                            <0 62 4>,
+                            <0 63 4>;
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0  0 4>,
+                               <0 0  1 &gic 0  1 4>,
+                               <0 0  2 &gic 0  2 4>,
+                               <0 0  3 &gic 0  3 4>,
+                               <0 0  4 &gic 0  4 4>,
+                               <0 0  5 &gic 0  5 4>,
+                               <0 0  6 &gic 0  6 4>,
+                               <0 0  7 &gic 0  7 4>,
+                               <0 0  8 &gic 0  8 4>,
+                               <0 0  9 &gic 0  9 4>,
+                               <0 0 10 &gic 0 10 4>,
+                               <0 0 11 &gic 0 11 4>,
+                               <0 0 12 &gic 0 12 4>,
+                               <0 0 13 &gic 0 13 4>,
+                               <0 0 14 &gic 0 14 4>,
+                               <0 0 15 &gic 0 15 4>,
+                               <0 0 16 &gic 0 16 4>,
+                               <0 0 17 &gic 0 17 4>,
+                               <0 0 18 &gic 0 18 4>,
+                               <0 0 19 &gic 0 19 4>,
+                               <0 0 20 &gic 0 20 4>,
+                               <0 0 21 &gic 0 21 4>,
+                               <0 0 22 &gic 0 22 4>,
+                               <0 0 23 &gic 0 23 4>,
+                               <0 0 24 &gic 0 24 4>,
+                               <0 0 25 &gic 0 25 4>,
+                               <0 0 26 &gic 0 26 4>,
+                               <0 0 27 &gic 0 27 4>,
+                               <0 0 28 &gic 0 28 4>,
+                               <0 0 29 &gic 0 29 4>,
+                               <0 0 30 &gic 0 30 4>,
+                               <0 0 31 &gic 0 31 4>,
+                               <0 0 32 &gic 0 32 4>,
+                               <0 0 33 &gic 0 33 4>,
+                               <0 0 34 &gic 0 34 4>,
+                               <0 0 35 &gic 0 35 4>,
+                               <0 0 36 &gic 0 36 4>,
+                               <0 0 37 &gic 0 37 4>,
+                               <0 0 38 &gic 0 38 4>,
+                               <0 0 39 &gic 0 39 4>,
+                               <0 0 40 &gic 0 40 4>,
+                               <0 0 41 &gic 0 41 4>,
+                               <0 0 42 &gic 0 42 4>;
+
+               /include/ "rtsm_ve-motherboard.dtsi"
+       };
+
+       panels {
+               panel@0 {
+                       compatible      = "panel";
+                       mode            = "XVGA";
+                       refresh         = <60>;
+                       xres            = <1024>;
+                       yres            = <768>;
+                       pixclock        = <15748>;
+                       left_margin     = <152>;
+                       right_margin    = <48>;
+                       upper_margin    = <23>;
+                       lower_margin    = <3>;
+                       hsync_len       = <104>;
+                       vsync_len       = <4>;
+                       sync            = <0>;
+                       vmode           = "FB_VMODE_NONINTERLACED";
+                       tim2            = "TIM2_BCD", "TIM2_IPC";
+                       cntl            = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
+                       caps            = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
+                       bpp             = <16>;
+               };
+       };
+};
diff --git a/fdts/fvp-base-gicv2legacy-psci.dtb b/fdts/fvp-base-gicv2legacy-psci.dtb
new file mode 100644 (file)
index 0000000..4270623
Binary files /dev/null and b/fdts/fvp-base-gicv2legacy-psci.dtb differ
diff --git a/fdts/fvp-base-gicv2legacy-psci.dts b/fdts/fvp-base-gicv2legacy-psci.dts
new file mode 100644 (file)
index 0000000..7bd5ea2
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+};
+
+/ {
+       model = "FVP Base";
+       compatible = "arm,vfp-base", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+       };
+
+       psci {
+               compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+               method = "smc";
+               cpu_suspend = <0xc4000001>;
+               cpu_off = <0x84000002>;
+               cpu_on = <0xc4000003>;
+               sys_poweroff = <0x84000008>;
+               sys_reset = <0x84000009>;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+                               core2 {
+                                       cpu = <&CPU2>;
+                               };
+                               core3 {
+                                       cpu = <&CPU3>;
+                               };
+                       };
+
+                       cluster1 {
+                               core0 {
+                                       cpu = <&CPU4>;
+                               };
+                               core1 {
+                                       cpu = <&CPU5>;
+                               };
+                               core2 {
+                                       cpu = <&CPU6>;
+                               };
+                               core3 {
+                                       cpu = <&CPU7>;
+                               };
+                       };
+               };
+
+               idle-states {
+                       entry-method = "arm,psci";
+
+                       CPU_SLEEP_0: cpu-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x0010000>;
+                               entry-latency-us = <40>;
+                               exit-latency-us = <100>;
+                               min-residency-us = <150>;
+                       };
+
+                       CLUSTER_SLEEP_0: cluster-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x1010000>;
+                               entry-latency-us = <500>;
+                               exit-latency-us = <1000>;
+                               min-residency-us = <2500>;
+                       };
+               };
+
+               CPU0:cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU1:cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU2:cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU3:cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU4:cpu@100 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x100>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU5:cpu@101 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x101>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU6:cpu@102 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x102>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU7:cpu@103 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x103>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x7F000000>,
+                     <0x00000008 0x80000000 0 0x80000000>;
+       };
+
+       gic: interrupt-controller@2c001000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0x0 0x2c001000 0 0x1000>,
+                     <0x0 0x2c002000 0 0x1000>,
+                     <0x0 0x2c004000 0 0x2000>,
+                     <0x0 0x2c006000 0 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xff01>,
+                            <1 14 0xff01>,
+                            <1 11 0xff01>,
+                            <1 10 0xff01>;
+               clock-frequency = <100000000>;
+       };
+
+       timer@2a810000 {
+                       compatible = "arm,armv7-timer-mem";
+                       reg = <0x0 0x2a810000 0x0 0x10000>;
+                       clock-frequency = <100000000>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       frame@2a830000 {
+                               frame-number = <1>;
+                               interrupts = <0 26 4>;
+                               reg = <0x0 0x2a830000 0x0 0x10000>;
+                       };
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 60 4>,
+                            <0 61 4>,
+                            <0 62 4>,
+                            <0 63 4>;
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0  0 4>,
+                               <0 0  1 &gic 0  1 4>,
+                               <0 0  2 &gic 0  2 4>,
+                               <0 0  3 &gic 0  3 4>,
+                               <0 0  4 &gic 0  4 4>,
+                               <0 0  5 &gic 0  5 4>,
+                               <0 0  6 &gic 0  6 4>,
+                               <0 0  7 &gic 0  7 4>,
+                               <0 0  8 &gic 0  8 4>,
+                               <0 0  9 &gic 0  9 4>,
+                               <0 0 10 &gic 0 10 4>,
+                               <0 0 11 &gic 0 11 4>,
+                               <0 0 12 &gic 0 12 4>,
+                               <0 0 13 &gic 0 13 4>,
+                               <0 0 14 &gic 0 14 4>,
+                               <0 0 15 &gic 0 15 4>,
+                               <0 0 16 &gic 0 16 4>,
+                               <0 0 17 &gic 0 17 4>,
+                               <0 0 18 &gic 0 18 4>,
+                               <0 0 19 &gic 0 19 4>,
+                               <0 0 20 &gic 0 20 4>,
+                               <0 0 21 &gic 0 21 4>,
+                               <0 0 22 &gic 0 22 4>,
+                               <0 0 23 &gic 0 23 4>,
+                               <0 0 24 &gic 0 24 4>,
+                               <0 0 25 &gic 0 25 4>,
+                               <0 0 26 &gic 0 26 4>,
+                               <0 0 27 &gic 0 27 4>,
+                               <0 0 28 &gic 0 28 4>,
+                               <0 0 29 &gic 0 29 4>,
+                               <0 0 30 &gic 0 30 4>,
+                               <0 0 31 &gic 0 31 4>,
+                               <0 0 32 &gic 0 32 4>,
+                               <0 0 33 &gic 0 33 4>,
+                               <0 0 34 &gic 0 34 4>,
+                               <0 0 35 &gic 0 35 4>,
+                               <0 0 36 &gic 0 36 4>,
+                               <0 0 37 &gic 0 37 4>,
+                               <0 0 38 &gic 0 38 4>,
+                               <0 0 39 &gic 0 39 4>,
+                               <0 0 40 &gic 0 40 4>,
+                               <0 0 41 &gic 0 41 4>,
+                               <0 0 42 &gic 0 42 4>;
+
+               /include/ "rtsm_ve-motherboard.dtsi"
+       };
+
+       panels {
+               panel@0 {
+                       compatible      = "panel";
+                       mode            = "XVGA";
+                       refresh         = <60>;
+                       xres            = <1024>;
+                       yres            = <768>;
+                       pixclock        = <15748>;
+                       left_margin     = <152>;
+                       right_margin    = <48>;
+                       upper_margin    = <23>;
+                       lower_margin    = <3>;
+                       hsync_len       = <104>;
+                       vsync_len       = <4>;
+                       sync            = <0>;
+                       vmode           = "FB_VMODE_NONINTERLACED";
+                       tim2            = "TIM2_BCD", "TIM2_IPC";
+                       cntl            = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
+                       caps            = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
+                       bpp             = <16>;
+               };
+       };
+};
diff --git a/fdts/fvp-base-gicv3-psci.dtb b/fdts/fvp-base-gicv3-psci.dtb
new file mode 100644 (file)
index 0000000..27c3f93
Binary files /dev/null and b/fdts/fvp-base-gicv3-psci.dtb differ
diff --git a/fdts/fvp-base-gicv3-psci.dts b/fdts/fvp-base-gicv3-psci.dts
new file mode 100644 (file)
index 0000000..32e577a
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+};
+
+/ {
+       model = "FVP Base";
+       compatible = "arm,vfp-base", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+       };
+
+       psci {
+               compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+               method = "smc";
+               cpu_suspend = <0xc4000001>;
+               cpu_off = <0x84000002>;
+               cpu_on = <0xc4000003>;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+                               core2 {
+                                       cpu = <&CPU2>;
+                               };
+                               core3 {
+                                       cpu = <&CPU3>;
+                               };
+                       };
+
+                       cluster1 {
+                               core0 {
+                                       cpu = <&CPU4>;
+                               };
+                               core1 {
+                                       cpu = <&CPU5>;
+                               };
+                               core2 {
+                                       cpu = <&CPU6>;
+                               };
+                               core3 {
+                                       cpu = <&CPU7>;
+                               };
+                       };
+               };
+
+               idle-states {
+                       entry-method = "arm,psci";
+
+                       CPU_SLEEP_0: cpu-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x0010000>;
+                               entry-latency-us = <40>;
+                               exit-latency-us = <100>;
+                               min-residency-us = <150>;
+                       };
+
+                       CLUSTER_SLEEP_0: cluster-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x1010000>;
+                               entry-latency-us = <500>;
+                               exit-latency-us = <1000>;
+                               min-residency-us = <2500>;
+                       };
+               };
+
+               CPU0:cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU1:cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU2:cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU3:cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU4:cpu@100 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x100>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU5:cpu@101 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x101>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU6:cpu@102 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x102>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU7:cpu@103 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x103>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x7F000000>,
+                     <0x00000008 0x80000000 0 0x80000000>;
+       };
+
+       gic: interrupt-controller@2f000000 {
+               compatible = "arm,gic-v3";
+               #interrupt-cells = <3>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+               interrupt-controller;
+               reg = <0x0 0x2f000000 0 0x10000>,       // GICD
+                     <0x0 0x2f100000 0 0x200000>,      // GICR
+                     <0x0 0x2c000000 0 0x2000>,        // GICC
+                     <0x0 0x2c010000 0 0x2000>,        // GICH
+                     <0x0 0x2c02f000 0 0x2000>;        // GICV
+               interrupts = <1 9 4>;
+
+               its: its@2f020000 {
+                       compatible = "arm,gic-v3-its";
+                       msi-controller;
+                       reg = <0x0 0x2f020000 0x0 0x20000>; // GITS
+               };
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xff01>,
+                            <1 14 0xff01>,
+                            <1 11 0xff01>,
+                            <1 10 0xff01>;
+               clock-frequency = <100000000>;
+       };
+
+       timer@2a810000 {
+                       compatible = "arm,armv7-timer-mem";
+                       reg = <0x0 0x2a810000 0x0 0x10000>;
+                       clock-frequency = <100000000>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       frame@2a830000 {
+                               frame-number = <1>;
+                               interrupts = <0 26 4>;
+                               reg = <0x0 0x2a830000 0x0 0x10000>;
+                       };
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 60 4>,
+                            <0 61 4>,
+                            <0 62 4>,
+                            <0 63 4>;
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0 0 0  0 4>,
+                               <0 0  1 &gic 0 0 0  1 4>,
+                               <0 0  2 &gic 0 0 0  2 4>,
+                               <0 0  3 &gic 0 0 0  3 4>,
+                               <0 0  4 &gic 0 0 0  4 4>,
+                               <0 0  5 &gic 0 0 0  5 4>,
+                               <0 0  6 &gic 0 0 0  6 4>,
+                               <0 0  7 &gic 0 0 0  7 4>,
+                               <0 0  8 &gic 0 0 0  8 4>,
+                               <0 0  9 &gic 0 0 0  9 4>,
+                               <0 0 10 &gic 0 0 0 10 4>,
+                               <0 0 11 &gic 0 0 0 11 4>,
+                               <0 0 12 &gic 0 0 0 12 4>,
+                               <0 0 13 &gic 0 0 0 13 4>,
+                               <0 0 14 &gic 0 0 0 14 4>,
+                               <0 0 15 &gic 0 0 0 15 4>,
+                               <0 0 16 &gic 0 0 0 16 4>,
+                               <0 0 17 &gic 0 0 0 17 4>,
+                               <0 0 18 &gic 0 0 0 18 4>,
+                               <0 0 19 &gic 0 0 0 19 4>,
+                               <0 0 20 &gic 0 0 0 20 4>,
+                               <0 0 21 &gic 0 0 0 21 4>,
+                               <0 0 22 &gic 0 0 0 22 4>,
+                               <0 0 23 &gic 0 0 0 23 4>,
+                               <0 0 24 &gic 0 0 0 24 4>,
+                               <0 0 25 &gic 0 0 0 25 4>,
+                               <0 0 26 &gic 0 0 0 26 4>,
+                               <0 0 27 &gic 0 0 0 27 4>,
+                               <0 0 28 &gic 0 0 0 28 4>,
+                               <0 0 29 &gic 0 0 0 29 4>,
+                               <0 0 30 &gic 0 0 0 30 4>,
+                               <0 0 31 &gic 0 0 0 31 4>,
+                               <0 0 32 &gic 0 0 0 32 4>,
+                               <0 0 33 &gic 0 0 0 33 4>,
+                               <0 0 34 &gic 0 0 0 34 4>,
+                               <0 0 35 &gic 0 0 0 35 4>,
+                               <0 0 36 &gic 0 0 0 36 4>,
+                               <0 0 37 &gic 0 0 0 37 4>,
+                               <0 0 38 &gic 0 0 0 38 4>,
+                               <0 0 39 &gic 0 0 0 39 4>,
+                               <0 0 40 &gic 0 0 0 40 4>,
+                               <0 0 41 &gic 0 0 0 41 4>,
+                               <0 0 42 &gic 0 0 0 42 4>;
+
+               /include/ "rtsm_ve-motherboard-no_psci.dtsi"
+       };
+
+       panels {
+               panel@0 {
+                       compatible      = "panel";
+                       mode            = "XVGA";
+                       refresh         = <60>;
+                       xres            = <1024>;
+                       yres            = <768>;
+                       pixclock        = <15748>;
+                       left_margin     = <152>;
+                       right_margin    = <48>;
+                       upper_margin    = <23>;
+                       lower_margin    = <3>;
+                       hsync_len       = <104>;
+                       vsync_len       = <4>;
+                       sync            = <0>;
+                       vmode           = "FB_VMODE_NONINTERLACED";
+                       tim2            = "TIM2_BCD", "TIM2_IPC";
+                       cntl            = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
+                       caps            = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
+                       bpp             = <16>;
+               };
+       };
+};
diff --git a/fdts/fvp-foundation-gicv2-psci.dtb b/fdts/fvp-foundation-gicv2-psci.dtb
new file mode 100644 (file)
index 0000000..5b92e5e
Binary files /dev/null and b/fdts/fvp-foundation-gicv2-psci.dtb differ
diff --git a/fdts/fvp-foundation-gicv2-psci.dts b/fdts/fvp-foundation-gicv2-psci.dts
new file mode 100644 (file)
index 0000000..c04d535
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2013-2014, 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 the 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.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+};
+
+/ {
+       model = "FVP Foundation";
+       compatible = "arm,fvp-base", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+       };
+
+       psci {
+               compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+               method = "smc";
+               cpu_suspend = <0xc4000001>;
+               cpu_off = <0x84000002>;
+               cpu_on = <0xc4000003>;
+               sys_poweroff = <0x84000008>;
+               sys_reset = <0x84000009>;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+                               core2 {
+                                       cpu = <&CPU2>;
+                               };
+                               core3 {
+                                       cpu = <&CPU3>;
+                               };
+                       };
+               };
+
+               idle-states {
+                       entry-method = "arm,psci";
+
+                       CPU_SLEEP_0: cpu-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x0010000>;
+                               entry-latency-us = <40>;
+                               exit-latency-us = <100>;
+                               min-residency-us = <150>;
+                       };
+
+                       CLUSTER_SLEEP_0: cluster-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x1010000>;
+                               entry-latency-us = <500>;
+                               exit-latency-us = <1000>;
+                               min-residency-us = <2500>;
+                       };
+               };
+
+               CPU0:cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU1:cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU2:cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU3:cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x7F000000>,
+                     <0x00000008 0x80000000 0 0x80000000>;
+       };
+
+       gic: interrupt-controller@2f000000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0x0 0x2f000000 0 0x10000>,
+                     <0x0 0x2c000000 0 0x2000>,
+                     <0x0 0x2c010000 0 0x2000>,
+                     <0x0 0x2c02F000 0 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xff01>,
+                            <1 14 0xff01>,
+                            <1 11 0xff01>,
+                            <1 10 0xff01>;
+               clock-frequency = <100000000>;
+       };
+
+       timer@2a810000 {
+                       compatible = "arm,armv7-timer-mem";
+                       reg = <0x0 0x2a810000 0x0 0x10000>;
+                       clock-frequency = <100000000>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       frame@2a830000 {
+                               frame-number = <1>;
+                               interrupts = <0 26 4>;
+                               reg = <0x0 0x2a830000 0x0 0x10000>;
+                       };
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 60 4>,
+                            <0 61 4>,
+                            <0 62 4>,
+                            <0 63 4>;
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0  0 4>,
+                               <0 0  1 &gic 0  1 4>,
+                               <0 0  2 &gic 0  2 4>,
+                               <0 0  3 &gic 0  3 4>,
+                               <0 0  4 &gic 0  4 4>,
+                               <0 0  5 &gic 0  5 4>,
+                               <0 0  6 &gic 0  6 4>,
+                               <0 0  7 &gic 0  7 4>,
+                               <0 0  8 &gic 0  8 4>,
+                               <0 0  9 &gic 0  9 4>,
+                               <0 0 10 &gic 0 10 4>,
+                               <0 0 11 &gic 0 11 4>,
+                               <0 0 12 &gic 0 12 4>,
+                               <0 0 13 &gic 0 13 4>,
+                               <0 0 14 &gic 0 14 4>,
+                               <0 0 15 &gic 0 15 4>,
+                               <0 0 16 &gic 0 16 4>,
+                               <0 0 17 &gic 0 17 4>,
+                               <0 0 18 &gic 0 18 4>,
+                               <0 0 19 &gic 0 19 4>,
+                               <0 0 20 &gic 0 20 4>,
+                               <0 0 21 &gic 0 21 4>,
+                               <0 0 22 &gic 0 22 4>,
+                               <0 0 23 &gic 0 23 4>,
+                               <0 0 24 &gic 0 24 4>,
+                               <0 0 25 &gic 0 25 4>,
+                               <0 0 26 &gic 0 26 4>,
+                               <0 0 27 &gic 0 27 4>,
+                               <0 0 28 &gic 0 28 4>,
+                               <0 0 29 &gic 0 29 4>,
+                               <0 0 30 &gic 0 30 4>,
+                               <0 0 31 &gic 0 31 4>,
+                               <0 0 32 &gic 0 32 4>,
+                               <0 0 33 &gic 0 33 4>,
+                               <0 0 34 &gic 0 34 4>,
+                               <0 0 35 &gic 0 35 4>,
+                               <0 0 36 &gic 0 36 4>,
+                               <0 0 37 &gic 0 37 4>,
+                               <0 0 38 &gic 0 38 4>,
+                               <0 0 39 &gic 0 39 4>,
+                               <0 0 40 &gic 0 40 4>,
+                               <0 0 41 &gic 0 41 4>,
+                               <0 0 42 &gic 0 42 4>;
+
+               /include/ "fvp-foundation-motherboard.dtsi"
+       };
+};
diff --git a/fdts/fvp-foundation-gicv2legacy-psci.dtb b/fdts/fvp-foundation-gicv2legacy-psci.dtb
new file mode 100644 (file)
index 0000000..71f6ae2
Binary files /dev/null and b/fdts/fvp-foundation-gicv2legacy-psci.dtb differ
diff --git a/fdts/fvp-foundation-gicv2legacy-psci.dts b/fdts/fvp-foundation-gicv2legacy-psci.dts
new file mode 100644 (file)
index 0000000..8dba04c
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2013-2014, 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 the 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.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+};
+
+/ {
+       model = "FVP Foundation";
+       compatible = "arm,fvp-base", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+       };
+
+       psci {
+               compatible = "arm,psci";
+               method = "smc";
+               cpu_suspend = <0xc4000001>;
+               cpu_off = <0x84000002>;
+               cpu_on = <0xc4000003>;
+               sys_poweroff = <0x84000008>;
+               sys_reset = <0x84000009>;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+                               core2 {
+                                       cpu = <&CPU2>;
+                               };
+                               core3 {
+                                       cpu = <&CPU3>;
+                               };
+                       };
+               };
+
+               idle-states {
+                       entry-method = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+
+                       CPU_SLEEP_0: cpu-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x0010000>;
+                               entry-latency-us = <40>;
+                               exit-latency-us = <100>;
+                               min-residency-us = <150>;
+                       };
+
+                       CLUSTER_SLEEP_0: cluster-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x1010000>;
+                               entry-latency-us = <500>;
+                               exit-latency-us = <1000>;
+                               min-residency-us = <2500>;
+                       };
+               };
+
+               CPU0:cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU1:cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU2:cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU3:cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x7F000000>,
+                     <0x00000008 0x80000000 0 0x80000000>;
+       };
+
+       gic: interrupt-controller@2c001000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0x0 0x2c001000 0 0x1000>,
+                     <0x0 0x2c002000 0 0x1000>,
+                     <0x0 0x2c004000 0 0x2000>,
+                     <0x0 0x2c006000 0 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xff01>,
+                            <1 14 0xff01>,
+                            <1 11 0xff01>,
+                            <1 10 0xff01>;
+               clock-frequency = <100000000>;
+       };
+
+       timer@2a810000 {
+                       compatible = "arm,armv7-timer-mem";
+                       reg = <0x0 0x2a810000 0x0 0x10000>;
+                       clock-frequency = <100000000>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       frame@2a830000 {
+                               frame-number = <1>;
+                               interrupts = <0 26 4>;
+                               reg = <0x0 0x2a830000 0x0 0x10000>;
+                       };
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 60 4>,
+                            <0 61 4>,
+                            <0 62 4>,
+                            <0 63 4>;
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0  0 4>,
+                               <0 0  1 &gic 0  1 4>,
+                               <0 0  2 &gic 0  2 4>,
+                               <0 0  3 &gic 0  3 4>,
+                               <0 0  4 &gic 0  4 4>,
+                               <0 0  5 &gic 0  5 4>,
+                               <0 0  6 &gic 0  6 4>,
+                               <0 0  7 &gic 0  7 4>,
+                               <0 0  8 &gic 0  8 4>,
+                               <0 0  9 &gic 0  9 4>,
+                               <0 0 10 &gic 0 10 4>,
+                               <0 0 11 &gic 0 11 4>,
+                               <0 0 12 &gic 0 12 4>,
+                               <0 0 13 &gic 0 13 4>,
+                               <0 0 14 &gic 0 14 4>,
+                               <0 0 15 &gic 0 15 4>,
+                               <0 0 16 &gic 0 16 4>,
+                               <0 0 17 &gic 0 17 4>,
+                               <0 0 18 &gic 0 18 4>,
+                               <0 0 19 &gic 0 19 4>,
+                               <0 0 20 &gic 0 20 4>,
+                               <0 0 21 &gic 0 21 4>,
+                               <0 0 22 &gic 0 22 4>,
+                               <0 0 23 &gic 0 23 4>,
+                               <0 0 24 &gic 0 24 4>,
+                               <0 0 25 &gic 0 25 4>,
+                               <0 0 26 &gic 0 26 4>,
+                               <0 0 27 &gic 0 27 4>,
+                               <0 0 28 &gic 0 28 4>,
+                               <0 0 29 &gic 0 29 4>,
+                               <0 0 30 &gic 0 30 4>,
+                               <0 0 31 &gic 0 31 4>,
+                               <0 0 32 &gic 0 32 4>,
+                               <0 0 33 &gic 0 33 4>,
+                               <0 0 34 &gic 0 34 4>,
+                               <0 0 35 &gic 0 35 4>,
+                               <0 0 36 &gic 0 36 4>,
+                               <0 0 37 &gic 0 37 4>,
+                               <0 0 38 &gic 0 38 4>,
+                               <0 0 39 &gic 0 39 4>,
+                               <0 0 40 &gic 0 40 4>,
+                               <0 0 41 &gic 0 41 4>,
+                               <0 0 42 &gic 0 42 4>;
+
+               /include/ "fvp-foundation-motherboard.dtsi"
+       };
+};
diff --git a/fdts/fvp-foundation-gicv3-psci.dtb b/fdts/fvp-foundation-gicv3-psci.dtb
new file mode 100644 (file)
index 0000000..d7d9e14
Binary files /dev/null and b/fdts/fvp-foundation-gicv3-psci.dtb differ
diff --git a/fdts/fvp-foundation-gicv3-psci.dts b/fdts/fvp-foundation-gicv3-psci.dts
new file mode 100644 (file)
index 0000000..48a1afc
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+};
+
+/ {
+       model = "FVP Foundation";
+       compatible = "arm,fvp-base", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+       };
+
+       psci {
+               compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+               method = "smc";
+               cpu_suspend = <0xc4000001>;
+               cpu_off = <0x84000002>;
+               cpu_on = <0xc4000003>;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+                               core2 {
+                                       cpu = <&CPU2>;
+                               };
+                               core3 {
+                                       cpu = <&CPU3>;
+                               };
+                       };
+               };
+
+               idle-states {
+                       entry-method = "arm,psci";
+
+                       CPU_SLEEP_0: cpu-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x0010000>;
+                               entry-latency-us = <40>;
+                               exit-latency-us = <100>;
+                               min-residency-us = <150>;
+                       };
+
+                       CLUSTER_SLEEP_0: cluster-sleep-0 {
+                               compatible = "arm,idle-state";
+                               entry-method-param = <0x1010000>;
+                               entry-latency-us = <500>;
+                               exit-latency-us = <1000>;
+                               min-residency-us = <2500>;
+                       };
+               };
+
+               CPU0:cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU1:cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU2:cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+
+               CPU3:cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x7F000000>,
+                     <0x00000008 0x80000000 0 0x80000000>;
+       };
+
+       gic: interrupt-controller@2f000000 {
+               compatible = "arm,gic-v3";
+               #interrupt-cells = <3>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+               interrupt-controller;
+               reg = <0x0 0x2f000000 0 0x10000>,       // GICD
+                     <0x0 0x2f100000 0 0x200000>,      // GICR
+                     <0x0 0x2c000000 0 0x2000>,        // GICC
+                     <0x0 0x2c010000 0 0x2000>,        // GICH
+                     <0x0 0x2c02f000 0 0x2000>;        // GICV
+               interrupts = <1 9 4>;
+
+               its: its@2f020000 {
+                       compatible = "arm,gic-v3-its";
+                       msi-controller;
+                       reg = <0x0 0x2f020000 0x0 0x20000>; // GITS
+               };
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xff01>,
+                            <1 14 0xff01>,
+                            <1 11 0xff01>,
+                            <1 10 0xff01>;
+               clock-frequency = <100000000>;
+       };
+
+       timer@2a810000 {
+                       compatible = "arm,armv7-timer-mem";
+                       reg = <0x0 0x2a810000 0x0 0x10000>;
+                       clock-frequency = <100000000>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       frame@2a830000 {
+                               frame-number = <1>;
+                               interrupts = <0 26 4>;
+                               reg = <0x0 0x2a830000 0x0 0x10000>;
+                       };
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 60 4>,
+                            <0 61 4>,
+                            <0 62 4>,
+                            <0 63 4>;
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0 0 0  0 4>,
+                               <0 0  1 &gic 0 0 0  1 4>,
+                               <0 0  2 &gic 0 0 0  2 4>,
+                               <0 0  3 &gic 0 0 0  3 4>,
+                               <0 0  4 &gic 0 0 0  4 4>,
+                               <0 0  5 &gic 0 0 0  5 4>,
+                               <0 0  6 &gic 0 0 0  6 4>,
+                               <0 0  7 &gic 0 0 0  7 4>,
+                               <0 0  8 &gic 0 0 0  8 4>,
+                               <0 0  9 &gic 0 0 0  9 4>,
+                               <0 0 10 &gic 0 0 0 10 4>,
+                               <0 0 11 &gic 0 0 0 11 4>,
+                               <0 0 12 &gic 0 0 0 12 4>,
+                               <0 0 13 &gic 0 0 0 13 4>,
+                               <0 0 14 &gic 0 0 0 14 4>,
+                               <0 0 15 &gic 0 0 0 15 4>,
+                               <0 0 16 &gic 0 0 0 16 4>,
+                               <0 0 17 &gic 0 0 0 17 4>,
+                               <0 0 18 &gic 0 0 0 18 4>,
+                               <0 0 19 &gic 0 0 0 19 4>,
+                               <0 0 20 &gic 0 0 0 20 4>,
+                               <0 0 21 &gic 0 0 0 21 4>,
+                               <0 0 22 &gic 0 0 0 22 4>,
+                               <0 0 23 &gic 0 0 0 23 4>,
+                               <0 0 24 &gic 0 0 0 24 4>,
+                               <0 0 25 &gic 0 0 0 25 4>,
+                               <0 0 26 &gic 0 0 0 26 4>,
+                               <0 0 27 &gic 0 0 0 27 4>,
+                               <0 0 28 &gic 0 0 0 28 4>,
+                               <0 0 29 &gic 0 0 0 29 4>,
+                               <0 0 30 &gic 0 0 0 30 4>,
+                               <0 0 31 &gic 0 0 0 31 4>,
+                               <0 0 32 &gic 0 0 0 32 4>,
+                               <0 0 33 &gic 0 0 0 33 4>,
+                               <0 0 34 &gic 0 0 0 34 4>,
+                               <0 0 35 &gic 0 0 0 35 4>,
+                               <0 0 36 &gic 0 0 0 36 4>,
+                               <0 0 37 &gic 0 0 0 37 4>,
+                               <0 0 38 &gic 0 0 0 38 4>,
+                               <0 0 39 &gic 0 0 0 39 4>,
+                               <0 0 40 &gic 0 0 0 40 4>,
+                               <0 0 41 &gic 0 0 0 41 4>,
+                               <0 0 42 &gic 0 0 0 42 4>;
+
+               /include/ "fvp-foundation-motherboard-no_psci.dtsi"
+       };
+};
diff --git a/fdts/fvp-foundation-motherboard-no_psci.dtsi b/fdts/fvp-foundation-motherboard-no_psci.dtsi
new file mode 100644 (file)
index 0000000..fd41c8a
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2013-2014, 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 the 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.
+ */
+
+       motherboard {
+               arm,v2m-memory-map = "rs1";
+               compatible = "arm,vexpress,v2m-p1", "simple-bus";
+               #address-cells = <2>; /* SMB chipselect number and offset */
+               #size-cells = <1>;
+               #interrupt-cells = <1>;
+               ranges;
+
+               ethernet@2,02000000 {
+                       compatible = "smsc,lan91c111";
+                       reg = <2 0x02000000 0x10000>;
+                       interrupts = <15>;
+               };
+
+               v2m_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "v2m:clk24mhz";
+               };
+
+               v2m_refclk1mhz: refclk1mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000>;
+                       clock-output-names = "v2m:refclk1mhz";
+               };
+
+               v2m_refclk32khz: refclk32khz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "v2m:refclk32khz";
+               };
+
+               iofpga@3,00000000 {
+                       compatible = "arm,amba-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 3 0 0x200000>;
+
+                       v2m_sysreg: sysreg@010000 {
+                               compatible = "arm,vexpress-sysreg";
+                               reg = <0x010000 0x1000>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+
+                       v2m_sysctl: sysctl@020000 {
+                               compatible = "arm,sp810", "arm,primecell";
+                               reg = <0x020000 0x1000>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
+                               clock-names = "refclk", "timclk", "apb_pclk";
+                               #clock-cells = <1>;
+                               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+                       };
+
+                       v2m_serial0: uart@090000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x090000 0x1000>;
+                               interrupts = <5>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial1: uart@0a0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0a0000 0x1000>;
+                               interrupts = <6>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial2: uart@0b0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0b0000 0x1000>;
+                               interrupts = <7>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial3: uart@0c0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0c0000 0x1000>;
+                               interrupts = <8>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       wdt@0f0000 {
+                               compatible = "arm,sp805", "arm,primecell";
+                               reg = <0x0f0000 0x1000>;
+                               interrupts = <0>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
+                               clock-names = "wdogclk", "apb_pclk";
+                       };
+
+                       v2m_timer01: timer@110000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x110000 0x1000>;
+                               interrupts = <2>;
+                               clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       v2m_timer23: timer@120000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x120000 0x1000>;
+                               interrupts = <3>;
+                               clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       rtc@170000 {
+                               compatible = "arm,pl031", "arm,primecell";
+                               reg = <0x170000 0x1000>;
+                               interrupts = <4>;
+                               clocks = <&v2m_clk24mhz>;
+                               clock-names = "apb_pclk";
+                       };
+
+                       virtio_block@0130000 {
+                               compatible = "virtio,mmio";
+                               reg = <0x130000 0x1000>;
+                               interrupts = <0x2a>;
+                       };
+               };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+
+               mcc {
+                       compatible = "arm,vexpress,config-bus", "simple-bus";
+                       arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+                       reset@0 {
+                               compatible = "arm,vexpress-reset";
+                               arm,vexpress-sysreg,func = <5 0>;
+                       };
+
+                       muxfpga@0 {
+                               compatible = "arm,vexpress-muxfpga";
+                               arm,vexpress-sysreg,func = <7 0>;
+                       };
+
+                       shutdown@0 {
+                               compatible = "arm,vexpress-shutdown";
+                               arm,vexpress-sysreg,func = <8 0>;
+                       };
+
+                       reboot@0 {
+                               compatible = "arm,vexpress-reboot";
+                               arm,vexpress-sysreg,func = <9 0>;
+                       };
+
+                       dvimode@0 {
+                               compatible = "arm,vexpress-dvimode";
+                               arm,vexpress-sysreg,func = <11 0>;
+                       };
+               };
+       };
diff --git a/fdts/fvp-foundation-motherboard.dtsi b/fdts/fvp-foundation-motherboard.dtsi
new file mode 100644 (file)
index 0000000..9d29e48
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2013-2014, 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 the 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.
+ */
+
+       motherboard {
+               arm,v2m-memory-map = "rs1";
+               compatible = "arm,vexpress,v2m-p1", "simple-bus";
+               #address-cells = <2>; /* SMB chipselect number and offset */
+               #size-cells = <1>;
+               #interrupt-cells = <1>;
+               ranges;
+
+               ethernet@2,02000000 {
+                       compatible = "smsc,lan91c111";
+                       reg = <2 0x02000000 0x10000>;
+                       interrupts = <15>;
+               };
+
+               v2m_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "v2m:clk24mhz";
+               };
+
+               v2m_refclk1mhz: refclk1mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000>;
+                       clock-output-names = "v2m:refclk1mhz";
+               };
+
+               v2m_refclk32khz: refclk32khz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "v2m:refclk32khz";
+               };
+
+               iofpga@3,00000000 {
+                       compatible = "arm,amba-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 3 0 0x200000>;
+
+                       v2m_sysreg: sysreg@010000 {
+                               compatible = "arm,vexpress-sysreg";
+                               reg = <0x010000 0x1000>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+
+                       v2m_sysctl: sysctl@020000 {
+                               compatible = "arm,sp810", "arm,primecell";
+                               reg = <0x020000 0x1000>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
+                               clock-names = "refclk", "timclk", "apb_pclk";
+                               #clock-cells = <1>;
+                               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+                       };
+
+                       v2m_serial0: uart@090000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x090000 0x1000>;
+                               interrupts = <5>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial1: uart@0a0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0a0000 0x1000>;
+                               interrupts = <6>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial2: uart@0b0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0b0000 0x1000>;
+                               interrupts = <7>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial3: uart@0c0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0c0000 0x1000>;
+                               interrupts = <8>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       wdt@0f0000 {
+                               compatible = "arm,sp805", "arm,primecell";
+                               reg = <0x0f0000 0x1000>;
+                               interrupts = <0>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
+                               clock-names = "wdogclk", "apb_pclk";
+                       };
+
+                       v2m_timer01: timer@110000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x110000 0x1000>;
+                               interrupts = <2>;
+                               clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       v2m_timer23: timer@120000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x120000 0x1000>;
+                               interrupts = <3>;
+                               clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       rtc@170000 {
+                               compatible = "arm,pl031", "arm,primecell";
+                               reg = <0x170000 0x1000>;
+                               interrupts = <4>;
+                               clocks = <&v2m_clk24mhz>;
+                               clock-names = "apb_pclk";
+                       };
+
+                       virtio_block@0130000 {
+                               compatible = "virtio,mmio";
+                               reg = <0x130000 0x1000>;
+                               interrupts = <0x2a>;
+                       };
+               };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+
+               mcc {
+                       compatible = "arm,vexpress,config-bus", "simple-bus";
+                       arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+                       /*
+                        * Not supported in FVP models
+                        *
+                        * reset@0 {
+                        *      compatible = "arm,vexpress-reset";
+                        *      arm,vexpress-sysreg,func = <5 0>;
+                        * };
+                        */
+
+                       muxfpga@0 {
+                               compatible = "arm,vexpress-muxfpga";
+                               arm,vexpress-sysreg,func = <7 0>;
+                       };
+
+                       /*
+                        * Not used - Superseded by PSCI sys_poweroff
+                        *
+                        * shutdown@0 {
+                        *      compatible = "arm,vexpress-shutdown";
+                        *      arm,vexpress-sysreg,func = <8 0>;
+                        * };
+                        */
+
+                       /*
+                        * Not used - Superseded by PSCI sys_reset
+                        *
+                        * reboot@0 {
+                        *      compatible = "arm,vexpress-reboot";
+                        *      arm,vexpress-sysreg,func = <9 0>;
+                        * };
+                        */
+
+                       dvimode@0 {
+                               compatible = "arm,vexpress-dvimode";
+                               arm,vexpress-sysreg,func = <11 0>;
+                       };
+               };
+       };
diff --git a/fdts/rtsm_ve-motherboard-no_psci.dtsi b/fdts/rtsm_ve-motherboard-no_psci.dtsi
new file mode 100644 (file)
index 0000000..7ba575e
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+       motherboard {
+               arm,v2m-memory-map = "rs1";
+               compatible = "arm,vexpress,v2m-p1", "simple-bus";
+               #address-cells = <2>; /* SMB chipselect number and offset */
+               #size-cells = <1>;
+               #interrupt-cells = <1>;
+               ranges;
+
+               flash@0,00000000 {
+                       compatible = "arm,vexpress-flash", "cfi-flash";
+                       reg = <0 0x00000000 0x04000000>,
+                             <4 0x00000000 0x04000000>;
+                       bank-width = <4>;
+               };
+
+               vram@2,00000000 {
+                       compatible = "arm,vexpress-vram";
+                       reg = <2 0x00000000 0x00800000>;
+               };
+
+               ethernet@2,02000000 {
+                       compatible = "smsc,lan91c111";
+                       reg = <2 0x02000000 0x10000>;
+                       interrupts = <15>;
+               };
+
+               v2m_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "v2m:clk24mhz";
+               };
+
+               v2m_refclk1mhz: refclk1mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000>;
+                       clock-output-names = "v2m:refclk1mhz";
+               };
+
+               v2m_refclk32khz: refclk32khz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "v2m:refclk32khz";
+               };
+
+               iofpga@3,00000000 {
+                       compatible = "arm,amba-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 3 0 0x200000>;
+
+                       v2m_sysreg: sysreg@010000 {
+                               compatible = "arm,vexpress-sysreg";
+                               reg = <0x010000 0x1000>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+
+                       v2m_sysctl: sysctl@020000 {
+                               compatible = "arm,sp810", "arm,primecell";
+                               reg = <0x020000 0x1000>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
+                               clock-names = "refclk", "timclk", "apb_pclk";
+                               #clock-cells = <1>;
+                               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+                       };
+
+                       aaci@040000 {
+                               compatible = "arm,pl041", "arm,primecell";
+                               reg = <0x040000 0x1000>;
+                               interrupts = <11>;
+                               clocks = <&v2m_clk24mhz>;
+                               clock-names = "apb_pclk";
+                       };
+
+                       mmci@050000 {
+                               compatible = "arm,pl180", "arm,primecell";
+                               reg = <0x050000 0x1000>;
+                               interrupts = <9 10>;
+                               cd-gpios = <&v2m_sysreg 0 0>;
+                               wp-gpios = <&v2m_sysreg 1 0>;
+                               max-frequency = <12000000>;
+                               vmmc-supply = <&v2m_fixed_3v3>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "mclk", "apb_pclk";
+                       };
+
+                       kmi@060000 {
+                               compatible = "arm,pl050", "arm,primecell";
+                               reg = <0x060000 0x1000>;
+                               interrupts = <12>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
+                       };
+
+                       kmi@070000 {
+                               compatible = "arm,pl050", "arm,primecell";
+                               reg = <0x070000 0x1000>;
+                               interrupts = <13>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
+                       };
+
+                       v2m_serial0: uart@090000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x090000 0x1000>;
+                               interrupts = <5>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial1: uart@0a0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0a0000 0x1000>;
+                               interrupts = <6>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial2: uart@0b0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0b0000 0x1000>;
+                               interrupts = <7>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial3: uart@0c0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0c0000 0x1000>;
+                               interrupts = <8>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       wdt@0f0000 {
+                               compatible = "arm,sp805", "arm,primecell";
+                               reg = <0x0f0000 0x1000>;
+                               interrupts = <0>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
+                               clock-names = "wdogclk", "apb_pclk";
+                       };
+
+                       v2m_timer01: timer@110000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x110000 0x1000>;
+                               interrupts = <2>;
+                               clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       v2m_timer23: timer@120000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x120000 0x1000>;
+                               interrupts = <3>;
+                               clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       rtc@170000 {
+                               compatible = "arm,pl031", "arm,primecell";
+                               reg = <0x170000 0x1000>;
+                               interrupts = <4>;
+                               clocks = <&v2m_clk24mhz>;
+                               clock-names = "apb_pclk";
+                       };
+
+                       clcd@1f0000 {
+                               compatible = "arm,pl111", "arm,primecell";
+                               reg = <0x1f0000 0x1000>;
+                               interrupts = <14>;
+                               clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
+                               clock-names = "clcdclk", "apb_pclk";
+                               mode = "XVGA";
+                               use_dma = <0>;
+                               framebuffer = <0x18000000 0x00180000>;
+                       };
+
+                       virtio_block@0130000 {
+                               compatible = "virtio,mmio";
+                               reg = <0x130000 0x1000>;
+                               interrupts = <0x2a>;
+                       };
+               };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               mcc {
+                       compatible = "arm,vexpress,config-bus", "simple-bus";
+                       arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+                       v2m_oscclk1: osc@1 {
+                               /* CLCD clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 1>;
+                               freq-range = <23750000 63500000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk1";
+                       };
+
+                       reset@0 {
+                               compatible = "arm,vexpress-reset";
+                               arm,vexpress-sysreg,func = <5 0>;
+                       };
+
+                       muxfpga@0 {
+                               compatible = "arm,vexpress-muxfpga";
+                               arm,vexpress-sysreg,func = <7 0>;
+                       };
+
+                       shutdown@0 {
+                               compatible = "arm,vexpress-shutdown";
+                               arm,vexpress-sysreg,func = <8 0>;
+                       };
+
+                       reboot@0 {
+                               compatible = "arm,vexpress-reboot";
+                               arm,vexpress-sysreg,func = <9 0>;
+                       };
+
+                       dvimode@0 {
+                               compatible = "arm,vexpress-dvimode";
+                               arm,vexpress-sysreg,func = <11 0>;
+                       };
+               };
+       };
diff --git a/fdts/rtsm_ve-motherboard.dtsi b/fdts/rtsm_ve-motherboard.dtsi
new file mode 100644 (file)
index 0000000..6aa40ff
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+       motherboard {
+               arm,v2m-memory-map = "rs1";
+               compatible = "arm,vexpress,v2m-p1", "simple-bus";
+               #address-cells = <2>; /* SMB chipselect number and offset */
+               #size-cells = <1>;
+               #interrupt-cells = <1>;
+               ranges;
+
+               flash@0,00000000 {
+                       compatible = "arm,vexpress-flash", "cfi-flash";
+                       reg = <0 0x00000000 0x04000000>,
+                             <4 0x00000000 0x04000000>;
+                       bank-width = <4>;
+               };
+
+               vram@2,00000000 {
+                       compatible = "arm,vexpress-vram";
+                       reg = <2 0x00000000 0x00800000>;
+               };
+
+               ethernet@2,02000000 {
+                       compatible = "smsc,lan91c111";
+                       reg = <2 0x02000000 0x10000>;
+                       interrupts = <15>;
+               };
+
+               v2m_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "v2m:clk24mhz";
+               };
+
+               v2m_refclk1mhz: refclk1mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000>;
+                       clock-output-names = "v2m:refclk1mhz";
+               };
+
+               v2m_refclk32khz: refclk32khz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "v2m:refclk32khz";
+               };
+
+               iofpga@3,00000000 {
+                       compatible = "arm,amba-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 3 0 0x200000>;
+
+                       v2m_sysreg: sysreg@010000 {
+                               compatible = "arm,vexpress-sysreg";
+                               reg = <0x010000 0x1000>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+
+                       v2m_sysctl: sysctl@020000 {
+                               compatible = "arm,sp810", "arm,primecell";
+                               reg = <0x020000 0x1000>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
+                               clock-names = "refclk", "timclk", "apb_pclk";
+                               #clock-cells = <1>;
+                               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+                       };
+
+                       aaci@040000 {
+                               compatible = "arm,pl041", "arm,primecell";
+                               reg = <0x040000 0x1000>;
+                               interrupts = <11>;
+                               clocks = <&v2m_clk24mhz>;
+                               clock-names = "apb_pclk";
+                       };
+
+                       mmci@050000 {
+                               compatible = "arm,pl180", "arm,primecell";
+                               reg = <0x050000 0x1000>;
+                               interrupts = <9 10>;
+                               cd-gpios = <&v2m_sysreg 0 0>;
+                               wp-gpios = <&v2m_sysreg 1 0>;
+                               max-frequency = <12000000>;
+                               vmmc-supply = <&v2m_fixed_3v3>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "mclk", "apb_pclk";
+                       };
+
+                       kmi@060000 {
+                               compatible = "arm,pl050", "arm,primecell";
+                               reg = <0x060000 0x1000>;
+                               interrupts = <12>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
+                       };
+
+                       kmi@070000 {
+                               compatible = "arm,pl050", "arm,primecell";
+                               reg = <0x070000 0x1000>;
+                               interrupts = <13>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
+                       };
+
+                       v2m_serial0: uart@090000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x090000 0x1000>;
+                               interrupts = <5>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial1: uart@0a0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0a0000 0x1000>;
+                               interrupts = <6>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial2: uart@0b0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0b0000 0x1000>;
+                               interrupts = <7>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial3: uart@0c0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0c0000 0x1000>;
+                               interrupts = <8>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       wdt@0f0000 {
+                               compatible = "arm,sp805", "arm,primecell";
+                               reg = <0x0f0000 0x1000>;
+                               interrupts = <0>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
+                               clock-names = "wdogclk", "apb_pclk";
+                       };
+
+                       v2m_timer01: timer@110000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x110000 0x1000>;
+                               interrupts = <2>;
+                               clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       v2m_timer23: timer@120000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x120000 0x1000>;
+                               interrupts = <3>;
+                               clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       rtc@170000 {
+                               compatible = "arm,pl031", "arm,primecell";
+                               reg = <0x170000 0x1000>;
+                               interrupts = <4>;
+                               clocks = <&v2m_clk24mhz>;
+                               clock-names = "apb_pclk";
+                       };
+
+                       clcd@1f0000 {
+                               compatible = "arm,pl111", "arm,primecell";
+                               reg = <0x1f0000 0x1000>;
+                               interrupts = <14>;
+                               clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
+                               clock-names = "clcdclk", "apb_pclk";
+                               mode = "XVGA";
+                               use_dma = <0>;
+                               framebuffer = <0x18000000 0x00180000>;
+                       };
+
+                       virtio_block@0130000 {
+                               compatible = "virtio,mmio";
+                               reg = <0x130000 0x1000>;
+                               interrupts = <0x2a>;
+                       };
+               };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               mcc {
+                       compatible = "arm,vexpress,config-bus", "simple-bus";
+                       arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+                       v2m_oscclk1: osc@1 {
+                               /* CLCD clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 1>;
+                               freq-range = <23750000 63500000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk1";
+                       };
+
+                       /*
+                        * Not supported in FVP models
+                        *
+                        * reset@0 {
+                        *      compatible = "arm,vexpress-reset";
+                        *      arm,vexpress-sysreg,func = <5 0>;
+                        * };
+                        */
+
+                       muxfpga@0 {
+                               compatible = "arm,vexpress-muxfpga";
+                               arm,vexpress-sysreg,func = <7 0>;
+                       };
+
+                       /*
+                        * Not used - Superseded by PSCI sys_poweroff
+                        *
+                        * shutdown@0 {
+                        *      compatible = "arm,vexpress-shutdown";
+                        *      arm,vexpress-sysreg,func = <8 0>;
+                        * };
+                        */
+
+                       /*
+                        * Not used - Superseded by PSCI sys_reset
+                        *
+                        * reboot@0 {
+                        *      compatible = "arm,vexpress-reboot";
+                        *      arm,vexpress-sysreg,func = <9 0>;
+                        * };
+                        */
+
+                       dvimode@0 {
+                               compatible = "arm,vexpress-dvimode";
+                               arm,vexpress-sysreg,func = <11 0>;
+                       };
+               };
+       };
diff --git a/include/bl31/bl31.h b/include/bl31/bl31.h
new file mode 100644 (file)
index 0000000..96867b0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BL31_H__
+#define __BL31_H__
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * Function prototypes
+ ******************************************************************************/
+void bl31_arch_setup(void);
+void bl31_next_el_arch_setup(uint32_t security_state);
+void bl31_set_next_image_type(uint32_t type);
+uint32_t bl31_get_next_image_type(void);
+void bl31_prepare_next_image_entry(void);
+void bl31_register_bl32_init(int32_t (*)(void));
+
+#endif /* __BL31_H__ */
diff --git a/include/bl31/context.h b/include/bl31/context.h
new file mode 100644 (file)
index 0000000..0dfebe0
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CONTEXT_H__
+#define __CONTEXT_H__
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the 'gp_regs'
+ * structure at their correct offsets.
+ ******************************************************************************/
+#define CTX_GPREGS_OFFSET      0x0
+#define CTX_GPREG_X0           0x0
+#define CTX_GPREG_X1           0x8
+#define CTX_GPREG_X2           0x10
+#define CTX_GPREG_X3           0x18
+#define CTX_GPREG_X4           0x20
+#define CTX_GPREG_X5           0x28
+#define CTX_GPREG_X6           0x30
+#define CTX_GPREG_X7           0x38
+#define CTX_GPREG_X8           0x40
+#define CTX_GPREG_X9           0x48
+#define CTX_GPREG_X10          0x50
+#define CTX_GPREG_X11          0x58
+#define CTX_GPREG_X12          0x60
+#define CTX_GPREG_X13          0x68
+#define CTX_GPREG_X14          0x70
+#define CTX_GPREG_X15          0x78
+#define CTX_GPREG_X16          0x80
+#define CTX_GPREG_X17          0x88
+#define CTX_GPREG_X18          0x90
+#define CTX_GPREG_X19          0x98
+#define CTX_GPREG_X20          0xa0
+#define CTX_GPREG_X21          0xa8
+#define CTX_GPREG_X22          0xb0
+#define CTX_GPREG_X23          0xb8
+#define CTX_GPREG_X24          0xc0
+#define CTX_GPREG_X25          0xc8
+#define CTX_GPREG_X26          0xd0
+#define CTX_GPREG_X27          0xd8
+#define CTX_GPREG_X28          0xe0
+#define CTX_GPREG_X29          0xe8
+#define CTX_GPREG_LR           0xf0
+#define CTX_GPREG_SP_EL0       0xf8
+#define CTX_GPREGS_END         0x100
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the 'el3_state'
+ * structure at their correct offsets. Note that some of the registers are only
+ * 32-bits wide but are stored as 64-bit values for convenience
+ ******************************************************************************/
+#define CTX_EL3STATE_OFFSET    (CTX_GPREGS_OFFSET + CTX_GPREGS_END)
+#define CTX_SCR_EL3            0x0
+#define CTX_RUNTIME_SP         0x8
+#define CTX_SPSR_EL3           0x10
+#define CTX_ELR_EL3            0x18
+#define CTX_EL3STATE_END       0x20
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the
+ * 'el1_sys_regs' structure at their correct offsets. Note that some of the
+ * registers are only 32-bits wide but are stored as 64-bit values for
+ * convenience
+ ******************************************************************************/
+#define CTX_SYSREGS_OFFSET     (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
+#define CTX_SPSR_EL1           0x0
+#define CTX_ELR_EL1            0x8
+#define CTX_SPSR_ABT           0x10
+#define CTX_SPSR_UND           0x18
+#define CTX_SPSR_IRQ           0x20
+#define CTX_SPSR_FIQ           0x28
+#define CTX_SCTLR_EL1          0x30
+#define CTX_ACTLR_EL1          0x38
+#define CTX_CPACR_EL1          0x40
+#define CTX_CSSELR_EL1         0x48
+#define CTX_SP_EL1             0x50
+#define CTX_ESR_EL1            0x58
+#define CTX_TTBR0_EL1          0x60
+#define CTX_TTBR1_EL1          0x68
+#define CTX_MAIR_EL1           0x70
+#define CTX_AMAIR_EL1          0x78
+#define CTX_TCR_EL1            0x80
+#define CTX_TPIDR_EL1          0x88
+#define CTX_TPIDR_EL0          0x90
+#define CTX_TPIDRRO_EL0                0x98
+#define CTX_DACR32_EL2         0xa0
+#define CTX_IFSR32_EL2         0xa8
+#define CTX_PAR_EL1            0xb0
+#define CTX_FAR_EL1            0xb8
+#define CTX_AFSR0_EL1          0xc0
+#define CTX_AFSR1_EL1          0xc8
+#define CTX_CONTEXTIDR_EL1     0xd0
+#define CTX_VBAR_EL1           0xd8
+/*
+ * If the timer registers aren't saved and restored, we don't have to reserve
+ * space for them in the context
+ */
+#if NS_TIMER_SWITCH
+#define CTX_CNTP_CTL_EL0       0xe0
+#define CTX_CNTP_CVAL_EL0      0xe8
+#define CTX_CNTV_CTL_EL0       0xf0
+#define CTX_CNTV_CVAL_EL0      0xf8
+#define CTX_CNTKCTL_EL1                0x100
+#define CTX_FP_FPEXC32_EL2     0x108
+#define CTX_SYSREGS_END                0x110
+#else
+#define CTX_FP_FPEXC32_EL2     0xe0
+#define CTX_SYSREGS_END                0xf0
+#endif
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the 'fp_regs'
+ * structure at their correct offsets.
+ ******************************************************************************/
+#if CTX_INCLUDE_FPREGS
+#define CTX_FPREGS_OFFSET      (CTX_SYSREGS_OFFSET + CTX_SYSREGS_END)
+#define CTX_FP_Q0              0x0
+#define CTX_FP_Q1              0x10
+#define CTX_FP_Q2              0x20
+#define CTX_FP_Q3              0x30
+#define CTX_FP_Q4              0x40
+#define CTX_FP_Q5              0x50
+#define CTX_FP_Q6              0x60
+#define CTX_FP_Q7              0x70
+#define CTX_FP_Q8              0x80
+#define CTX_FP_Q9              0x90
+#define CTX_FP_Q10             0xa0
+#define CTX_FP_Q11             0xb0
+#define CTX_FP_Q12             0xc0
+#define CTX_FP_Q13             0xd0
+#define CTX_FP_Q14             0xe0
+#define CTX_FP_Q15             0xf0
+#define CTX_FP_Q16             0x100
+#define CTX_FP_Q17             0x110
+#define CTX_FP_Q18             0x120
+#define CTX_FP_Q19             0x130
+#define CTX_FP_Q20             0x140
+#define CTX_FP_Q21             0x150
+#define CTX_FP_Q22             0x160
+#define CTX_FP_Q23             0x170
+#define CTX_FP_Q24             0x180
+#define CTX_FP_Q25             0x190
+#define CTX_FP_Q26             0x1a0
+#define CTX_FP_Q27             0x1b0
+#define CTX_FP_Q28             0x1c0
+#define CTX_FP_Q29             0x1d0
+#define CTX_FP_Q30             0x1e0
+#define CTX_FP_Q31             0x1f0
+#define CTX_FP_FPSR            0x200
+#define CTX_FP_FPCR            0x208
+#define CTX_FPREGS_END         0x210
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <cassert.h>
+#include <platform_def.h>      /* for CACHE_WRITEBACK_GRANULE */
+#include <stdint.h>
+
+/*
+ * Common constants to help define the 'cpu_context' structure and its
+ * members below.
+ */
+#define DWORD_SHIFT            3
+#define DEFINE_REG_STRUCT(name, num_regs)      \
+       typedef struct name {                   \
+               uint64_t _regs[num_regs];       \
+       }  __aligned(16) name##_t
+
+/* Constants to determine the size of individual context structures */
+#define CTX_GPREG_ALL          (CTX_GPREGS_END >> DWORD_SHIFT)
+#define CTX_SYSREG_ALL         (CTX_SYSREGS_END >> DWORD_SHIFT)
+#if CTX_INCLUDE_FPREGS
+#define CTX_FPREG_ALL          (CTX_FPREGS_END >> DWORD_SHIFT)
+#endif
+#define CTX_EL3STATE_ALL       (CTX_EL3STATE_END >> DWORD_SHIFT)
+
+/*
+ * AArch64 general purpose register context structure. Usually x0-x18,
+ * lr are saved as the compiler is expected to preserve the remaining
+ * callee saved registers if used by the C runtime and the assembler
+ * does not touch the remaining. But in case of world switch during
+ * exception handling, we need to save the callee registers too.
+ */
+DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL);
+
+/*
+ * AArch64 EL1 system register context structure for preserving the
+ * architectural state during switches from one security state to
+ * another in EL1.
+ */
+DEFINE_REG_STRUCT(el1_sys_regs, CTX_SYSREG_ALL);
+
+/*
+ * AArch64 floating point register context structure for preserving
+ * the floating point state during switches from one security state to
+ * another.
+ */
+#if CTX_INCLUDE_FPREGS
+DEFINE_REG_STRUCT(fp_regs, CTX_FPREG_ALL);
+#endif
+
+/*
+ * Miscellaneous registers used by EL3 firmware to maintain its state
+ * across exception entries and exits
+ */
+DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL);
+
+/*
+ * Macros to access members of any of the above structures using their
+ * offsets
+ */
+#define read_ctx_reg(ctx, offset)      ((ctx)->_regs[offset >> DWORD_SHIFT])
+#define write_ctx_reg(ctx, offset, val)        (((ctx)->_regs[offset >> DWORD_SHIFT]) \
+                                        = val)
+
+/*
+ * Top-level context structure which is used by EL3 firmware to
+ * preserve the state of a core at EL1 in one of the two security
+ * states and save enough EL3 meta data to be able to return to that
+ * EL and security state. The context management library will be used
+ * to ensure that SP_EL3 always points to an instance of this
+ * structure at exception entry and exit. Each instance will
+ * correspond to either the secure or the non-secure state.
+ */
+typedef struct cpu_context {
+       gp_regs_t gpregs_ctx;
+       el3_state_t el3state_ctx;
+       el1_sys_regs_t sysregs_ctx;
+#if CTX_INCLUDE_FPREGS
+       fp_regs_t fpregs_ctx;
+#endif
+} cpu_context_t;
+
+/* Macros to access members of the 'cpu_context_t' structure */
+#define get_el3state_ctx(h)    (&((cpu_context_t *) h)->el3state_ctx)
+#if CTX_INCLUDE_FPREGS
+#define get_fpregs_ctx(h)      (&((cpu_context_t *) h)->fpregs_ctx)
+#endif
+#define get_sysregs_ctx(h)     (&((cpu_context_t *) h)->sysregs_ctx)
+#define get_gpregs_ctx(h)      (&((cpu_context_t *) h)->gpregs_ctx)
+
+/*
+ * Compile time assertions related to the 'cpu_context' structure to
+ * ensure that the assembler and the compiler view of the offsets of
+ * the structure members is the same.
+ */
+CASSERT(CTX_GPREGS_OFFSET == __builtin_offsetof(cpu_context_t, gpregs_ctx), \
+       assert_core_context_gp_offset_mismatch);
+CASSERT(CTX_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, sysregs_ctx), \
+       assert_core_context_sys_offset_mismatch);
+#if CTX_INCLUDE_FPREGS
+CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx), \
+       assert_core_context_fp_offset_mismatch);
+#endif
+CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx), \
+       assert_core_context_el3state_offset_mismatch);
+
+/*
+ * Helper macro to set the general purpose registers that correspond to
+ * parameters in an aapcs_64 call i.e. x0-x7
+ */
+#define set_aapcs_args0(ctx, x0)                               do {    \
+               write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0, x0);   \
+       } while (0);
+#define set_aapcs_args1(ctx, x0, x1)                           do {    \
+               write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1, x1);   \
+               set_aapcs_args0(ctx, x0);                               \
+       } while (0);
+#define set_aapcs_args2(ctx, x0, x1, x2)                       do {    \
+               write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2, x2);   \
+               set_aapcs_args1(ctx, x0, x1);                           \
+       } while (0);
+#define set_aapcs_args3(ctx, x0, x1, x2, x3)                   do {    \
+               write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3, x3);   \
+               set_aapcs_args2(ctx, x0, x1, x2);                       \
+       } while (0);
+#define set_aapcs_args4(ctx, x0, x1, x2, x3, x4)               do {    \
+               write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X4, x4);   \
+               set_aapcs_args3(ctx, x0, x1, x2, x3);                   \
+       } while (0);
+#define set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5)           do {    \
+               write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X5, x5);   \
+               set_aapcs_args4(ctx, x0, x1, x2, x3, x4);               \
+       } while (0);
+#define set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6)       do {    \
+               write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X6, x6);   \
+               set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5);           \
+       } while (0);
+#define set_aapcs_args7(ctx, x0, x1, x2, x3, x4, x5, x6, x7)   do {    \
+               write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X7, x7);   \
+               set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6);       \
+       } while (0);
+
+/*******************************************************************************
+ * Function prototypes
+ ******************************************************************************/
+void el1_sysregs_context_save(el1_sys_regs_t *regs);
+void el1_sysregs_context_restore(el1_sys_regs_t *regs);
+#if CTX_INCLUDE_FPREGS
+void fpregs_context_save(fp_regs_t *regs);
+void fpregs_context_restore(fp_regs_t *regs);
+#endif
+
+
+#undef CTX_SYSREG_ALL
+#if CTX_INCLUDE_FPREGS
+#undef CTX_FPREG_ALL
+#endif
+#undef CTX_GPREG_ALL
+#undef CTX_EL3STATE_ALL
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __CONTEXT_H__ */
diff --git a/include/bl31/context_mgmt.h b/include/bl31/context_mgmt.h
new file mode 100644 (file)
index 0000000..6e82fb7
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CM_H__
+#define __CM_H__
+
+#include <cpu_data.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+struct entry_point_info;
+
+/*******************************************************************************
+ * Function & variable prototypes
+ ******************************************************************************/
+void cm_init(void);
+void *cm_get_context_by_mpidr(uint64_t mpidr, uint32_t security_state);
+static inline void *cm_get_context(uint32_t security_state);
+void cm_set_context_by_mpidr(uint64_t mpidr,
+                            void *context,
+                            uint32_t security_state);
+static inline void cm_set_context(void *context, uint32_t security_state);
+void cm_init_context(uint64_t mpidr, const struct entry_point_info *ep);
+void cm_prepare_el3_exit(uint32_t security_state);
+void cm_el1_sysregs_context_save(uint32_t security_state);
+void cm_el1_sysregs_context_restore(uint32_t security_state);
+void cm_set_elr_el3(uint32_t security_state, uint64_t entrypoint);
+void cm_set_elr_spsr_el3(uint32_t security_state,
+                        uint64_t entrypoint, uint32_t spsr);
+void cm_write_scr_el3_bit(uint32_t security_state,
+                         uint32_t bit_pos,
+                         uint32_t value);
+void cm_set_next_eret_context(uint32_t security_state);
+uint32_t cm_get_scr_el3(uint32_t security_state);
+
+/* Inline definitions */
+
+/*******************************************************************************
+ * 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);
+}
+
+
+#endif /* __CM_H__ */
diff --git a/include/bl31/cpu_data.h b/include/bl31/cpu_data.h
new file mode 100644 (file)
index 0000000..1926e29
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPU_DATA_H__
+#define __CPU_DATA_H__
+
+/* Offsets for the cpu_data structure */
+#define CPU_DATA_CRASH_BUF_OFFSET      0x18
+#if CRASH_REPORTING
+#define CPU_DATA_LOG2SIZE              7
+#else
+#define CPU_DATA_LOG2SIZE              6
+#endif
+/* need enough space in crash buffer to save 8 registers */
+#define CPU_DATA_CRASH_BUF_SIZE                64
+#define CPU_DATA_CPU_OPS_PTR           0x10
+
+#ifndef __ASSEMBLY__
+
+#include <arch_helpers.h>
+#include <cassert.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <stdint.h>
+
+/* Offsets for the cpu_data structure */
+#define CPU_DATA_PSCI_LOCK_OFFSET      __builtin_offsetof\
+               (cpu_data_t, psci_svc_cpu_data.pcpu_bakery_info)
+
+#if PLAT_PCPU_DATA_SIZE
+#define CPU_DATA_PLAT_PCPU_OFFSET      __builtin_offsetof\
+               (cpu_data_t, platform_cpu_data)
+#endif
+
+/*******************************************************************************
+ * Function & variable prototypes
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Cache of frequently used per-cpu data:
+ *   Pointers to non-secure and secure security state contexts
+ *   Address of the crash stack
+ * It is aligned to the cache line boundary to allow efficient concurrent
+ * manipulation of these pointers on different cpus
+ *
+ * TODO: Add other commonly used variables to this (tf_issues#90)
+ *
+ * The data structure and the _cpu_data accessors should not be used directly
+ * by components that have per-cpu members. The member access macros should be
+ * used for this.
+ ******************************************************************************/
+typedef struct cpu_data {
+       void *cpu_context[2];
+       uint64_t cpu_ops_ptr;
+#if CRASH_REPORTING
+       uint64_t crash_buf[CPU_DATA_CRASH_BUF_SIZE >> 3];
+#endif
+       struct psci_cpu_data psci_svc_cpu_data;
+#if PLAT_PCPU_DATA_SIZE
+       uint8_t platform_cpu_data[PLAT_PCPU_DATA_SIZE];
+#endif
+} __aligned(CACHE_WRITEBACK_GRANULE) cpu_data_t;
+
+#if CRASH_REPORTING
+/* verify assembler offsets match data structures */
+CASSERT(CPU_DATA_CRASH_BUF_OFFSET == __builtin_offsetof
+       (cpu_data_t, crash_buf),
+       assert_cpu_data_crash_stack_offset_mismatch);
+#endif
+
+CASSERT((1 << CPU_DATA_LOG2SIZE) == sizeof(cpu_data_t),
+       assert_cpu_data_log2size_mismatch);
+
+CASSERT(CPU_DATA_CPU_OPS_PTR == __builtin_offsetof
+               (cpu_data_t, cpu_ops_ptr),
+               assert_cpu_data_cpu_ops_ptr_offset_mismatch);
+
+struct cpu_data *_cpu_data_by_index(uint32_t cpu_index);
+struct cpu_data *_cpu_data_by_mpidr(uint64_t mpidr);
+
+/* Return the cpu_data structure for the current CPU. */
+static inline struct cpu_data *_cpu_data(void)
+{
+       return (cpu_data_t *)read_tpidr_el3();
+}
+
+
+/**************************************************************************
+ * APIs for initialising and accessing per-cpu data
+ *************************************************************************/
+
+void init_cpu_data_ptr(void);
+
+#define get_cpu_data(_m)                  _cpu_data()->_m
+#define set_cpu_data(_m, _v)              _cpu_data()->_m = _v
+#define get_cpu_data_by_index(_ix, _m)    _cpu_data_by_index(_ix)->_m
+#define set_cpu_data_by_index(_ix, _m, _v) _cpu_data_by_index(_ix)->_m = _v
+#define get_cpu_data_by_mpidr(_id, _m)    _cpu_data_by_mpidr(_id)->_m
+#define set_cpu_data_by_mpidr(_id, _m, _v) _cpu_data_by_mpidr(_id)->_m = _v
+
+#define flush_cpu_data(_m)        flush_dcache_range((uint64_t)          \
+                                                     &(_cpu_data()->_m), \
+                                                     sizeof(_cpu_data()->_m))
+#define flush_cpu_data_by_index(_ix, _m)       \
+                                  flush_dcache_range((uint64_t)          \
+                                        &(_cpu_data_by_index(_ix)->_m),  \
+                                        sizeof(_cpu_data_by_index(_ix)->_m))
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* __CPU_DATA_H__ */
diff --git a/include/bl31/interrupt_mgmt.h b/include/bl31/interrupt_mgmt.h
new file mode 100644 (file)
index 0000000..e07ddf8
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INTERRUPT_MGMT_H__
+#define __INTERRUPT_MGMT_H__
+
+#include <arch.h>
+
+/*******************************************************************************
+ * Constants for the types of interrupts recognised by the IM framework
+ ******************************************************************************/
+#define INTR_TYPE_S_EL1                        0
+#define INTR_TYPE_EL3                  1
+#define INTR_TYPE_NS                   2
+#define MAX_INTR_TYPES                 3
+#define INTR_TYPE_INVAL                        MAX_INTR_TYPES
+/*
+ * Constant passed to the interrupt handler in the 'id' field when the
+ * framework does not read the gic registers to determine the interrupt id.
+ */
+#define INTR_ID_UNAVAILABLE            0xFFFFFFFF
+
+
+/*******************************************************************************
+ * Mask for _both_ the routing model bits in the 'flags' parameter and
+ * constants to define the valid routing models for each supported interrupt
+ * type
+ ******************************************************************************/
+#define INTR_RM_FLAGS_SHIFT            0x0
+#define INTR_RM_FLAGS_MASK             0x3
+/* Routed to EL3 from NS. Taken to S-EL1 from Secure */
+#define INTR_SEL1_VALID_RM0            0x2
+/* Routed to EL3 from NS and Secure */
+#define INTR_SEL1_VALID_RM1            0x3
+/* Routed to EL1/EL2 from NS and to S-EL1 from Secure */
+#define INTR_NS_VALID_RM0              0x0
+/* Routed to EL1/EL2 from NS and to EL3 from Secure */
+#define INTR_NS_VALID_RM1              0x1
+/* This is the default routing model */
+#define INTR_DEFAULT_RM                0x0
+
+/*******************************************************************************
+ * Constants for the _individual_ routing model bits in the 'flags' field for
+ * each interrupt type and mask to validate the 'flags' parameter while
+ * registering an interrupt handler
+ ******************************************************************************/
+#define INTR_TYPE_FLAGS_MASK           0xFFFFFFFC
+
+#define INTR_RM_FROM_SEC_SHIFT         SECURE          /* BIT[0] */
+#define INTR_RM_FROM_NS_SHIFT          NON_SECURE      /* BIT[1] */
+#define INTR_RM_FROM_FLAG_MASK         1
+#define get_interrupt_rm_flag(flag, ss)        (((flag >> INTR_RM_FLAGS_SHIFT) >> ss) \
+                                        & INTR_RM_FROM_FLAG_MASK)
+#define set_interrupt_rm_flag(flag, ss)        (flag |= 1 << ss)
+#define clr_interrupt_rm_flag(flag, ss)        (flag &= ~(1 << ss))
+
+
+/*******************************************************************************
+ * Macros to validate the routing model bits in the 'flags' for a type
+ * of interrupt. If the model does not match one of the valid masks
+ * -EINVAL is returned.
+ ******************************************************************************/
+#define validate_sel1_interrupt_rm(x)  (x == INTR_SEL1_VALID_RM0 ? 0 : \
+                                        (x == INTR_SEL1_VALID_RM1 ? 0 :\
+                                         -EINVAL))
+
+#define validate_ns_interrupt_rm(x)    (x == INTR_NS_VALID_RM0 ? 0 : \
+                                        (x == INTR_NS_VALID_RM1 ? 0 :\
+                                         -EINVAL))
+
+/*******************************************************************************
+ * Macros to set the 'flags' parameter passed to an interrupt type handler. Only
+ * the flag to indicate the security state when the exception was generated is
+ * supported.
+ ******************************************************************************/
+#define INTR_SRC_SS_FLAG_SHIFT         0               /* BIT[0] */
+#define INTR_SRC_SS_FLAG_MASK          1
+#define set_interrupt_src_ss(flag, val)        (flag |= val << INTR_SRC_SS_FLAG_SHIFT)
+#define clr_interrupt_src_ss(flag)     (flag &= ~(1 << INTR_SRC_SS_FLAG_SHIFT))
+#define get_interrupt_src_ss(flag)     ((flag >> INTR_SRC_SS_FLAG_SHIFT) & \
+                                        INTR_SRC_SS_FLAG_MASK)
+
+#ifndef __ASSEMBLY__
+
+/* Prototype for defining a handler for an interrupt type */
+typedef uint64_t (*interrupt_type_handler_t)(uint32_t id,
+                                            uint32_t flags,
+                                            void *handle,
+                                            void *cookie);
+
+/*******************************************************************************
+ * Function & variable prototypes
+ ******************************************************************************/
+uint32_t get_scr_el3_from_routing_model(uint32_t security_state);
+int32_t set_routing_model(uint32_t type, uint32_t flags);
+int32_t register_interrupt_type_handler(uint32_t type,
+                                       interrupt_type_handler_t handler,
+                                       uint32_t flags);
+interrupt_type_handler_t get_interrupt_type_handler(uint32_t interrupt_type);
+int disable_intr_rm_local(uint32_t type, uint32_t security_state);
+int enable_intr_rm_local(uint32_t type, uint32_t security_state);
+
+#endif /*__ASSEMBLY__*/
+#endif /* __INTERRUPT_MGMT_H__ */
diff --git a/include/bl31/runtime_svc.h b/include/bl31/runtime_svc.h
new file mode 100644 (file)
index 0000000..de40041
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RUNTIME_SVC_H__
+#define __RUNTIME_SVC_H__
+
+#include <utils.h>
+
+/*******************************************************************************
+ * Bit definitions inside the function id as per the SMC calling convention
+ ******************************************************************************/
+#define FUNCID_TYPE_SHIFT              31
+#define FUNCID_CC_SHIFT                        30
+#define FUNCID_OEN_SHIFT               24
+#define FUNCID_NUM_SHIFT               0
+
+#define FUNCID_TYPE_MASK               0x1
+#define FUNCID_CC_MASK                 0x1
+#define FUNCID_OEN_MASK                        0x3f
+#define FUNCID_NUM_MASK                        0xffff
+
+#define FUNCID_TYPE_WIDTH              1
+#define FUNCID_CC_WIDTH                        1
+#define FUNCID_OEN_WIDTH               6
+#define FUNCID_NUM_WIDTH               16
+
+#define GET_SMC_CC(id)                 ((id >> FUNCID_CC_SHIFT) & \
+                                        FUNCID_CC_MASK)
+#define GET_SMC_TYPE(id)               ((id >> FUNCID_TYPE_SHIFT) & \
+                                        FUNCID_TYPE_MASK)
+
+#define SMC_64                         1
+#define SMC_32                         0
+#define SMC_UNK                                0xffffffff
+#define SMC_TYPE_FAST                  ULL(1)
+#define SMC_TYPE_STD                   0
+#define SMC_PREEMPTED          0xfffffffe
+/*******************************************************************************
+ * Owning entity number definitions inside the function id as per the SMC
+ * calling convention
+ ******************************************************************************/
+#define OEN_ARM_START                  0
+#define OEN_ARM_END                    0
+#define OEN_CPU_START                  1
+#define OEN_CPU_END                    1
+#define OEN_SIP_START                  2
+#define OEN_SIP_END                    2
+#define OEN_OEM_START                  3
+#define OEN_OEM_END                    3
+#define OEN_STD_START                  4       /* Standard Calls */
+#define OEN_STD_END                    4
+#define OEN_TAP_START                  48      /* Trusted Applications */
+#define OEN_TAP_END                    49
+#define OEN_TOS_START                  50      /* Trusted OS */
+#define OEN_TOS_END                    63
+#define OEN_LIMIT                      64
+
+/*******************************************************************************
+ * Constants to indicate type of exception to the common exception handler.
+ ******************************************************************************/
+#define SYNC_EXCEPTION_SP_EL0          0x0
+#define IRQ_SP_EL0                     0x1
+#define FIQ_SP_EL0                     0x2
+#define SERROR_SP_EL0                  0x3
+#define SYNC_EXCEPTION_SP_ELX          0x4
+#define IRQ_SP_ELX                     0x5
+#define FIQ_SP_ELX                     0x6
+#define SERROR_SP_ELX                  0x7
+#define SYNC_EXCEPTION_AARCH64         0x8
+#define IRQ_AARCH64                    0x9
+#define FIQ_AARCH64                    0xa
+#define SERROR_AARCH64                 0xb
+#define SYNC_EXCEPTION_AARCH32         0xc
+#define IRQ_AARCH32                    0xd
+#define FIQ_AARCH32                    0xe
+#define SERROR_AARCH32                 0xf
+
+/*******************************************************************************
+ * Structure definition, typedefs & constants for the runtime service framework
+ ******************************************************************************/
+
+/*
+ * Constants to allow the assembler access a runtime service
+ * descriptor
+ */
+#define RT_SVC_SIZE_LOG2       5
+#define SIZEOF_RT_SVC_DESC     (1 << RT_SVC_SIZE_LOG2)
+#define RT_SVC_DESC_INIT       16
+#define RT_SVC_DESC_HANDLE     24
+
+/*
+ * The function identifier has 6 bits for the owning entity number and
+ * single bit for the type of smc call. When taken together these
+ * values limit the maximum number of runtime services to 128.
+ */
+#define MAX_RT_SVCS            128
+
+#ifndef __ASSEMBLY__
+
+#include <cassert.h>
+#include <context.h>
+#include <stdint.h>
+
+/* Various flags passed to SMC handlers */
+#define SMC_FROM_SECURE                (0 << 0)
+#define SMC_FROM_NON_SECURE    (1 << 0)
+
+#define is_caller_non_secure(_f)       (!!(_f & SMC_FROM_NON_SECURE))
+#define is_caller_secure(_f)           (!(is_caller_non_secure(_f)))
+
+/* Prototype for runtime service initializing function */
+typedef int32_t (*rt_svc_init_t)(void);
+
+/* Convenience macros to return from SMC handler */
+#define SMC_RET0(_h)   { \
+       return (uint64_t) (_h);         \
+}
+#define SMC_RET1(_h, _x0)      { \
+       write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X0, (_x0)); \
+       SMC_RET0(_h);                                           \
+}
+#define SMC_RET2(_h, _x0, _x1) { \
+       write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X1, (_x1)); \
+       SMC_RET1(_h, (_x0)); \
+}
+#define SMC_RET3(_h, _x0, _x1, _x2)    { \
+       write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X2, (_x2)); \
+       SMC_RET2(_h, (_x0), (_x1)); \
+}
+#define SMC_RET4(_h, _x0, _x1, _x2, _x3)       { \
+       write_ctx_reg(get_gpregs_ctx(_h), CTX_GPREG_X3, (_x3)); \
+       SMC_RET3(_h, (_x0), (_x1), (_x2)); \
+}
+
+
+/*
+ * Convenience macros to access general purpose registers using handle provided
+ * to SMC handler. These takes the offset values defined in context.h
+ */
+#define SMC_GET_GP(_h, _g) \
+       read_ctx_reg(get_gpregs_ctx(_h), (_g));
+#define SMC_SET_GP(_h, _g, _v) \
+       write_ctx_reg(get_gpregs_ctx(_h), (_g), (_v));
+
+/*
+ * Convenience macros to access EL3 context registers using handle provided to
+ * SMC handler. These takes the offset values defined in context.h
+ */
+#define SMC_GET_EL3(_h, _e) \
+       read_ctx_reg(get_el3state_ctx(_h), (_e));
+#define SMC_SET_EL3(_h, _e, _v) \
+       write_ctx_reg(get_el3state_ctx(_h), (_e), (_v));
+
+/* The macro below is used to identify a Standard Service SMC call */
+#define is_std_svc_call(_fid)          ((((_fid) >> FUNCID_OEN_SHIFT) & \
+                                          FUNCID_OEN_MASK) == OEN_STD_START)
+
+/* The macro below is used to identify a valid Fast SMC call */
+#define is_valid_fast_smc(_fid)                ((!(((_fid) >> 16) & 0xff)) && \
+                                          (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST))
+
+/*
+ * Prototype for runtime service SMC handler function. x0 (SMC Function ID) to
+ * x4 are as passed by the caller. Rest of the arguments to SMC and the context
+ * can be accessed using the handle pointer. The cookie parameter is reserved
+ * for future use
+ */
+typedef uint64_t (*rt_svc_handle_t)(uint32_t smc_fid,
+                                 uint64_t x1,
+                                 uint64_t x2,
+                                 uint64_t x3,
+                                 uint64_t x4,
+                                 void *cookie,
+                                 void *handle,
+                                 uint64_t flags);
+typedef struct rt_svc_desc {
+       uint8_t start_oen;
+       uint8_t end_oen;
+       uint8_t call_type;
+       const char *name;
+       rt_svc_init_t init;
+       rt_svc_handle_t handle;
+} rt_svc_desc_t;
+
+/*
+ * Convenience macro to declare a service descriptor
+ */
+#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \
+       static const rt_svc_desc_t __svc_desc_ ## _name \
+               __attribute__ ((section("rt_svc_descs"), used)) = { \
+                       _start, \
+                       _end, \
+                       _type, \
+                       #_name, \
+                       _setup, \
+                       _smch }
+
+/*
+ * Compile time assertions related to the 'rt_svc_desc' structure to:
+ * 1. ensure that the assembler and the compiler view of the size
+ *    of the structure are the same.
+ * 2. ensure that the assembler and the compiler see the initialisation
+ *    routine at the same offset.
+ * 3. ensure that the assembler and the compiler see the handler
+ *    routine at the same offset.
+ */
+CASSERT((sizeof(rt_svc_desc_t) == SIZEOF_RT_SVC_DESC), \
+       assert_sizeof_rt_svc_desc_mismatch);
+CASSERT(RT_SVC_DESC_INIT == __builtin_offsetof(rt_svc_desc_t, init), \
+       assert_rt_svc_desc_init_offset_mismatch);
+CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \
+       assert_rt_svc_desc_handle_offset_mismatch);
+
+
+/*
+ * This macro combines the call type and the owning entity number corresponding
+ * to a runtime service to generate a unique owning entity number. This unique
+ * oen is used to access an entry in the 'rt_svc_descs_indices' array. The entry
+ * contains the index of the service descriptor in the 'rt_svc_descs' array.
+ */
+#define get_unique_oen(oen, call_type) ((oen & FUNCID_OEN_MASK) |      \
+                                       ((call_type & FUNCID_TYPE_MASK) \
+                                        << FUNCID_OEN_WIDTH))
+
+
+/*
+ * Macro to define UUID for services. Apart from defining and initializing a
+ * uuid_t structure, this macro verifies that the first word of the defined UUID
+ * does not equal SMC_UNK. This is to ensure that the caller won't mistake the
+ * returned UUID in x0 for an invalid SMC error return
+ */
+#define DEFINE_SVC_UUID(_name, _tl, _tm, _th, _cl, _ch, \
+               _n0, _n1, _n2, _n3, _n4, _n5) \
+       CASSERT(_tl != SMC_UNK, invalid_svc_uuid);\
+       static const uuid_t _name = { \
+               _tl, _tm, _th, _cl, _ch, \
+               { _n0, _n1, _n2, _n3, _n4, _n5 } \
+       }
+
+/* Return a UUID in the SMC return registers */
+#define SMC_UUID_RET(_h, _uuid) \
+       SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
+                        ((const uint32_t *) &(_uuid))[1], \
+                        ((const uint32_t *) &(_uuid))[2], \
+                        ((const uint32_t *) &(_uuid))[3])
+
+/*******************************************************************************
+ * Function & variable prototypes
+ ******************************************************************************/
+void runtime_svc_init(void);
+extern uint64_t __RT_SVC_DESCS_START__;
+extern uint64_t __RT_SVC_DESCS_END__;
+void init_crash_reporting(void);
+
+#endif /*__ASSEMBLY__*/
+#endif /* __RUNTIME_SVC_H__ */
diff --git a/include/bl31/services/psci.h b/include/bl31/services/psci.h
new file mode 100644 (file)
index 0000000..dd1891c
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PSCI_H__
+#define __PSCI_H__
+
+#include <bakery_lock.h>
+#include <platform_def.h>      /* for PLATFORM_NUM_AFFS */
+
+/*******************************************************************************
+ * Number of affinity instances whose state this psci imp. can track
+ ******************************************************************************/
+#ifdef PLATFORM_NUM_AFFS
+#define PSCI_NUM_AFFS          PLATFORM_NUM_AFFS
+#else
+#define PSCI_NUM_AFFS          (2 * PLATFORM_CORE_COUNT)
+#endif
+
+/*******************************************************************************
+ * Defines for runtime services func ids
+ ******************************************************************************/
+#define PSCI_VERSION                   0x84000000
+#define PSCI_CPU_SUSPEND_AARCH32       0x84000001
+#define PSCI_CPU_SUSPEND_AARCH64       0xc4000001
+#define PSCI_CPU_OFF                   0x84000002
+#define PSCI_CPU_ON_AARCH32            0x84000003
+#define PSCI_CPU_ON_AARCH64            0xc4000003
+#define PSCI_AFFINITY_INFO_AARCH32     0x84000004
+#define PSCI_AFFINITY_INFO_AARCH64     0xc4000004
+#define PSCI_MIG_AARCH32               0x84000005
+#define PSCI_MIG_AARCH64               0xc4000005
+#define PSCI_MIG_INFO_TYPE             0x84000006
+#define PSCI_MIG_INFO_UP_CPU_AARCH32   0x84000007
+#define PSCI_MIG_INFO_UP_CPU_AARCH64   0xc4000007
+#define PSCI_SYSTEM_OFF                        0x84000008
+#define PSCI_SYSTEM_RESET              0x84000009
+#define PSCI_FEATURES                  0x8400000A
+#define PSCI_SYSTEM_SUSPEND_AARCH32    0x8400000E
+#define PSCI_SYSTEM_SUSPEND_AARCH64    0xc400000E
+
+/* Macro to help build the psci capabilities bitfield */
+#define define_psci_cap(x)             (1 << (x & 0x1f))
+
+/*
+ * Number of PSCI calls (above) implemented
+ */
+#define PSCI_NUM_CALLS                 18
+
+/*******************************************************************************
+ * PSCI Migrate and friends
+ ******************************************************************************/
+#define PSCI_TOS_UP_MIG_CAP    0
+#define PSCI_TOS_NOT_UP_MIG_CAP        1
+#define PSCI_TOS_NOT_PRESENT_MP        2
+
+/*******************************************************************************
+ * PSCI CPU_SUSPEND 'power_state' parameter specific defines
+ ******************************************************************************/
+#define PSTATE_ID_SHIFT                0
+#define PSTATE_TYPE_SHIFT      16
+#define PSTATE_AFF_LVL_SHIFT   24
+
+#define PSTATE_ID_MASK         0xffff
+#define PSTATE_TYPE_MASK       0x1
+#define PSTATE_AFF_LVL_MASK    0x3
+#define PSTATE_VALID_MASK     0xFCFE0000
+
+#define PSTATE_TYPE_STANDBY    0x0
+#define PSTATE_TYPE_POWERDOWN  0x1
+
+#define psci_get_pstate_id(pstate)     (((pstate) >> PSTATE_ID_SHIFT) & \
+                                       PSTATE_ID_MASK)
+#define psci_get_pstate_type(pstate)   (((pstate) >> PSTATE_TYPE_SHIFT) & \
+                                       PSTATE_TYPE_MASK)
+#define psci_get_pstate_afflvl(pstate) (((pstate) >> PSTATE_AFF_LVL_SHIFT) & \
+                                       PSTATE_AFF_LVL_MASK)
+#define psci_make_powerstate(state_id, type, afflvl) \
+                       (((state_id) & PSTATE_ID_MASK) << PSTATE_ID_SHIFT) |\
+                       (((type) & PSTATE_TYPE_MASK) << PSTATE_TYPE_SHIFT) |\
+                       (((afflvl) & PSTATE_AFF_LVL_MASK) << PSTATE_AFF_LVL_SHIFT)
+
+/*******************************************************************************
+ * PSCI CPU_FEATURES feature flag specific defines
+ ******************************************************************************/
+/* Features flags for CPU SUSPEND power state parameter format. Bits [1:1] */
+#define FF_PSTATE_SHIFT                1
+#define FF_PSTATE_ORIG         0
+#define FF_PSTATE_EXTENDED     1
+
+/* Features flags for CPU SUSPEND OS Initiated mode support. Bits [0:0] */
+#define FF_MODE_SUPPORT_SHIFT          0
+#define FF_SUPPORTS_OS_INIT_MODE       1
+
+/*******************************************************************************
+ * PSCI version
+ ******************************************************************************/
+#define PSCI_MAJOR_VER         (1 << 16)
+#define PSCI_MINOR_VER         0x0
+
+/*******************************************************************************
+ * PSCI error codes
+ ******************************************************************************/
+#define PSCI_E_SUCCESS         0
+#define PSCI_E_NOT_SUPPORTED   -1
+#define PSCI_E_INVALID_PARAMS  -2
+#define PSCI_E_DENIED          -3
+#define PSCI_E_ALREADY_ON      -4
+#define PSCI_E_ON_PENDING      -5
+#define PSCI_E_INTERN_FAIL     -6
+#define PSCI_E_NOT_PRESENT     -7
+#define PSCI_E_DISABLED                -8
+
+/*******************************************************************************
+ * PSCI affinity state related constants. An affinity instance could be present
+ * or absent physically to cater for asymmetric topologies. If present then it
+ * could in one of the 4 further defined states.
+ ******************************************************************************/
+#define PSCI_STATE_SHIFT       1
+#define PSCI_STATE_MASK                0xff
+
+#define PSCI_AFF_ABSENT                0x0
+#define PSCI_AFF_PRESENT       0x1
+#define PSCI_STATE_ON          0x0
+#define PSCI_STATE_OFF         0x1
+#define PSCI_STATE_ON_PENDING  0x2
+#define PSCI_STATE_SUSPEND     0x3
+
+#define PSCI_INVALID_DATA -1
+
+#define get_phys_state(x)      (x != PSCI_STATE_ON ? \
+                                PSCI_STATE_OFF : PSCI_STATE_ON)
+
+#define psci_validate_power_state(pstate) (pstate & PSTATE_VALID_MASK)
+
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * Structure used to store per-cpu information relevant to the PSCI service.
+ * It is populated in the per-cpu data array. In return we get a guarantee that
+ * this information will not reside on a cache line shared with another cpu.
+ ******************************************************************************/
+typedef struct psci_cpu_data {
+       uint32_t power_state;
+       uint32_t max_phys_off_afflvl;   /* Highest affinity level in physically
+                                          powered off state */
+#if !USE_COHERENT_MEM
+       bakery_info_t pcpu_bakery_info[PSCI_NUM_AFFS];
+#endif
+} psci_cpu_data_t;
+
+/*******************************************************************************
+ * Structure populated by platform specific code to export routines which
+ * perform common low level pm functions
+ ******************************************************************************/
+typedef struct plat_pm_ops {
+       void (*affinst_standby)(unsigned int power_state);
+       int (*affinst_on)(unsigned long mpidr,
+                         unsigned long sec_entrypoint,
+                         unsigned int afflvl,
+                         unsigned int state);
+       void (*affinst_off)(unsigned int afflvl, unsigned int state);
+       void (*affinst_suspend)(unsigned long sec_entrypoint,
+                              unsigned int afflvl,
+                              unsigned int state);
+       void (*affinst_on_finish)(unsigned int afflvl, unsigned int state);
+       void (*affinst_suspend_finish)(unsigned int afflvl,
+                                     unsigned int state);
+       void (*system_off)(void) __dead2;
+       void (*system_reset)(void) __dead2;
+       int (*validate_power_state)(unsigned int power_state);
+       int (*validate_ns_entrypoint)(unsigned long ns_entrypoint);
+       unsigned int (*get_sys_suspend_power_state)(void);
+} plat_pm_ops_t;
+
+/*******************************************************************************
+ * Optional structure populated by the Secure Payload Dispatcher to be given a
+ * chance to perform any bookkeeping before PSCI executes a power mgmt.
+ * operation. It also allows PSCI to determine certain properties of the SP e.g.
+ * migrate capability etc.
+ ******************************************************************************/
+typedef struct spd_pm_ops {
+       void (*svc_on)(uint64_t target_cpu);
+       int32_t (*svc_off)(uint64_t __unused);
+       void (*svc_suspend)(uint64_t __unused);
+       void (*svc_on_finish)(uint64_t __unused);
+       void (*svc_suspend_finish)(uint64_t suspend_level);
+       int32_t (*svc_migrate)(uint64_t from_cpu, uint64_t to_cpu);
+       int32_t (*svc_migrate_info)(uint64_t *resident_cpu);
+       void (*svc_system_off)(void);
+       void (*svc_system_reset)(void);
+} spd_pm_ops_t;
+
+/*******************************************************************************
+ * Function & Data prototypes
+ ******************************************************************************/
+unsigned int psci_version(void);
+int psci_affinity_info(unsigned long, unsigned int);
+int psci_migrate(unsigned long);
+int psci_migrate_info_type(void);
+long psci_migrate_info_up_cpu(void);
+int psci_cpu_on(unsigned long,
+               unsigned long,
+               unsigned long);
+void __dead2 psci_power_down_wfi(void);
+void psci_aff_on_finish_entry(void);
+void psci_aff_suspend_finish_entry(void);
+void psci_register_spd_pm_hook(const spd_pm_ops_t *);
+int psci_get_suspend_stateid_by_mpidr(unsigned long);
+int psci_get_suspend_stateid(void);
+int psci_get_suspend_afflvl(void);
+uint32_t psci_get_max_phys_off_afflvl(void);
+
+uint64_t psci_smc_handler(uint32_t smc_fid,
+                         uint64_t x1,
+                         uint64_t x2,
+                         uint64_t x3,
+                         uint64_t x4,
+                         void *cookie,
+                         void *handle,
+                         uint64_t flags);
+
+/* PSCI setup function */
+int32_t psci_setup(void);
+
+
+#endif /*__ASSEMBLY__*/
+
+
+#endif /* __PSCI_H__ */
diff --git a/include/bl31/services/std_svc.h b/include/bl31/services/std_svc.h
new file mode 100644 (file)
index 0000000..cbd5b62
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __STD_SVC_H__
+#define __STD_SVC_H__
+
+/* SMC function IDs for Standard Service queries */
+
+#define ARM_STD_SVC_CALL_COUNT         0x8400ff00
+#define ARM_STD_SVC_UID                        0x8400ff01
+/*                                     0x8400ff02 is reserved */
+#define ARM_STD_SVC_VERSION            0x8400ff03
+
+/* ARM Standard Service Calls version numbers */
+#define STD_SVC_VERSION_MAJOR          0x0
+#define STD_SVC_VERSION_MINOR          0x1
+
+/* The macros below are used to identify PSCI calls from the SMC function ID */
+#define PSCI_FID_MASK                  0xffe0u
+#define PSCI_FID_VALUE                 0u
+#define is_psci_fid(_fid) \
+       (((_fid) & PSCI_FID_MASK) == PSCI_FID_VALUE)
+
+#endif /* __STD_SVC_H__ */
diff --git a/include/bl32/tsp/platform_tsp.h b/include/bl32/tsp/platform_tsp.h
new file mode 100644 (file)
index 0000000..f6f7391
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_TSP_H__
+
+
+/*******************************************************************************
+ * Mandatory TSP functions (only if platform contains a TSP)
+ ******************************************************************************/
+void tsp_early_platform_setup(void);
+void tsp_plat_arch_setup(void);
+void tsp_platform_setup(void);
+
+
+#define __PLATFORM_H__
+
+#endif
diff --git a/include/bl32/tsp/tsp.h b/include/bl32/tsp/tsp.h
new file mode 100644 (file)
index 0000000..c6578b7
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TSP_H__
+#define __TSP_H__
+
+/*
+ * SMC function IDs that TSP uses to signal various forms of completions
+ * to the secure payload dispatcher.
+ */
+#define TSP_ENTRY_DONE         0xf2000000
+#define TSP_ON_DONE            0xf2000001
+#define TSP_OFF_DONE           0xf2000002
+#define TSP_SUSPEND_DONE       0xf2000003
+#define TSP_RESUME_DONE                0xf2000004
+#define TSP_PREEMPTED          0xf2000005
+#define TSP_SYSTEM_OFF_DONE    0xf2000008
+#define TSP_SYSTEM_RESET_DONE  0xf2000009
+
+/*
+ * Function identifiers to handle FIQs through the synchronous handling model.
+ * If the TSP was previously interrupted then control has to be returned to
+ * the TSPD after handling the interrupt else execution can remain in the TSP.
+ */
+#define TSP_HANDLED_S_EL1_FIQ          0xf2000006
+#define TSP_EL3_FIQ                    0xf2000007
+
+/* SMC function ID that TSP uses to request service from secure monitor */
+#define TSP_GET_ARGS           0xf2001000
+
+/*
+ * Identifiers for various TSP services. Corresponding function IDs (whether
+ * fast or standard) are generated by macros defined below
+ */
+#define TSP_ADD                0x2000
+#define TSP_SUB                0x2001
+#define TSP_MUL                0x2002
+#define TSP_DIV                0x2003
+#define TSP_HANDLE_FIQ_AND_RETURN      0x2004
+
+/*
+ * Generate function IDs for TSP services to be used in SMC calls, by
+ * appropriately setting bit 31 to differentiate standard and fast SMC calls
+ */
+#define TSP_STD_FID(fid)       ((fid) | 0x72000000 | (0 << 31))
+#define TSP_FAST_FID(fid)      ((fid) | 0x72000000 | (1 << 31))
+
+/* SMC function ID to request a previously preempted std smc */
+#define TSP_FID_RESUME         TSP_STD_FID(0x3000)
+
+/*
+ * Identify a TSP service from function ID filtering the last 16 bits from the
+ * SMC function ID
+ */
+#define TSP_BARE_FID(fid)      ((fid) & 0xffff)
+
+/*
+ * Total number of function IDs implemented for services offered to NS clients.
+ * The function IDs are defined above
+ */
+#define TSP_NUM_FID            0x4
+
+/* TSP implementation version numbers */
+#define TSP_VERSION_MAJOR      0x0 /* Major version */
+#define TSP_VERSION_MINOR      0x1 /* Minor version */
+
+/*
+ * Standard Trusted OS Function IDs that fall under Trusted OS call range
+ * according to SMC calling convention
+ */
+#define TOS_CALL_COUNT         0xbf00ff00 /* Number of calls implemented */
+#define TOS_UID                        0xbf00ff01 /* Implementation UID */
+/*                             0xbf00ff02 is reserved */
+#define TOS_CALL_VERSION       0xbf00ff03 /* Trusted OS Call Version */
+
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+
+typedef uint32_t tsp_vector_isn_t;
+
+typedef struct tsp_vectors {
+       tsp_vector_isn_t std_smc_entry;
+       tsp_vector_isn_t fast_smc_entry;
+       tsp_vector_isn_t cpu_on_entry;
+       tsp_vector_isn_t cpu_off_entry;
+       tsp_vector_isn_t cpu_resume_entry;
+       tsp_vector_isn_t cpu_suspend_entry;
+       tsp_vector_isn_t fiq_entry;
+       tsp_vector_isn_t system_off_entry;
+       tsp_vector_isn_t system_reset_entry;
+} tsp_vectors_t;
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __TSP_H__ */
diff --git a/include/common/asm_macros.S b/include/common/asm_macros.S
new file mode 100644 (file)
index 0000000..238fa82
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+
+
+       .macro  func_prologue
+       stp     x29, x30, [sp, #-0x10]!
+       mov     x29,sp
+       .endm
+
+       .macro  func_epilogue
+       ldp     x29, x30, [sp], #0x10
+       .endm
+
+
+       .macro  dcache_line_size  reg, tmp
+       mrs     \tmp, ctr_el0
+       ubfx    \tmp, \tmp, #16, #4
+       mov     \reg, #4
+       lsl     \reg, \reg, \tmp
+       .endm
+
+
+       .macro  icache_line_size  reg, tmp
+       mrs     \tmp, ctr_el0
+       and     \tmp, \tmp, #0xf
+       mov     \reg, #4
+       lsl     \reg, \reg, \tmp
+       .endm
+
+
+       .macro  smc_check  label
+       mrs     x0, esr_el3
+       ubfx    x0, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH
+       cmp     x0, #EC_AARCH64_SMC
+       b.ne    $label
+       .endm
+
+
+       /*
+        * This macro verifies that the a given vector doesn't exceed the
+        * architectural limit of 32 instructions. This is meant to be placed
+        * immedately after the last instruction in the vector. It takes the
+        * vector entry as the parameter
+        */
+       .macro check_vector_size since
+         .if (. - \since) > (32 * 4)
+           .error "Vector exceeds 32 instructions"
+         .endif
+       .endm
+
+       /*
+        * This macro is used to create a function label and place the
+        * code into a separate text section based on the function name
+        * to enable elimination of unused code during linking
+        */
+       .macro func _name
+       .section .text.\_name, "ax"
+       .type \_name, %function
+       \_name:
+       .endm
+
+       /* ---------------------------------------------
+        * Find the type of reset and jump to handler
+        * if present. If the handler is null then it is
+        * a cold boot. The primary cpu will set up the
+        * platform while the secondaries wait for
+        * their turn to be woken up
+        * ---------------------------------------------
+        */
+       .macro wait_for_entrypoint
+wait_for_entrypoint:
+       mrs     x0, mpidr_el1
+       bl      platform_get_entrypoint
+       cbnz    x0, do_warm_boot
+       mrs     x0, mpidr_el1
+       bl      platform_is_primary_cpu
+       cbnz    x0, do_cold_boot
+
+       /* ---------------------------------------------
+        * Perform any platform specific secondary cpu
+        * actions
+        * ---------------------------------------------
+        */
+       bl      plat_secondary_cold_boot_setup
+       b       wait_for_entrypoint
+
+       do_warm_boot:
+       /* ---------------------------------------------
+        * Jump to BL31 for all warm boot init.
+        * ---------------------------------------------
+        */
+       blr     x0
+
+       do_cold_boot:
+       .endm
+
+       /*
+        * This macro declares an array of 1 or more stacks, properly
+        * aligned and in the requested section
+        */
+#define STACK_ALIGN    6
+
+       .macro declare_stack _name, _section, _size, _count
+       .if ((\_size & ((1 << STACK_ALIGN) - 1)) <> 0)
+         .error "Stack size not correctly aligned"
+       .endif
+       .section    \_section, "aw", %nobits
+       .align STACK_ALIGN
+       \_name:
+       .space ((\_count) * (\_size)), 0
+       .endm
+
+       /*
+        * This macro calculates the base address of an MP stack using the
+        * platform_get_core_pos() index, the name of the stack storage and
+        * the size of each stack
+        * In: X0 = MPIDR of CPU whose stack is wanted
+        * Out: X0 = physical address of stack base
+        * Clobber: X30, X1, X2
+        */
+       .macro get_mp_stack _name, _size
+       bl  platform_get_core_pos
+       ldr x2, =(\_name + \_size)
+       mov x1, #\_size
+       madd x0, x0, x1, x2
+       .endm
+
+       /*
+        * This macro calculates the base address of a UP stack using the
+        * name of the stack storage and the size of the stack
+        * Out: X0 = physical address of stack base
+        */
+       .macro get_up_stack _name, _size
+       ldr x0, =(\_name + \_size)
+       .endm
+
+       /*
+        * Helper macro to generate the best mov/movk combinations according
+        * the value to be moved. The 16 bits from '_shift' are tested and
+        * if not zero, they are moved into '_reg' without affecting
+        * other bits.
+        */
+       .macro _mov_imm16 _reg, _val, _shift
+               .if (\_val >> \_shift) & 0xffff
+                       .if (\_val & (1 << \_shift - 1))
+                               movk    \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift
+                       .else
+                               mov     \_reg, \_val & (0xffff << \_shift)
+                       .endif
+               .endif
+       .endm
+
+       /*
+        * Helper macro to load arbitrary values into 32 or 64-bit registers
+        * which generates the best mov/movk combinations. Many base addresses
+        * are 64KB aligned the macro will eliminate updating bits 15:0 in
+        * that case
+        */
+       .macro mov_imm _reg, _val
+               .if (\_val) == 0
+                       mov     \_reg, #0
+               .else
+                       _mov_imm16      \_reg, (\_val), 0
+                       _mov_imm16      \_reg, (\_val), 16
+                       _mov_imm16      \_reg, (\_val), 32
+                       _mov_imm16      \_reg, (\_val), 48
+               .endif
+       .endm
diff --git a/include/common/assert_macros.S b/include/common/assert_macros.S
new file mode 100644 (file)
index 0000000..807972f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+       /*
+        * Assembler macro to enable asm_assert. Use this macro wherever
+        * assert is required in assembly. Please note that the macro makes
+        * use of label '300' to provide the logic and the caller
+        * should make sure that this label is not used to branch prior
+        * to calling this macro.
+        */
+#define ASM_ASSERT(_cc) \
+.ifndef .L_assert_filename ;\
+       .pushsection .rodata.str1.1, "aS" ;\
+       .L_assert_filename: ;\
+                       .string __FILE__ ;\
+       .popsection ;\
+.endif ;\
+       b._cc   300f ;\
+       adr     x0, .L_assert_filename ;\
+       mov     x1, __LINE__ ;\
+       b       asm_assert ;\
+300:
diff --git a/include/common/auth.h b/include/common/auth.h
new file mode 100644 (file)
index 0000000..3c3a6bd
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AUTH_H_
+#define AUTH_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * Authentication infrastructure for Trusted Boot
+ *
+ * This infrastructure provides an API to access the authentication module. This
+ * module will implement the required operations for Trusted Boot by creating an
+ * instance of the structure 'auth_mod_t'. This instance must be called
+ * 'auth_mod' and must provide the functions to initialize the module and
+ * verify the authenticity of the images.
+ */
+
+/* Objects (images and certificates) involved in the TBB process */
+enum {
+       AUTH_BL2_IMG_CERT,
+       AUTH_BL2_IMG,
+       AUTH_TRUSTED_KEY_CERT,
+       AUTH_BL30_KEY_CERT,
+       AUTH_BL30_IMG_CERT,
+       AUTH_BL30_IMG,
+       AUTH_BL31_KEY_CERT,
+       AUTH_BL31_IMG_CERT,
+       AUTH_BL31_IMG,
+       AUTH_BL32_KEY_CERT,
+       AUTH_BL32_IMG_CERT,
+       AUTH_BL32_IMG,
+       AUTH_BL33_KEY_CERT,
+       AUTH_BL33_IMG_CERT,
+       AUTH_BL33_IMG,
+       AUTH_NUM_OBJ
+};
+
+/* Authentication module structure */
+typedef struct auth_mod_s {
+       /* [mandatory] Module name. Printed to the log during initialization */
+       const char *name;
+
+       /* [mandatory] Initialize the authentication module */
+       int (*init)(void);
+
+       /* [mandatory] This function will be called to authenticate a new
+        * object loaded into memory. The obj_id corresponds to one of the
+        * values in the enumeration above */
+       int (*verify)(unsigned int obj_id, uintptr_t obj_buf, size_t len);
+} auth_mod_t;
+
+/* This variable must be instantiated by the authentication module */
+extern const auth_mod_t auth_mod;
+
+/* Public functions */
+void auth_init(void);
+int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len);
+
+#endif /* AUTH_H_ */
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
new file mode 100644 (file)
index 0000000..0959c89
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BL_COMMON_H__
+#define __BL_COMMON_H__
+
+#define SECURE         0x0
+#define NON_SECURE     0x1
+#define sec_state_is_valid(s) (((s) == SECURE) || ((s) == NON_SECURE))
+
+#define UP     1
+#define DOWN   0
+
+/*******************************************************************************
+ * Constants to identify the location of a memory region in a given memory
+ * layout.
+******************************************************************************/
+#define TOP    0x1
+#define BOTTOM !TOP
+
+/******************************************************************************
+ * Opcode passed in x0 to tell next EL that we want to run an image.
+ * Corresponds to the function ID of the only SMC that the BL1 exception
+ * handlers service. That's why the chosen value is the first function ID of
+ * the ARM SMC64 range.
+ *****************************************************************************/
+#define RUN_IMAGE      0xC0000000
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the
+ * 'entry_point_info' structure at their correct offsets.
+ ******************************************************************************/
+#define ENTRY_POINT_INFO_PC_OFFSET     0x08
+#define ENTRY_POINT_INFO_ARGS_OFFSET   0x18
+
+#define PARAM_EP_SECURITY_MASK    0x1
+#define GET_SECURITY_STATE(x) (x & PARAM_EP_SECURITY_MASK)
+#define SET_SECURITY_STATE(x, security) \
+                       ((x) = ((x) & ~PARAM_EP_SECURITY_MASK) | (security))
+
+#define EP_EE_MASK     0x2
+#define EP_EE_LITTLE   0x0
+#define EP_EE_BIG      0x2
+#define EP_GET_EE(x) (x & EP_EE_MASK)
+#define EP_SET_EE(x, ee) ((x) = ((x) & ~EP_EE_MASK) | (ee))
+
+#define EP_ST_MASK     0x4
+#define EP_ST_DISABLE  0x0
+#define EP_ST_ENABLE   0x4
+#define EP_GET_ST(x) (x & EP_ST_MASK)
+#define EP_SET_ST(x, ee) ((x) = ((x) & ~EP_ST_MASK) | (ee))
+
+#define PARAM_EP     0x01
+#define PARAM_IMAGE_BINARY  0x02
+#define PARAM_BL31       0x03
+
+#define VERSION_1              0x01
+
+#define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \
+       (_p)->h.type = (uint8_t)(_type); \
+       (_p)->h.version = (uint8_t)(_ver); \
+       (_p)->h.size = (uint16_t)sizeof(*_p); \
+       (_p)->h.attr = (uint32_t)(_attr) ; \
+       } while (0)
+
+/*******************************************************************************
+ * Constant that indicates if this is the first version of the reset handler
+ * contained in an image. This will be the case when the image is BL1 or when
+ * its BL3-1 and RESET_TO_BL31 is true. This constant enables a subsequent
+ * version of the reset handler to perform actions that override the ones
+ * performed in the first version of the code. This will be required when the
+ * first version exists in an un-modifiable image e.g. a BootROM image.
+ ******************************************************************************/
+#if IMAGE_BL1 || (IMAGE_BL31 && RESET_TO_BL31)
+#define FIRST_RESET_HANDLER_CALL
+#endif
+
+#ifndef __ASSEMBLY__
+#include <cdefs.h> /* For __dead2 */
+#include <cassert.h>
+#include <stdint.h>
+#include <stddef.h>
+
+/*******************************************************************************
+ * Structure used for telling the next BL how much of a particular type of
+ * memory is available for its use and how much is already used.
+ ******************************************************************************/
+typedef struct meminfo {
+       uint64_t total_base;
+       size_t total_size;
+       uint64_t free_base;
+       size_t free_size;
+} meminfo_t;
+
+typedef struct aapcs64_params {
+       unsigned long arg0;
+       unsigned long arg1;
+       unsigned long arg2;
+       unsigned long arg3;
+       unsigned long arg4;
+       unsigned long arg5;
+       unsigned long arg6;
+       unsigned long arg7;
+} aapcs64_params_t;
+
+/***************************************************************************
+ * This structure provides version information and the size of the
+ * structure, attributes for the structure it represents
+ ***************************************************************************/
+typedef struct param_header {
+       uint8_t type;           /* type of the structure */
+       uint8_t version;    /* version of this structure */
+       uint16_t size;      /* size of this structure in bytes */
+       uint32_t attr;      /* attributes: unused bits SBZ */
+} param_header_t;
+
+/*****************************************************************************
+ * This structure represents the superset of information needed while
+ * switching exception levels. The only two mechanisms to do so are
+ * ERET & SMC. Security state is indicated using bit zero of header
+ * attribute
+ * NOTE: BL1 expects entrypoint followed by spsr while processing
+ * SMC to jump to BL31 from the start of entry_point_info
+ *****************************************************************************/
+typedef struct entry_point_info {
+       param_header_t h;
+       uintptr_t pc;
+       uint32_t spsr;
+       aapcs64_params_t args;
+} entry_point_info_t;
+
+/*****************************************************************************
+ * Image info binary provides information from the image loader that
+ * can be used by the firmware to manage available trusted RAM.
+ * More advanced firmware image formats can provide additional
+ * information that enables optimization or greater flexibility in the
+ * common firmware code
+ *****************************************************************************/
+typedef struct image_info {
+       param_header_t h;
+       uintptr_t image_base;   /* physical address of base of image */
+       uint32_t image_size;    /* bytes read from image file */
+} image_info_t;
+
+/*******************************************************************************
+ * This structure represents the superset of information that can be passed to
+ * BL31 e.g. while passing control to it from BL2. The BL32 parameters will be
+ * populated only if BL2 detects its presence. A pointer to a structure of this
+ * type should be passed in X3 to BL31's cold boot entrypoint
+ *
+ * Use of this structure and the X3 parameter is not mandatory: the BL3-1
+ * platform code can use other mechanisms to provide the necessary information
+ * about BL3-2 and BL3-3 to the common and SPD code.
+ *
+ * BL3-1 image information is mandatory if this structure is used. If either of
+ * the optional BL3-2 and BL3-3 image information is not provided, this is
+ * indicated by the respective image_info pointers being zero.
+ ******************************************************************************/
+typedef struct bl31_params {
+       param_header_t h;
+       image_info_t *bl31_image_info;
+       entry_point_info_t *bl32_ep_info;
+       image_info_t *bl32_image_info;
+       entry_point_info_t *bl33_ep_info;
+       image_info_t *bl33_image_info;
+} bl31_params_t;
+
+
+/*
+ * Compile time assertions related to the 'entry_point_info' structure to
+ * ensure that the assembler and the compiler view of the offsets of
+ * the structure members is the same.
+ */
+CASSERT(ENTRY_POINT_INFO_PC_OFFSET ==
+               __builtin_offsetof(entry_point_info_t, pc), \
+               assert_BL31_pc_offset_mismatch);
+
+CASSERT(ENTRY_POINT_INFO_ARGS_OFFSET == \
+               __builtin_offsetof(entry_point_info_t, args), \
+               assert_BL31_args_offset_mismatch);
+
+CASSERT(sizeof(unsigned long) ==
+               __builtin_offsetof(entry_point_info_t, spsr) - \
+               __builtin_offsetof(entry_point_info_t, pc), \
+               assert_entrypoint_and_spsr_should_be_adjacent);
+
+/*******************************************************************************
+ * Function & variable prototypes
+ ******************************************************************************/
+unsigned long page_align(unsigned long, unsigned);
+void change_security_state(unsigned int);
+unsigned long image_size(const char *);
+int load_image(meminfo_t *mem_layout,
+              const char *image_name,
+              uint64_t image_base,
+              image_info_t *image_data,
+              entry_point_info_t *entry_point_info);
+extern const char build_message[];
+extern const char version_string[];
+
+void reserve_mem(uint64_t *free_base, size_t *free_size,
+               uint64_t addr, size_t size);
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* __BL_COMMON_H__ */
diff --git a/include/common/debug.h b/include/common/debug.h
new file mode 100644 (file)
index 0000000..a8dcb8d
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#include <stdio.h>
+
+/* The log output macros print output to the console. These macros produce
+ * compiled log output only if the LOG_LEVEL defined in the makefile (or the
+ * make command line) is greater or equal than the level required for that
+ * type of log output.
+ * The format expected is the same as for printf(). For example:
+ * INFO("Info %s.\n", "message")    -> INFO:    Info message.
+ * WARN("Warning %s.\n", "message") -> WARNING: Warning message.
+ */
+
+#define LOG_LEVEL_NONE                 0
+#define LOG_LEVEL_ERROR                        10
+#define LOG_LEVEL_NOTICE               20
+#define LOG_LEVEL_WARNING              30
+#define LOG_LEVEL_INFO                 40
+#define LOG_LEVEL_VERBOSE              50
+
+
+#if LOG_LEVEL >= LOG_LEVEL_NOTICE
+# define NOTICE(...)   tf_printf("NOTICE:  " __VA_ARGS__)
+#else
+# define NOTICE(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_ERROR
+# define ERROR(...)    tf_printf("ERROR:   " __VA_ARGS__)
+#else
+# define ERROR(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_WARNING
+# define WARN(...)     tf_printf("WARNING: " __VA_ARGS__)
+#else
+# define WARN(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+# define INFO(...)     tf_printf("INFO:    " __VA_ARGS__)
+#else
+# define INFO(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+# define VERBOSE(...)  tf_printf("VERBOSE: " __VA_ARGS__)
+#else
+# define VERBOSE(...)
+#endif
+
+
+void __dead2 do_panic(void);
+#define panic()        do_panic()
+
+void tf_printf(const char *fmt, ...);
+
+#endif /* __DEBUG_H__ */
diff --git a/include/common/firmware_image_package.h b/include/common/firmware_image_package.h
new file mode 100644 (file)
index 0000000..8fb669e
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FIRMWARE_IMAGE_PACKAGE_H__
+#define __FIRMWARE_IMAGE_PACKAGE_H__
+
+#include <stdint.h>
+#include <uuid.h>
+
+/* This is used as a signature to validate the blob header */
+#define TOC_HEADER_NAME        0xAA640001
+
+
+/* ToC Entry UUIDs */
+#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \
+       {0x0becf95f, 0x224d, 0x4d3e, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} }
+#define UUID_SCP_FIRMWARE_BL30 \
+       {0x3dfd6697, 0xbe89, 0x49e8, 0xae, 0x5d, {0x78, 0xa1, 0x40, 0x60, 0x82, 0x13} }
+#define UUID_EL3_RUNTIME_FIRMWARE_BL31 \
+       {0x6d08d447, 0xfe4c, 0x4698, 0x9b, 0x95, {0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x00} }
+#define UUID_SECURE_PAYLOAD_BL32 \
+       {0x89e1d005, 0xdc53, 0x4713, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} }
+#define UUID_NON_TRUSTED_FIRMWARE_BL33 \
+       {0xa7eed0d6, 0xeafc, 0x4bd5, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} }
+/* Key certificates */
+#define UUID_ROT_KEY_CERT \
+       {0x721d2d86, 0x60f8, 0x11e4, 0x92, 0x0b, {0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24} }
+#define UUID_TRUSTED_KEY_CERT \
+       {0x90e87e82, 0x60f8, 0x11e4, 0xa1, 0xb4, {0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c} }
+#define UUID_NON_TRUSTED_WORLD_KEY_CERT \
+       {0x3d87671c, 0x635f, 0x11e4, 0x97, 0x8d, {0x27, 0xc0, 0xc7, 0x14, 0x8a, 0xbd} }
+#define UUID_SCP_FIRMWARE_BL30_KEY_CERT \
+       {0xa1214202, 0x60f8, 0x11e4, 0x8d, 0x9b, {0xf3, 0x3c, 0x0e, 0x15, 0xa0, 0x14} }
+#define UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT \
+       {0xccbeb88a, 0x60f9, 0x11e4, 0x9a, 0xd0, {0xeb, 0x48, 0x22, 0xd8, 0xdc, 0xf8} }
+#define UUID_SECURE_PAYLOAD_BL32_KEY_CERT \
+       {0x03d67794, 0x60fb, 0x11e4, 0x85, 0xdd, {0xb7, 0x10, 0x5b, 0x8c, 0xee, 0x04} }
+#define UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT \
+       {0x2a83d58a, 0x60fb, 0x11e4, 0x8a, 0xaf, {0xdf, 0x30, 0xbb, 0xc4, 0x98, 0x59} }
+/* Content certificates */
+#define UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT \
+       {0xea69e2d6, 0x635d, 0x11e4, 0x8d, 0x8c, {0x9f, 0xba, 0xbe, 0x99, 0x56, 0xa5} }
+#define UUID_SCP_FIRMWARE_BL30_CERT \
+       {0x046fbe44, 0x635e, 0x11e4, 0xb2, 0x8b, {0x73, 0xd8, 0xea, 0xae, 0x96, 0x56} }
+#define UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT \
+       {0x200cb2e2, 0x635e, 0x11e4, 0x9c, 0xe8, {0xab, 0xcc, 0xf9, 0x2b, 0xb6, 0x66} }
+#define UUID_SECURE_PAYLOAD_BL32_CERT \
+       {0x11449fa4, 0x635e, 0x11e4, 0x87, 0x28, {0x3f, 0x05, 0x72, 0x2a, 0xf3, 0x3d} }
+#define UUID_NON_TRUSTED_FIRMWARE_BL33_CERT \
+       {0xf3c1c48e, 0x635d, 0x11e4, 0xa7, 0xa9, {0x87, 0xee, 0x40, 0xb2, 0x3f, 0xa7} }
+
+typedef struct fip_toc_header {
+       uint32_t        name;
+       uint32_t        serial_number;
+       uint64_t        flags;
+} fip_toc_header_t;
+
+typedef struct fip_toc_entry {
+       uuid_t          uuid;
+       uint64_t        offset_address;
+       uint64_t        size;
+       uint64_t        flags;
+} fip_toc_entry_t;
+
+#endif /* __FIRMWARE_IMAGE_PACKAGE_H__ */
diff --git a/include/drivers/arm/arm_gic.h b/include/drivers/arm/arm_gic.h
new file mode 100644 (file)
index 0000000..9ab1a95
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARM_GIC_H__
+#define __ARM_GIC_H__
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * Function declarations
+ ******************************************************************************/
+void arm_gic_init(unsigned int gicc_base,
+               unsigned int gicd_base,
+               unsigned long gicr_base,
+               const unsigned int *irq_sec_ptr,
+               unsigned int num_irqs);
+void arm_gic_setup(void);
+void arm_gic_cpuif_deactivate(void);
+void arm_gic_cpuif_setup(void);
+void arm_gic_pcpu_distif_setup(void);
+
+uint32_t arm_gic_interrupt_type_to_line(uint32_t type,
+                               uint32_t security_state);
+uint32_t arm_gic_get_pending_interrupt_type(void);
+uint32_t arm_gic_get_pending_interrupt_id(void);
+uint32_t arm_gic_acknowledge_interrupt(void);
+void arm_gic_end_of_interrupt(uint32_t id);
+uint32_t arm_gic_get_interrupt_type(uint32_t id);
+
+#endif /* __GIC_H__ */
diff --git a/include/drivers/arm/cci400.h b/include/drivers/arm/cci400.h
new file mode 100644 (file)
index 0000000..7756bdf
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CCI_400_H__
+#define __CCI_400_H__
+
+/* Slave interface offsets from PERIPHBASE */
+#define SLAVE_IFACE4_OFFSET            0x5000
+#define SLAVE_IFACE3_OFFSET            0x4000
+#define SLAVE_IFACE2_OFFSET            0x3000
+#define SLAVE_IFACE1_OFFSET            0x2000
+#define SLAVE_IFACE0_OFFSET            0x1000
+#define SLAVE_IFACE_OFFSET(index)      SLAVE_IFACE0_OFFSET +   \
+                                       (0x1000 * (index))
+
+/* Control and ID register offsets */
+#define CTRL_OVERRIDE_REG              0x0
+#define SPEC_CTRL_REG                  0x4
+#define SECURE_ACCESS_REG              0x8
+#define STATUS_REG                     0xc
+#define IMPRECISE_ERR_REG              0x10
+#define PERFMON_CTRL_REG               0x100
+
+/* Slave interface register offsets */
+#define SNOOP_CTRL_REG                 0x0
+#define SH_OVERRIDE_REG                        0x4
+#define READ_CHNL_QOS_VAL_OVERRIDE_REG 0x100
+#define WRITE_CHNL_QOS_VAL_OVERRIDE_REG        0x104
+#define QOS_CTRL_REG                   0x10c
+#define MAX_OT_REG                     0x110
+#define TARGET_LATENCY_REG             0x130
+#define LATENCY_REGULATION_REG         0x134
+#define QOS_RANGE_REG                  0x138
+
+/* Snoop Control register bit definitions */
+#define DVM_EN_BIT                     (1 << 1)
+#define SNOOP_EN_BIT                   (1 << 0)
+
+/* Status register bit definitions */
+#define CHANGE_PENDING_BIT             (1 << 0)
+
+#ifndef __ASSEMBLY__
+
+/* Function declarations */
+
+/*
+ * The CCI-400 driver must be initialized with the base address of the
+ * CCI-400 device in the platform memory map, and the cluster indices for
+ * the CCI-400 slave interfaces 3 and 4 respectively. These are the fully
+ * coherent ACE slave interfaces of CCI-400.
+ * The cluster indices must either be 0 or 1, corresponding to the level 1
+ * affinity instance of the mpidr representing the cluster. A negative cluster
+ * index indicates that no cluster is present on that slave interface.
+ */
+void cci_init(unsigned long cci_base,
+               int slave_iface3_cluster_ix,
+               int slave_iface4_cluster_ix);
+
+void cci_enable_cluster_coherency(unsigned long mpidr);
+void cci_disable_cluster_coherency(unsigned long mpidr);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __CCI_400_H__ */
diff --git a/include/drivers/arm/gic_v2.h b/include/drivers/arm/gic_v2.h
new file mode 100644 (file)
index 0000000..a2d3eee
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GIC_V2_H__
+#define __GIC_V2_H__
+
+
+#define GIC400_NUM_SPIS                480
+#define MAX_PPIS               14
+#define MAX_SGIS               16
+
+#define MIN_SGI_ID             0
+#define MIN_PPI_ID             16
+#define MIN_SPI_ID             32
+
+#define GRP0                   0
+#define GRP1                   1
+#define GIC_PRI_MASK           0xff
+#define GIC_HIGHEST_SEC_PRIORITY 0
+#define GIC_LOWEST_SEC_PRIORITY        127
+#define GIC_HIGHEST_NS_PRIORITY        128
+#define GIC_LOWEST_NS_PRIORITY 254 /* 255 would disable an interrupt */
+#define GIC_SPURIOUS_INTERRUPT 1023
+#define GIC_TARGET_CPU_MASK    0xff
+
+#define ENABLE_GRP0            (1 << 0)
+#define ENABLE_GRP1            (1 << 1)
+
+/* Distributor interface definitions */
+#define GICD_CTLR              0x0
+#define GICD_TYPER             0x4
+#define GICD_IGROUPR           0x80
+#define GICD_ISENABLER         0x100
+#define GICD_ICENABLER         0x180
+#define GICD_ISPENDR           0x200
+#define GICD_ICPENDR           0x280
+#define GICD_ISACTIVER         0x300
+#define GICD_ICACTIVER         0x380
+#define GICD_IPRIORITYR                0x400
+#define GICD_ITARGETSR         0x800
+#define GICD_ICFGR             0xC00
+#define GICD_SGIR              0xF00
+#define GICD_CPENDSGIR         0xF10
+#define GICD_SPENDSGIR         0xF20
+
+#define IGROUPR_SHIFT          5
+#define ISENABLER_SHIFT                5
+#define ICENABLER_SHIFT                ISENABLER_SHIFT
+#define ISPENDR_SHIFT          5
+#define ICPENDR_SHIFT          ISPENDR_SHIFT
+#define ISACTIVER_SHIFT                5
+#define ICACTIVER_SHIFT                ISACTIVER_SHIFT
+#define IPRIORITYR_SHIFT       2
+#define ITARGETSR_SHIFT                2
+#define ICFGR_SHIFT            4
+#define CPENDSGIR_SHIFT                2
+#define SPENDSGIR_SHIFT                CPENDSGIR_SHIFT
+
+/* GICD_TYPER bit definitions */
+#define IT_LINES_NO_MASK       0x1f
+
+/* Physical CPU Interface registers */
+#define GICC_CTLR              0x0
+#define GICC_PMR               0x4
+#define GICC_BPR               0x8
+#define GICC_IAR               0xC
+#define GICC_EOIR              0x10
+#define GICC_RPR               0x14
+#define GICC_HPPIR             0x18
+#define GICC_AHPPIR            0x28
+#define GICC_IIDR              0xFC
+#define GICC_DIR               0x1000
+#define GICC_PRIODROP           GICC_EOIR
+
+/* GICC_CTLR bit definitions */
+#define EOI_MODE_NS            (1 << 10)
+#define EOI_MODE_S             (1 << 9)
+#define IRQ_BYP_DIS_GRP1       (1 << 8)
+#define FIQ_BYP_DIS_GRP1       (1 << 7)
+#define IRQ_BYP_DIS_GRP0       (1 << 6)
+#define FIQ_BYP_DIS_GRP0       (1 << 5)
+#define CBPR                   (1 << 4)
+#define FIQ_EN                 (1 << 3)
+#define ACK_CTL                        (1 << 2)
+
+/* GICC_IIDR bit masks and shifts */
+#define GICC_IIDR_PID_SHIFT    20
+#define GICC_IIDR_ARCH_SHIFT   16
+#define GICC_IIDR_REV_SHIFT    12
+#define GICC_IIDR_IMP_SHIFT    0
+
+#define GICC_IIDR_PID_MASK     0xfff
+#define GICC_IIDR_ARCH_MASK    0xf
+#define GICC_IIDR_REV_MASK     0xf
+#define GICC_IIDR_IMP_MASK     0xfff
+
+/* HYP view virtual CPU Interface registers */
+#define GICH_CTL               0x0
+#define GICH_VTR               0x4
+#define GICH_ELRSR0            0x30
+#define GICH_ELRSR1            0x34
+#define GICH_APR0              0xF0
+#define GICH_LR_BASE           0x100
+
+/* Virtual CPU Interface registers */
+#define GICV_CTL               0x0
+#define GICV_PRIMASK           0x4
+#define GICV_BP                        0x8
+#define GICV_INTACK            0xC
+#define GICV_EOI               0x10
+#define GICV_RUNNINGPRI                0x14
+#define GICV_HIGHESTPEND       0x18
+#define GICV_DEACTIVATE                0x1000
+
+#ifndef __ASSEMBLY__
+
+#include <mmio.h>
+
+
+/*******************************************************************************
+ * GIC Distributor function prototypes
+ ******************************************************************************/
+
+unsigned int gicd_read_igroupr(unsigned int, unsigned int);
+unsigned int gicd_read_isenabler(unsigned int, unsigned int);
+unsigned int gicd_read_icenabler(unsigned int, unsigned int);
+unsigned int gicd_read_ispendr(unsigned int, unsigned int);
+unsigned int gicd_read_icpendr(unsigned int, unsigned int);
+unsigned int gicd_read_isactiver(unsigned int, unsigned int);
+unsigned int gicd_read_icactiver(unsigned int, unsigned int);
+unsigned int gicd_read_ipriorityr(unsigned int, unsigned int);
+unsigned int gicd_read_itargetsr(unsigned int, unsigned int);
+unsigned int gicd_read_icfgr(unsigned int, unsigned int);
+unsigned int gicd_read_cpendsgir(unsigned int, unsigned int);
+unsigned int gicd_read_spendsgir(unsigned int, unsigned int);
+void gicd_write_igroupr(unsigned int, unsigned int, unsigned int);
+void gicd_write_isenabler(unsigned int, unsigned int, unsigned int);
+void gicd_write_icenabler(unsigned int, unsigned int, unsigned int);
+void gicd_write_ispendr(unsigned int, unsigned int, unsigned int);
+void gicd_write_icpendr(unsigned int, unsigned int, unsigned int);
+void gicd_write_isactiver(unsigned int, unsigned int, unsigned int);
+void gicd_write_icactiver(unsigned int, unsigned int, unsigned int);
+void gicd_write_ipriorityr(unsigned int, unsigned int, unsigned int);
+void gicd_write_itargetsr(unsigned int, unsigned int, unsigned int);
+void gicd_write_icfgr(unsigned int, unsigned int, unsigned int);
+void gicd_write_cpendsgir(unsigned int, unsigned int, unsigned int);
+void gicd_write_spendsgir(unsigned int, unsigned int, unsigned int);
+unsigned int gicd_get_igroupr(unsigned int, unsigned int);
+void gicd_set_igroupr(unsigned int, unsigned int);
+void gicd_clr_igroupr(unsigned int, unsigned int);
+void gicd_set_isenabler(unsigned int, unsigned int);
+void gicd_set_icenabler(unsigned int, unsigned int);
+void gicd_set_ispendr(unsigned int, unsigned int);
+void gicd_set_icpendr(unsigned int, unsigned int);
+void gicd_set_isactiver(unsigned int, unsigned int);
+void gicd_set_icactiver(unsigned int, unsigned int);
+void gicd_set_ipriorityr(unsigned int, unsigned int, unsigned int);
+void gicd_set_itargetsr(unsigned int, unsigned int, unsigned int);
+
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+
+static inline unsigned int gicd_read_ctlr(unsigned int base)
+{
+       return mmio_read_32(base + GICD_CTLR);
+}
+
+static inline unsigned int gicd_read_typer(unsigned int base)
+{
+       return mmio_read_32(base + GICD_TYPER);
+}
+
+static inline unsigned int gicd_read_sgir(unsigned int base)
+{
+       return mmio_read_32(base + GICD_SGIR);
+}
+
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+
+static inline void gicd_write_ctlr(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICD_CTLR, val);
+}
+
+static inline void gicd_write_sgir(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICD_SGIR, val);
+}
+
+
+/*******************************************************************************
+ * GIC CPU interface accessors for reading entire registers
+ ******************************************************************************/
+
+static inline unsigned int gicc_read_ctlr(unsigned int base)
+{
+       return mmio_read_32(base + GICC_CTLR);
+}
+
+static inline unsigned int gicc_read_pmr(unsigned int base)
+{
+       return mmio_read_32(base + GICC_PMR);
+}
+
+static inline unsigned int gicc_read_BPR(unsigned int base)
+{
+       return mmio_read_32(base + GICC_BPR);
+}
+
+static inline unsigned int gicc_read_IAR(unsigned int base)
+{
+       return mmio_read_32(base + GICC_IAR);
+}
+
+static inline unsigned int gicc_read_EOIR(unsigned int base)
+{
+       return mmio_read_32(base + GICC_EOIR);
+}
+
+static inline unsigned int gicc_read_hppir(unsigned int base)
+{
+       return mmio_read_32(base + GICC_HPPIR);
+}
+
+static inline unsigned int gicc_read_ahppir(unsigned int base)
+{
+       return mmio_read_32(base + GICC_AHPPIR);
+}
+
+static inline unsigned int gicc_read_dir(unsigned int base)
+{
+       return mmio_read_32(base + GICC_DIR);
+}
+
+static inline unsigned int gicc_read_iidr(unsigned int base)
+{
+       return mmio_read_32(base + GICC_IIDR);
+}
+
+
+/*******************************************************************************
+ * GIC CPU interface accessors for writing entire registers
+ ******************************************************************************/
+
+static inline void gicc_write_ctlr(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICC_CTLR, val);
+}
+
+static inline void gicc_write_pmr(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICC_PMR, val);
+}
+
+static inline void gicc_write_BPR(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICC_BPR, val);
+}
+
+
+static inline void gicc_write_IAR(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICC_IAR, val);
+}
+
+static inline void gicc_write_EOIR(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICC_EOIR, val);
+}
+
+static inline void gicc_write_hppir(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICC_HPPIR, val);
+}
+
+static inline void gicc_write_dir(unsigned int base, unsigned int val)
+{
+       mmio_write_32(base + GICC_DIR, val);
+}
+
+/*******************************************************************************
+ * Prototype of function to map an interrupt type to the interrupt line used to
+ * signal it.
+ ******************************************************************************/
+uint32_t gicv2_interrupt_type_to_line(uint32_t cpuif_base, uint32_t type);
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* __GIC_V2_H__ */
diff --git a/include/drivers/arm/gic_v3.h b/include/drivers/arm/gic_v3.h
new file mode 100644 (file)
index 0000000..c410626
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GIC_V3_H__
+#define __GIC_V3_H__
+
+#include <mmio.h>
+#include <stdint.h>
+
+
+/* GICv3 Re-distributor interface registers & shifts */
+#define GICR_PCPUBASE_SHIFT    0x11
+#define GICR_TYPER             0x08
+#define GICR_WAKER             0x14
+
+/* GICR_WAKER bit definitions */
+#define WAKER_CA               (1UL << 2)
+#define WAKER_PS               (1UL << 1)
+
+/* GICR_TYPER bit definitions */
+#define GICR_TYPER_AFF_SHIFT   32
+#define GICR_TYPER_AFF_MASK    0xffffffff
+#define GICR_TYPER_LAST                (1UL << 4)
+
+/* GICv3 ICC_SRE register bit definitions*/
+#define ICC_SRE_EN             (1UL << 3)
+#define ICC_SRE_SRE            (1UL << 0)
+
+/*******************************************************************************
+ * GICv3 defintions
+ ******************************************************************************/
+#define GICV3_AFFLVL_MASK      0xff
+#define GICV3_AFF0_SHIFT       0
+#define GICV3_AFF1_SHIFT       8
+#define GICV3_AFF2_SHIFT       16
+#define GICV3_AFF3_SHIFT       24
+#define GICV3_AFFINITY_MASK    0xffffffff
+
+/*******************************************************************************
+ * Function prototypes
+ ******************************************************************************/
+uintptr_t gicv3_get_rdist(uintptr_t gicr_base, uint64_t mpidr);
+
+/*******************************************************************************
+ * GIC Redistributor interface accessors
+ ******************************************************************************/
+static inline uint32_t gicr_read_waker(uintptr_t base)
+{
+       return mmio_read_32(base + GICR_WAKER);
+}
+
+static inline void gicr_write_waker(uintptr_t base, uint32_t val)
+{
+       mmio_write_32(base + GICR_WAKER, val);
+}
+
+static inline uint64_t gicr_read_typer(uintptr_t base)
+{
+       return mmio_read_64(base + GICR_TYPER);
+}
+
+
+#endif /* __GIC_V3_H__ */
diff --git a/include/drivers/arm/gpio.h b/include/drivers/arm/gpio.h
new file mode 100644 (file)
index 0000000..06a41ad
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GPIO_H__
+#define __GPIO_H__
+
+extern int gpio_direction_input(unsigned int gpio);
+extern int gpio_direction_output(unsigned int gpio);
+extern int gpio_get_value(unsigned int gpio);
+extern int gpio_set_value(unsigned int gpio, unsigned int value);
+extern int gpio_register_device(unsigned int base);
+
+#endif /* __GPIO_H__ */
diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h
new file mode 100644 (file)
index 0000000..7c4df62
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PL011_H__
+#define __PL011_H__
+
+/* PL011 Registers */
+#define UARTDR                    0x000
+#define UARTRSR                   0x004
+#define UARTECR                   0x004
+#define UARTFR                    0x018
+#define UARTILPR                  0x020
+#define UARTIBRD                  0x024
+#define UARTFBRD                  0x028
+#define UARTLCR_H                 0x02C
+#define UARTCR                    0x030
+#define UARTIFLS                  0x034
+#define UARTIMSC                  0x038
+#define UARTRIS                   0x03C
+#define UARTMIS                   0x040
+#define UARTICR                   0x044
+#define UARTDMACR                 0x048
+
+/* Data status bits */
+#define UART_DATA_ERROR_MASK      0x0F00
+
+/* Status reg bits */
+#define UART_STATUS_ERROR_MASK    0x0F
+
+/* Flag reg bits */
+#define PL011_UARTFR_RI           (1 << 8)     /* Ring indicator */
+#define PL011_UARTFR_TXFE         (1 << 7)     /* Transmit FIFO empty */
+#define PL011_UARTFR_RXFF         (1 << 6)     /* Receive  FIFO full */
+#define PL011_UARTFR_TXFF         (1 << 5)     /* Transmit FIFO full */
+#define PL011_UARTFR_RXFE         (1 << 4)     /* Receive  FIFO empty */
+#define PL011_UARTFR_BUSY         (1 << 3)     /* UART busy */
+#define PL011_UARTFR_DCD          (1 << 2)     /* Data carrier detect */
+#define PL011_UARTFR_DSR          (1 << 1)     /* Data set ready */
+#define PL011_UARTFR_CTS          (1 << 0)     /* Clear to send */
+
+#define PL011_UARTFR_TXFF_BIT  5       /* Transmit FIFO full bit in UARTFR register */
+#define PL011_UARTFR_RXFE_BIT  4       /* Receive FIFO empty bit in UARTFR register */
+
+/* Control reg bits */
+#define PL011_UARTCR_CTSEN        (1 << 15)    /* CTS hardware flow control enable */
+#define PL011_UARTCR_RTSEN        (1 << 14)    /* RTS hardware flow control enable */
+#define PL011_UARTCR_RTS          (1 << 11)    /* Request to send */
+#define PL011_UARTCR_DTR          (1 << 10)    /* Data transmit ready. */
+#define PL011_UARTCR_RXE          (1 << 9)     /* Receive enable */
+#define PL011_UARTCR_TXE          (1 << 8)     /* Transmit enable */
+#define PL011_UARTCR_LBE          (1 << 7)     /* Loopback enable */
+#define PL011_UARTCR_UARTEN       (1 << 0)     /* UART Enable */
+
+#if !defined(PL011_LINE_CONTROL)
+/* FIFO Enabled / No Parity / 8 Data bit / One Stop Bit */
+#define PL011_LINE_CONTROL  (PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8)
+#endif
+
+/* Line Control Register Bits */
+#define PL011_UARTLCR_H_SPS       (1 << 7)     /* Stick parity select */
+#define PL011_UARTLCR_H_WLEN_8    (3 << 5)
+#define PL011_UARTLCR_H_WLEN_7    (2 << 5)
+#define PL011_UARTLCR_H_WLEN_6    (1 << 5)
+#define PL011_UARTLCR_H_WLEN_5    (0 << 5)
+#define PL011_UARTLCR_H_FEN       (1 << 4)     /* FIFOs Enable */
+#define PL011_UARTLCR_H_STP2      (1 << 3)     /* Two stop bits select */
+#define PL011_UARTLCR_H_EPS       (1 << 2)     /* Even parity select */
+#define PL011_UARTLCR_H_PEN       (1 << 1)     /* Parity Enable */
+#define PL011_UARTLCR_H_BRK       (1 << 0)     /* Send break */
+
+#endif /* __PL011_H__ */
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
new file mode 100644 (file)
index 0000000..d62e67b
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TZC400_H__
+#define __TZC400_H__
+
+#include <stdint.h>
+
+#define BUILD_CONFIG_OFF       0x000
+#define ACTION_OFF             0x004
+#define GATE_KEEPER_OFF                0x008
+#define SPECULATION_CTRL_OFF   0x00c
+#define INT_STATUS             0x010
+#define INT_CLEAR              0x014
+
+#define FAIL_ADDRESS_LOW_OFF   0x020
+#define FAIL_ADDRESS_HIGH_OFF  0x024
+#define FAIL_CONTROL_OFF       0x028
+#define FAIL_ID                        0x02c
+
+#define REGION_BASE_LOW_OFF    0x100
+#define REGION_BASE_HIGH_OFF   0x104
+#define REGION_TOP_LOW_OFF     0x108
+#define REGION_TOP_HIGH_OFF    0x10c
+#define REGION_ATTRIBUTES_OFF  0x110
+#define REGION_ID_ACCESS_OFF   0x114
+#define REGION_NUM_OFF(region)  (0x20 * region)
+
+/* ID Registers */
+#define PID0_OFF               0xfe0
+#define PID1_OFF               0xfe4
+#define PID2_OFF               0xfe8
+#define PID3_OFF               0xfec
+#define PID4_OFF               0xfd0
+#define PID5_OFF               0xfd4
+#define PID6_OFF               0xfd8
+#define PID7_OFF               0xfdc
+#define CID0_OFF               0xff0
+#define CID1_OFF               0xff4
+#define CID2_OFF               0xff8
+#define CID3_OFF               0xffc
+
+#define BUILD_CONFIG_NF_SHIFT  24
+#define BUILD_CONFIG_NF_MASK   0x3
+#define BUILD_CONFIG_AW_SHIFT  8
+#define BUILD_CONFIG_AW_MASK   0x3f
+#define BUILD_CONFIG_NR_SHIFT  0
+#define BUILD_CONFIG_NR_MASK   0x1f
+
+/* Not describing the case where regions 1 to 8 overlap */
+#define ACTION_RV_SHIFT                0
+#define ACTION_RV_MASK         0x3
+#define  ACTION_RV_LOWOK       0x0
+#define  ACTION_RV_LOWERR      0x1
+#define  ACTION_RV_HIGHOK      0x2
+#define  ACTION_RV_HIGHERR     0x3
+
+/*
+ * Number of gate keepers is implementation defined. But we know the max for
+ * this device is 4. Get implementation details from BUILD_CONFIG.
+ */
+#define GATE_KEEPER_OS_SHIFT   16
+#define GATE_KEEPER_OS_MASK    0xf
+#define GATE_KEEPER_OR_SHIFT   0
+#define GATE_KEEPER_OR_MASK    0xf
+#define GATE_KEEPER_FILTER_MASK        0x1
+
+/* Speculation is enabled by default. */
+#define SPECULATION_CTRL_WRITE_DISABLE (1 << 1)
+#define SPECULATION_CTRL_READ_DISABLE  (1 << 0)
+
+/* Max number of filters allowed is 4. */
+#define INT_STATUS_OVERLAP_SHIFT       16
+#define INT_STATUS_OVERLAP_MASK                0xf
+#define INT_STATUS_OVERRUN_SHIFT       8
+#define INT_STATUS_OVERRUN_MASK                0xf
+#define INT_STATUS_STATUS_SHIFT                0
+#define INT_STATUS_STATUS_MASK         0xf
+
+#define INT_CLEAR_CLEAR_SHIFT          0
+#define INT_CLEAR_CLEAR_MASK           0xf
+
+#define FAIL_CONTROL_DIR_SHIFT         (1 << 24)
+#define  FAIL_CONTROL_DIR_READ         0x0
+#define  FAIL_CONTROL_DIR_WRITE                0x1
+#define FAIL_CONTROL_NS_SHIFT          (1 << 21)
+#define  FAIL_CONTROL_NS_SECURE                0x0
+#define  FAIL_CONTROL_NS_NONSECURE     0x1
+#define FAIL_CONTROL_PRIV_SHIFT                (1 << 20)
+#define  FAIL_CONTROL_PRIV_PRIV                0x0
+#define  FAIL_CONTROL_PRIV_UNPRIV      0x1
+
+/*
+ * FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific.
+ * Platform should provide the value on initialisation.
+ */
+#define FAIL_ID_VNET_SHIFT             24
+#define FAIL_ID_VNET_MASK              0xf
+#define FAIL_ID_ID_SHIFT               0
+
+/* Used along with 'tzc_region_attributes_t' below */
+#define REG_ATTR_SEC_SHIFT             30
+#define REG_ATTR_F_EN_SHIFT            0
+#define REG_ATTR_F_EN_MASK             0xf
+#define REG_ATTR_FILTER_BIT(x)         ((1 << x) << REG_ATTR_F_EN_SHIFT)
+#define REG_ATTR_FILTER_BIT_ALL                (REG_ATTR_F_EN_MASK << \
+                                       REG_ATTR_F_EN_SHIFT)
+
+#define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT     16
+#define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT     0
+#define REGION_ID_ACCESS_NSAID_ID_MASK         0xf
+
+
+/* Macros for setting Region ID access permissions based on NSAID */
+#define TZC_REGION_ACCESS_RD(id)                                       \
+               ((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) <<        \
+                REGION_ID_ACCESS_NSAID_RD_EN_SHIFT)
+#define TZC_REGION_ACCESS_WR(id)                                       \
+               ((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) <<        \
+                REGION_ID_ACCESS_NSAID_WR_EN_SHIFT)
+#define TZC_REGION_ACCESS_RDWR(id)                                     \
+               (TZC_REGION_ACCESS_RD(id) | TZC_REGION_ACCESS_WR(id))
+
+/* Filters are bit mapped 0 to 3. */
+#define TZC400_COMPONENT_ID    0xb105f00d
+
+/*******************************************************************************
+ * Function & variable prototypes
+ ******************************************************************************/
+
+/*
+ * What type of action is expected when an access violation occurs.
+ * The memory requested is zeroed. But we can also raise and event to
+ * let the system know it happened.
+ * We can raise an interrupt(INT) and/or cause an exception(ERR).
+ *  TZC_ACTION_NONE    - No interrupt, no Exception
+ *  TZC_ACTION_ERR     - No interrupt, raise exception -> sync external
+ *                       data abort
+ *  TZC_ACTION_INT     - Raise interrupt, no exception
+ *  TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
+ *                       external data abort
+ */
+typedef enum {
+       TZC_ACTION_NONE = 0,
+       TZC_ACTION_ERR = 1,
+       TZC_ACTION_INT = 2,
+       TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
+} tzc_action_t;
+
+/*
+ * Controls secure access to a region. If not enabled secure access is not
+ * allowed to region.
+ */
+typedef enum {
+       TZC_REGION_S_NONE = 0,
+       TZC_REGION_S_RD = 1,
+       TZC_REGION_S_WR = 2,
+       TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
+} tzc_region_attributes_t;
+
+
+void tzc_init(uint64_t base);
+void tzc_configure_region(uint32_t filters,
+                       uint8_t region,
+                       uint64_t region_base,
+                       uint64_t region_top,
+                       tzc_region_attributes_t sec_attr,
+                       uint32_t ns_device_access);
+void tzc_enable_filters(void);
+void tzc_disable_filters(void);
+void tzc_set_action(tzc_action_t action);
+
+
+#endif /* __TZC400__ */
diff --git a/include/drivers/console.h b/include/drivers/console.h
new file mode 100644 (file)
index 0000000..f144ab9
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CONSOLE_H__
+#define __CONSOLE_H__
+
+int console_init(unsigned long base_addr,
+               unsigned int uart_clk, unsigned int baud_rate);
+int console_putc(int c);
+int console_getc(void);
+
+#endif /* __CONSOLE_H__ */
+
diff --git a/include/drivers/fastboot.h b/include/drivers/fastboot.h
new file mode 100644 (file)
index 0000000..d5bf965
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, Linaro Ltd. and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FASTBOOT_H__
+#define __FASTBOOT_H__
+
+#include <sys/types.h>
+
+typedef struct sparse_header {
+       uint32_t        magic;
+       uint16_t        major_version;
+       uint16_t        minor_version;
+       uint16_t        file_hdr_sz;
+       uint16_t        chunk_hdr_sz;
+       uint32_t        blk_sz;
+       uint32_t        total_blks;
+       uint32_t        total_chunks;
+       uint32_t        image_checksum;
+} sparse_header_t;
+
+#define SPARSE_HEADER_MAGIC    0xed26ff3a
+
+#define CHUNK_TYPE_RAW         0xCAC1
+#define CHUNK_TYPE_FILL                0xCAC2
+#define CHUNK_TYPE_DONT_CARE   0xCAC3
+#define CHUNK_TYPE_CRC32       0xCAC4
+
+typedef struct chunk_header {
+       uint16_t        chunk_type;     /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
+       uint16_t        reserved1;
+       uint32_t        chunk_sz;       /* in blocks in output image */
+       uint32_t        total_sz;       /* in bytes of chunk input file including chunk header and data */
+} chunk_header_t;
+
+#endif /* __FASTBOOT_H__ */
diff --git a/include/drivers/io/io_block.h b/include/drivers/io/io_block.h
new file mode 100644 (file)
index 0000000..a0a8558
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IO_BLOCK_H__
+#define __IO_BLOCK_H__
+
+struct io_dev_connector;
+
+struct block_ops {
+       int     (*init)(void);
+       int     (*read)(unsigned long, unsigned long, size_t, uint32_t);
+       int     (*write)(unsigned long, unsigned long, size_t, uint32_t);
+};
+
+int register_io_dev_block(const struct io_dev_connector **dev_con);
+
+#endif /* __IO_BLOCK_H__ */
diff --git a/include/drivers/io/io_driver.h b/include/drivers/io/io_driver.h
new file mode 100644 (file)
index 0000000..adb38b0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IO_DRIVER_H__
+#define __IO_DRIVER_H__
+
+#include <io_storage.h>
+#include <stdint.h>
+
+
+/* Generic IO entity structure,representing an accessible IO construct on the
+ * device, such as a file */
+typedef struct io_entity {
+       struct io_dev_info *dev_handle;
+       uintptr_t info;
+} io_entity_t;
+
+
+/* Device info structure, providing device-specific functions and a means of
+ * adding driver-specific state */
+typedef struct io_dev_info {
+       const struct io_dev_funcs *funcs;
+       uintptr_t info;
+} io_dev_info_t;
+
+
+/* Structure used to create a connection to a type of device */
+typedef struct io_dev_connector {
+       /* dev_open opens a connection to a particular device driver */
+       int (*dev_open)(const uintptr_t dev_spec, io_dev_info_t **dev_info);
+} io_dev_connector_t;
+
+
+/* Structure to hold device driver function pointers */
+typedef struct io_dev_funcs {
+       io_type_t (*type)(void);
+       int (*open)(io_dev_info_t *dev_info, const uintptr_t spec,
+                       io_entity_t *entity);
+       int (*seek)(io_entity_t *entity, int mode, ssize_t offset);
+       int (*size)(io_entity_t *entity, size_t *length);
+       int (*read)(io_entity_t *entity, uintptr_t buffer, size_t length,
+                       size_t *length_read);
+       int (*write)(io_entity_t *entity, const uintptr_t buffer,
+                       size_t length, size_t *length_written);
+       int (*close)(io_entity_t *entity);
+       int (*dev_init)(io_dev_info_t *dev_info, const uintptr_t init_params);
+       int (*dev_close)(io_dev_info_t *dev_info);
+} io_dev_funcs_t;
+
+
+/* Operations intended to be performed during platform initialisation */
+
+/* Register an IO device */
+int io_register_device(const io_dev_info_t *dev_info);
+
+#endif  /* __IO_DRIVER_H__ */
diff --git a/include/drivers/io/io_fip.h b/include/drivers/io/io_fip.h
new file mode 100644 (file)
index 0000000..90b2fd0
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IO_FIP_H__
+#define __IO_FIP_H__
+
+struct io_dev_connector;
+
+int register_io_dev_fip(const struct io_dev_connector **dev_con);
+
+#endif /* __IO_FIP_H__ */
diff --git a/include/drivers/io/io_memmap.h b/include/drivers/io/io_memmap.h
new file mode 100644 (file)
index 0000000..7ee60fe
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IO_MEMMAP_H__
+#define __IO_MEMMAP_H__
+
+struct io_dev_connector;
+
+int register_io_dev_memmap(const struct io_dev_connector **dev_con);
+
+#endif /* __IO_MEMMAP_H__ */
diff --git a/include/drivers/io/io_semihosting.h b/include/drivers/io/io_semihosting.h
new file mode 100644 (file)
index 0000000..8902a6f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IO_SH_H__
+#define __IO_SH_H__
+
+struct io_dev_connector;
+
+int register_io_dev_sh(const struct io_dev_connector **dev_con);
+
+#endif /* __IO_SH_H__ */
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
new file mode 100644 (file)
index 0000000..1c2d26d
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IO_H__
+#define __IO_H__
+
+#include <stdint.h>
+#include <stdio.h> /* For ssize_t */
+
+
+/* Device type which can be used to enable policy decisions about which device
+ * to access */
+typedef enum {
+       IO_TYPE_INVALID,
+       IO_TYPE_SEMIHOSTING,
+       IO_TYPE_MEMMAP,
+       IO_TYPE_FIRMWARE_IMAGE_PACKAGE,
+       IO_TYPE_BLOCK,
+       IO_TYPE_MAX
+} io_type_t;
+
+
+/* Modes used when seeking data on a supported device */
+typedef enum {
+       IO_SEEK_INVALID,
+       IO_SEEK_SET,
+       IO_SEEK_END,
+       IO_SEEK_CUR,
+       IO_SEEK_MAX
+} io_seek_mode_t;
+
+
+/* Connector type, providing a means of identifying a device to open */
+struct io_dev_connector;
+
+
+/* File specification - used to refer to data on a device supporting file-like
+ * entities */
+typedef struct io_file_spec {
+       const char *path;
+       unsigned int mode;
+} io_file_spec_t;
+
+
+/* Block specification - used to refer to data on a device supporting
+ * block-like entities */
+typedef struct io_block_spec {
+       size_t offset;
+       size_t length;
+} io_block_spec_t;
+
+
+/* Access modes used when accessing data on a device */
+#define IO_MODE_INVALID (0)
+#define IO_MODE_RO     (1 << 0)
+#define IO_MODE_RW     (1 << 1)
+
+
+/* Return codes reported by 'io_*' APIs */
+#define IO_SUCCESS             (0)
+#define IO_FAIL                        (-1)
+#define IO_NOT_SUPPORTED       (-2)
+#define IO_RESOURCES_EXHAUSTED (-3)
+
+
+/* Open a connection to a device */
+int io_dev_open(const struct io_dev_connector *dev_con,
+               const uintptr_t dev_spec,
+               uintptr_t *dev_handle);
+
+
+/* Initialise a device explicitly - to permit lazy initialisation or
+ * re-initialisation */
+int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params);
+
+/* TODO: Consider whether an explicit "shutdown" API should be included */
+
+/* Close a connection to a device */
+int io_dev_close(uintptr_t dev_handle);
+
+
+/* Synchronous operations */
+int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle);
+
+int io_seek(uintptr_t handle, io_seek_mode_t mode, ssize_t offset);
+
+int io_size(uintptr_t handle, size_t *length);
+
+int io_read(uintptr_t handle, uintptr_t buffer, size_t length,
+               size_t *length_read);
+
+int io_write(uintptr_t handle, const uintptr_t buffer, size_t length,
+               size_t *length_written);
+
+int io_close(uintptr_t handle);
+
+
+#endif /* __IO_H__ */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
new file mode 100644 (file)
index 0000000..5291684
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_H__
+#define __ARCH_H__
+
+
+/*******************************************************************************
+ * MIDR bit definitions
+ ******************************************************************************/
+#define MIDR_IMPL_MASK         0xff
+#define MIDR_IMPL_SHIFT                0x18
+#define MIDR_VAR_SHIFT         20
+#define MIDR_VAR_BITS          4
+#define MIDR_REV_SHIFT         0
+#define MIDR_REV_BITS          4
+#define MIDR_PN_MASK           0xfff
+#define MIDR_PN_SHIFT          0x4
+
+/*******************************************************************************
+ * MPIDR macros
+ ******************************************************************************/
+#define MPIDR_CPU_MASK         MPIDR_AFFLVL_MASK
+#define MPIDR_CLUSTER_MASK     MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS
+#define MPIDR_AFFINITY_BITS    8
+#define MPIDR_AFFLVL_MASK      0xff
+#define MPIDR_AFF0_SHIFT       0
+#define MPIDR_AFF1_SHIFT       8
+#define MPIDR_AFF2_SHIFT       16
+#define MPIDR_AFF3_SHIFT       32
+#define MPIDR_AFFINITY_MASK    0xff00ffffff
+#define MPIDR_AFFLVL_SHIFT     3
+#define MPIDR_AFFLVL0          0
+#define MPIDR_AFFLVL1          1
+#define MPIDR_AFFLVL2          2
+#define MPIDR_AFFLVL3          3
+/*
+ * The MPIDR_MAX_AFFLVL count starts from 0. Take care to
+ * add one while using this macro to define array sizes.
+ * TODO: Support only the first 3 affinity levels for now.
+ */
+#define MPIDR_MAX_AFFLVL       2
+
+/* Constant to highlight the assumption that MPIDR allocation starts from 0 */
+#define FIRST_MPIDR            0
+
+/*******************************************************************************
+ * Definitions for CPU system register interface to GICv3
+ ******************************************************************************/
+#define ICC_SRE_EL1     S3_0_C12_C12_5
+#define ICC_SRE_EL2     S3_4_C12_C9_5
+#define ICC_SRE_EL3     S3_6_C12_C12_5
+#define ICC_CTLR_EL1    S3_0_C12_C12_4
+#define ICC_CTLR_EL3    S3_6_C12_C12_4
+#define ICC_PMR_EL1     S3_0_C4_C6_0
+
+/*******************************************************************************
+ * Generic timer memory mapped registers & offsets
+ ******************************************************************************/
+#define CNTCR_OFF                      0x000
+#define CNTFID_OFF                     0x020
+
+#define CNTCR_EN                       (1 << 0)
+#define CNTCR_HDBG                     (1 << 1)
+#define CNTCR_FCREQ(x)                 ((x) << 8)
+
+/*******************************************************************************
+ * System register bit definitions
+ ******************************************************************************/
+/* CLIDR definitions */
+#define LOUIS_SHIFT            21
+#define LOC_SHIFT              24
+#define CLIDR_FIELD_WIDTH      3
+
+/* CSSELR definitions */
+#define LEVEL_SHIFT            1
+
+/* D$ set/way op type defines */
+#define DCISW                  0x0
+#define DCCISW                 0x1
+#define DCCSW                  0x2
+
+/* ID_AA64PFR0_EL1 definitions */
+#define ID_AA64PFR0_EL0_SHIFT  0
+#define ID_AA64PFR0_EL1_SHIFT  4
+#define ID_AA64PFR0_EL2_SHIFT  8
+#define ID_AA64PFR0_EL3_SHIFT  12
+#define ID_AA64PFR0_ELX_MASK   0xf
+
+/* ID_PFR1_EL1 definitions */
+#define ID_PFR1_VIRTEXT_SHIFT  12
+#define ID_PFR1_VIRTEXT_MASK   0xf
+#define GET_VIRT_EXT(id)       ((id >> ID_PFR1_VIRTEXT_SHIFT) \
+                                & ID_PFR1_VIRTEXT_MASK)
+
+/* SCTLR definitions */
+#define SCTLR_EL2_RES1  ((1 << 29) | (1 << 28) | (1 << 23) | (1 << 22) | \
+                       (1 << 18) | (1 << 16) | (1 << 11) | (1 << 5) |  \
+                       (1 << 4))
+
+#define SCTLR_EL1_RES1  ((1 << 29) | (1 << 28) | (1 << 23) | (1 << 22) | \
+                       (1 << 11))
+#define SCTLR_AARCH32_EL1_RES1 \
+                       ((1 << 23) | (1 << 22) | (1 << 11) | (1 << 4) | \
+                       (1 << 3))
+
+#define SCTLR_M_BIT            (1 << 0)
+#define SCTLR_A_BIT            (1 << 1)
+#define SCTLR_C_BIT            (1 << 2)
+#define SCTLR_SA_BIT           (1 << 3)
+#define SCTLR_I_BIT            (1 << 12)
+#define SCTLR_WXN_BIT          (1 << 19)
+#define SCTLR_EE_BIT           (1 << 25)
+
+/* CPACR_El1 definitions */
+#define CPACR_EL1_FPEN(x)      (x << 20)
+#define CPACR_EL1_FP_TRAP_EL0  0x1
+#define CPACR_EL1_FP_TRAP_ALL  0x2
+#define CPACR_EL1_FP_TRAP_NONE 0x3
+
+/* SCR definitions */
+#define SCR_RES1_BITS          ((1 << 4) | (1 << 5))
+#define SCR_TWE_BIT            (1 << 13)
+#define SCR_TWI_BIT            (1 << 12)
+#define SCR_ST_BIT             (1 << 11)
+#define SCR_RW_BIT             (1 << 10)
+#define SCR_SIF_BIT            (1 << 9)
+#define SCR_HCE_BIT            (1 << 8)
+#define SCR_SMD_BIT            (1 << 7)
+#define SCR_EA_BIT             (1 << 3)
+#define SCR_FIQ_BIT            (1 << 2)
+#define SCR_IRQ_BIT            (1 << 1)
+#define SCR_NS_BIT             (1 << 0)
+#define SCR_VALID_BIT_MASK     0x2f8f
+
+/* HCR definitions */
+#define HCR_RW_BIT             (1ull << 31)
+#define HCR_AMO_BIT            (1 << 5)
+#define HCR_IMO_BIT            (1 << 4)
+#define HCR_FMO_BIT            (1 << 3)
+
+/* CNTHCTL_EL2 definitions */
+#define EVNTEN_BIT             (1 << 2)
+#define EL1PCEN_BIT            (1 << 1)
+#define EL1PCTEN_BIT           (1 << 0)
+
+/* CNTKCTL_EL1 definitions */
+#define EL0PTEN_BIT            (1 << 9)
+#define EL0VTEN_BIT            (1 << 8)
+#define EL0PCTEN_BIT           (1 << 0)
+#define EL0VCTEN_BIT           (1 << 1)
+#define EVNTEN_BIT             (1 << 2)
+#define EVNTDIR_BIT            (1 << 3)
+#define EVNTI_SHIFT            4
+#define EVNTI_MASK             0xf
+
+/* CPTR_EL3 definitions */
+#define TCPAC_BIT              (1 << 31)
+#define TTA_BIT                        (1 << 20)
+#define TFP_BIT                        (1 << 10)
+
+/* CPSR/SPSR definitions */
+#define DAIF_FIQ_BIT           (1 << 0)
+#define DAIF_IRQ_BIT           (1 << 1)
+#define DAIF_ABT_BIT           (1 << 2)
+#define DAIF_DBG_BIT           (1 << 3)
+#define SPSR_DAIF_SHIFT                6
+#define SPSR_DAIF_MASK         0xf
+
+#define SPSR_AIF_SHIFT         6
+#define SPSR_AIF_MASK          0x7
+
+#define SPSR_E_SHIFT           9
+#define SPSR_E_MASK                    0x1
+#define SPSR_E_LITTLE          0x0
+#define SPSR_E_BIG                     0x1
+
+#define SPSR_T_SHIFT           5
+#define SPSR_T_MASK                    0x1
+#define SPSR_T_ARM                     0x0
+#define SPSR_T_THUMB           0x1
+
+#define DISABLE_ALL_EXCEPTIONS \
+               (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT)
+
+
+/*
+ * TCR defintions
+ */
+#define TCR_EL3_RES1           ((1UL << 31) | (1UL << 23))
+#define TCR_EL1_IPS_SHIFT      32
+#define TCR_EL3_PS_SHIFT       16
+
+/* (internal) physical address size bits in EL3/EL1 */
+#define TCR_PS_BITS_4GB                (0x0)
+#define TCR_PS_BITS_64GB       (0x1)
+#define TCR_PS_BITS_1TB                (0x2)
+#define TCR_PS_BITS_4TB                (0x3)
+#define TCR_PS_BITS_16TB       (0x4)
+#define TCR_PS_BITS_256TB      (0x5)
+
+#define ADDR_MASK_48_TO_63     0xFFFF000000000000UL
+#define ADDR_MASK_44_TO_47     0x0000F00000000000UL
+#define ADDR_MASK_42_TO_43     0x00000C0000000000UL
+#define ADDR_MASK_40_TO_41     0x0000030000000000UL
+#define ADDR_MASK_36_TO_39     0x000000F000000000UL
+#define ADDR_MASK_32_TO_35     0x0000000F00000000UL
+
+#define TCR_RGN_INNER_NC       (0x0 << 8)
+#define TCR_RGN_INNER_WBA      (0x1 << 8)
+#define TCR_RGN_INNER_WT       (0x2 << 8)
+#define TCR_RGN_INNER_WBNA     (0x3 << 8)
+
+#define TCR_RGN_OUTER_NC       (0x0 << 10)
+#define TCR_RGN_OUTER_WBA      (0x1 << 10)
+#define TCR_RGN_OUTER_WT       (0x2 << 10)
+#define TCR_RGN_OUTER_WBNA     (0x3 << 10)
+
+#define TCR_SH_NON_SHAREABLE   (0x0 << 12)
+#define TCR_SH_OUTER_SHAREABLE (0x2 << 12)
+#define TCR_SH_INNER_SHAREABLE (0x3 << 12)
+
+#define MODE_SP_SHIFT          0x0
+#define MODE_SP_MASK           0x1
+#define MODE_SP_EL0            0x0
+#define MODE_SP_ELX            0x1
+
+#define MODE_RW_SHIFT          0x4
+#define MODE_RW_MASK           0x1
+#define MODE_RW_64                     0x0
+#define MODE_RW_32                     0x1
+
+#define MODE_EL_SHIFT          0x2
+#define MODE_EL_MASK           0x3
+#define MODE_EL3               0x3
+#define MODE_EL2               0x2
+#define MODE_EL1               0x1
+#define MODE_EL0               0x0
+
+#define MODE32_SHIFT           0
+#define MODE32_MASK            0xf
+#define MODE32_usr             0x0
+#define MODE32_fiq             0x1
+#define MODE32_irq             0x2
+#define MODE32_svc             0x3
+#define MODE32_mon             0x6
+#define MODE32_abt             0x7
+#define MODE32_hyp             0xa
+#define MODE32_und             0xb
+#define MODE32_sys             0xf
+
+#define GET_RW(mode)           (((mode) >> MODE_RW_SHIFT) & MODE_RW_MASK)
+#define GET_EL(mode)           (((mode) >> MODE_EL_SHIFT) & MODE_EL_MASK)
+#define GET_SP(mode)           (((mode) >> MODE_SP_SHIFT) & MODE_SP_MASK)
+#define GET_M32(mode)          (((mode) >> MODE32_SHIFT) & MODE32_MASK)
+
+#define SPSR_64(el, sp, daif)                          \
+       (MODE_RW_64 << MODE_RW_SHIFT |                  \
+       ((el) & MODE_EL_MASK) << MODE_EL_SHIFT |        \
+       ((sp) & MODE_SP_MASK) << MODE_SP_SHIFT |        \
+       ((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT)
+
+#define SPSR_MODE32(mode, isa, endian, aif)            \
+       (MODE_RW_32 << MODE_RW_SHIFT |                  \
+       ((mode) & MODE32_MASK) << MODE32_SHIFT |        \
+       ((isa) & SPSR_T_MASK) << SPSR_T_SHIFT |         \
+       ((endian) & SPSR_E_MASK) << SPSR_E_SHIFT |      \
+       ((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT)
+
+
+/* Physical timer control register bit fields shifts and masks */
+#define CNTP_CTL_ENABLE_SHIFT   0
+#define CNTP_CTL_IMASK_SHIFT    1
+#define CNTP_CTL_ISTATUS_SHIFT  2
+
+#define CNTP_CTL_ENABLE_MASK    1
+#define CNTP_CTL_IMASK_MASK     1
+#define CNTP_CTL_ISTATUS_MASK   1
+
+#define get_cntp_ctl_enable(x)  ((x >> CNTP_CTL_ENABLE_SHIFT) & \
+                                       CNTP_CTL_ENABLE_MASK)
+#define get_cntp_ctl_imask(x)   ((x >> CNTP_CTL_IMASK_SHIFT) & \
+                                       CNTP_CTL_IMASK_MASK)
+#define get_cntp_ctl_istatus(x) ((x >> CNTP_CTL_ISTATUS_SHIFT) & \
+                                       CNTP_CTL_ISTATUS_MASK)
+
+#define set_cntp_ctl_enable(x)  (x |= 1 << CNTP_CTL_ENABLE_SHIFT)
+#define set_cntp_ctl_imask(x)   (x |= 1 << CNTP_CTL_IMASK_SHIFT)
+
+#define clr_cntp_ctl_enable(x)  (x &= ~(1 << CNTP_CTL_ENABLE_SHIFT))
+#define clr_cntp_ctl_imask(x)   (x &= ~(1 << CNTP_CTL_IMASK_SHIFT))
+
+/* Miscellaneous MMU related constants */
+#define NUM_2MB_IN_GB          (1 << 9)
+#define NUM_4K_IN_2MB          (1 << 9)
+#define NUM_GB_IN_4GB          (1 << 2)
+
+#define TWO_MB_SHIFT           21
+#define ONE_GB_SHIFT           30
+#define FOUR_KB_SHIFT          12
+
+#define ONE_GB_INDEX(x)                ((x) >> ONE_GB_SHIFT)
+#define TWO_MB_INDEX(x)                ((x) >> TWO_MB_SHIFT)
+#define FOUR_KB_INDEX(x)       ((x) >> FOUR_KB_SHIFT)
+
+#define INVALID_DESC           0x0
+#define BLOCK_DESC             0x1
+#define TABLE_DESC             0x3
+
+#define FIRST_LEVEL_DESC_N     ONE_GB_SHIFT
+#define SECOND_LEVEL_DESC_N    TWO_MB_SHIFT
+#define THIRD_LEVEL_DESC_N     FOUR_KB_SHIFT
+
+#define LEVEL1                 1
+#define LEVEL2                 2
+#define LEVEL3                 3
+
+#define XN                     (1ull << 2)
+#define PXN                    (1ull << 1)
+#define CONT_HINT              (1ull << 0)
+
+#define UPPER_ATTRS(x)         (x & 0x7) << 52
+#define NON_GLOBAL             (1 << 9)
+#define ACCESS_FLAG            (1 << 8)
+#define NSH                    (0x0 << 6)
+#define OSH                    (0x2 << 6)
+#define ISH                    (0x3 << 6)
+
+#define PAGE_SIZE_SHIFT                FOUR_KB_SHIFT
+#define PAGE_SIZE              (1 << PAGE_SIZE_SHIFT)
+#define PAGE_SIZE_MASK         (PAGE_SIZE - 1)
+#define IS_PAGE_ALIGNED(addr)  (((addr) & PAGE_SIZE_MASK) == 0)
+
+#define XLAT_ENTRY_SIZE_SHIFT  3 /* Each MMU table entry is 8 bytes (1 << 3) */
+#define XLAT_ENTRY_SIZE                (1 << XLAT_ENTRY_SIZE_SHIFT)
+
+#define XLAT_TABLE_SIZE_SHIFT  PAGE_SIZE_SHIFT
+#define XLAT_TABLE_SIZE                (1 << XLAT_TABLE_SIZE_SHIFT)
+
+/* Values for number of entries in each MMU translation table */
+#define XLAT_TABLE_ENTRIES_SHIFT (XLAT_TABLE_SIZE_SHIFT - XLAT_ENTRY_SIZE_SHIFT)
+#define XLAT_TABLE_ENTRIES     (1 << XLAT_TABLE_ENTRIES_SHIFT)
+#define XLAT_TABLE_ENTRIES_MASK        (XLAT_TABLE_ENTRIES - 1)
+
+/* Values to convert a memory address to an index into a translation table */
+#define L3_XLAT_ADDRESS_SHIFT  PAGE_SIZE_SHIFT
+#define L2_XLAT_ADDRESS_SHIFT  (L3_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT)
+#define L1_XLAT_ADDRESS_SHIFT  (L2_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT)
+
+/*
+ * AP[1] bit is ignored by hardware and is
+ * treated as if it is One in EL2/EL3
+ */
+#define AP_RO                  (0x1 << 5)
+#define AP_RW                  (0x0 << 5)
+
+#define NS                             (0x1 << 3)
+#define ATTR_SO_INDEX                  0x2
+#define ATTR_DEVICE_INDEX              0x1
+#define ATTR_IWBWA_OWBWA_NTR_INDEX     0x0
+#define LOWER_ATTRS(x)                 (((x) & 0xfff) << 2)
+#define ATTR_SO                                (0x0)
+#define ATTR_DEVICE                    (0x4)
+#define ATTR_IWBWA_OWBWA_NTR           (0xff)
+#define MAIR_ATTR_SET(attr, index)     (attr << (index << 3))
+
+/* Exception Syndrome register bits and bobs */
+#define ESR_EC_SHIFT                   26
+#define ESR_EC_MASK                    0x3f
+#define ESR_EC_LENGTH                  6
+#define EC_UNKNOWN                     0x0
+#define EC_WFE_WFI                     0x1
+#define EC_AARCH32_CP15_MRC_MCR                0x3
+#define EC_AARCH32_CP15_MRRC_MCRR      0x4
+#define EC_AARCH32_CP14_MRC_MCR                0x5
+#define EC_AARCH32_CP14_LDC_STC                0x6
+#define EC_FP_SIMD                     0x7
+#define EC_AARCH32_CP10_MRC            0x8
+#define EC_AARCH32_CP14_MRRC_MCRR      0xc
+#define EC_ILLEGAL                     0xe
+#define EC_AARCH32_SVC                 0x11
+#define EC_AARCH32_HVC                 0x12
+#define EC_AARCH32_SMC                 0x13
+#define EC_AARCH64_SVC                 0x15
+#define EC_AARCH64_HVC                 0x16
+#define EC_AARCH64_SMC                 0x17
+#define EC_AARCH64_SYS                 0x18
+#define EC_IABORT_LOWER_EL             0x20
+#define EC_IABORT_CUR_EL               0x21
+#define EC_PC_ALIGN                    0x22
+#define EC_DABORT_LOWER_EL             0x24
+#define EC_DABORT_CUR_EL               0x25
+#define EC_SP_ALIGN                    0x26
+#define EC_AARCH32_FP                  0x28
+#define EC_AARCH64_FP                  0x2c
+#define EC_SERROR                      0x2f
+
+#define EC_BITS(x)                     (x >> ESR_EC_SHIFT) & ESR_EC_MASK
+
+/*******************************************************************************
+ * Definitions of register offsets and fields in the CNTCTLBase Frame of the
+ * system level implementation of the Generic Timer.
+ ******************************************************************************/
+#define CNTNSAR                        0x4
+#define CNTNSAR_NS_SHIFT(x)    x
+
+#define CNTACR_BASE(x)         (0x40 + (x << 2))
+#define CNTACR_RPCT_SHIFT      0x0
+#define CNTACR_RVCT_SHIFT      0x1
+#define CNTACR_RFRQ_SHIFT      0x2
+#define CNTACR_RVOFF_SHIFT     0x3
+#define CNTACR_RWVT_SHIFT      0x4
+#define CNTACR_RWPT_SHIFT      0x5
+
+#endif /* __ARCH_H__ */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
new file mode 100644 (file)
index 0000000..65941e6
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_HELPERS_H__
+#define __ARCH_HELPERS_H__
+
+#include <arch.h>      /* for additional register definitions */
+#include <cdefs.h>     /* For __dead2 */
+#include <stdint.h>
+
+/**********************************************************************
+ * Macros which create inline functions to read or write CPU system
+ * registers
+ *********************************************************************/
+
+#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name)             \
+static inline uint64_t read_ ## _name(void)                    \
+{                                                              \
+       uint64_t v;                                             \
+       __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v));    \
+       return v;                                               \
+}
+
+#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)                    \
+static inline void write_ ## _name(uint64_t v)                         \
+{                                                                      \
+       __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v));        \
+}
+
+#define _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name)              \
+static inline void write_ ## _name(const uint64_t v)                   \
+{                                                                      \
+       __asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v));        \
+}
+
+/* Define read function for system register */
+#define DEFINE_SYSREG_READ_FUNC(_name)                         \
+       _DEFINE_SYSREG_READ_FUNC(_name, _name)
+
+/* Define read & write function for system register */
+#define DEFINE_SYSREG_RW_FUNCS(_name)                  \
+       _DEFINE_SYSREG_READ_FUNC(_name, _name)          \
+       _DEFINE_SYSREG_WRITE_FUNC(_name, _name)
+
+/* Define read & write function for renamed system register */
+#define DEFINE_RENAME_SYSREG_RW_FUNCS(_name, _reg_name)        \
+       _DEFINE_SYSREG_READ_FUNC(_name, _reg_name)      \
+       _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)
+
+/* Define write function for special system registers */
+#define DEFINE_SYSREG_WRITE_CONST_FUNC(_name)          \
+       _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _name)
+
+
+/**********************************************************************
+ * Macros to create inline functions for system instructions
+ *********************************************************************/
+
+/* Define function for simple system instruction */
+#define DEFINE_SYSOP_FUNC(_op)                         \
+static inline void _op(void)                           \
+{                                                      \
+       __asm__ (#_op);                                 \
+}
+
+/* Define function for system instruction with type specifier */
+#define DEFINE_SYSOP_TYPE_FUNC(_op, _type)             \
+static inline void _op ## _type(void)                  \
+{                                                      \
+       __asm__ (#_op " " #_type);                      \
+}
+
+/* Define function for system instruction with register parameter */
+#define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type)       \
+static inline void _op ## _type(uint64_t v)            \
+{                                                      \
+        __asm__ (#_op " " #_type ", %0" : : "r" (v));  \
+}
+
+/*******************************************************************************
+ * Aarch64 translation tables manipulation helper prototypes
+******************************************************************************/
+uint64_t create_table_desc(uint64_t *next_table_ptr);
+uint64_t create_block_desc(uint64_t desc, uint64_t addr, uint32_t level);
+uint64_t create_device_block(uint64_t output_addr, uint32_t level, uint32_t ns);
+uint64_t create_romem_block(uint64_t output_addr, uint32_t level, uint32_t ns);
+uint64_t create_rwmem_block(uint64_t output_addr, uint32_t level, uint32_t ns);
+
+/*******************************************************************************
+ * TLB maintenance accessor prototypes
+ ******************************************************************************/
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1)
+
+/*******************************************************************************
+ * Cache maintenance accessor prototypes
+ ******************************************************************************/
+DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, isw)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cisw)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, csw)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvac)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, ivac)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, civac)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvau)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, zva)
+
+void flush_dcache_range(uint64_t, uint64_t);
+void inv_dcache_range(uint64_t, uint64_t);
+void dcsw_op_louis(uint32_t);
+void dcsw_op_all(uint32_t);
+
+void disable_mmu_el3(void);
+void disable_mmu_icache_el3(void);
+
+/*******************************************************************************
+ * Misc. accessor prototypes
+ ******************************************************************************/
+
+DEFINE_SYSREG_WRITE_CONST_FUNC(daifset)
+DEFINE_SYSREG_WRITE_CONST_FUNC(daifclr)
+
+#define enable_irq()                   write_daifclr(DAIF_IRQ_BIT)
+#define enable_fiq()                   write_daifclr(DAIF_FIQ_BIT)
+#define enable_serror()                        write_daifclr(DAIF_ABT_BIT)
+#define enable_debug_exceptions()      write_daifclr(DAIF_DBG_BIT)
+#define disable_irq()                  write_daifset(DAIF_IRQ_BIT)
+#define disable_fiq()                  write_daifset(DAIF_FIQ_BIT)
+#define disable_serror()               write_daifset(DAIF_ABT_BIT)
+#define disable_debug_exceptions()     write_daifset(DAIF_DBG_BIT)
+
+DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
+DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
+DEFINE_SYSREG_READ_FUNC(CurrentEl)
+DEFINE_SYSREG_RW_FUNCS(daif)
+DEFINE_SYSREG_RW_FUNCS(spsr_el1)
+DEFINE_SYSREG_RW_FUNCS(spsr_el2)
+DEFINE_SYSREG_RW_FUNCS(spsr_el3)
+DEFINE_SYSREG_RW_FUNCS(elr_el1)
+DEFINE_SYSREG_RW_FUNCS(elr_el2)
+DEFINE_SYSREG_RW_FUNCS(elr_el3)
+
+DEFINE_SYSOP_FUNC(wfi)
+DEFINE_SYSOP_FUNC(wfe)
+DEFINE_SYSOP_FUNC(sev)
+DEFINE_SYSOP_TYPE_FUNC(dsb, sy)
+DEFINE_SYSOP_TYPE_FUNC(dmb, sy)
+DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
+DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
+DEFINE_SYSOP_FUNC(isb)
+
+uint32_t get_afflvl_shift(uint32_t);
+uint32_t mpidr_mask_lower_afflvls(uint64_t, uint32_t);
+
+
+void __dead2 eret(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3,
+                 uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7);
+void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3,
+                uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7);
+
+/*******************************************************************************
+ * System register accessor prototypes
+ ******************************************************************************/
+DEFINE_SYSREG_READ_FUNC(midr_el1)
+DEFINE_SYSREG_READ_FUNC(mpidr_el1)
+
+DEFINE_SYSREG_RW_FUNCS(scr_el3)
+DEFINE_SYSREG_RW_FUNCS(hcr_el2)
+
+DEFINE_SYSREG_RW_FUNCS(vbar_el1)
+DEFINE_SYSREG_RW_FUNCS(vbar_el2)
+DEFINE_SYSREG_RW_FUNCS(vbar_el3)
+
+DEFINE_SYSREG_RW_FUNCS(sctlr_el1)
+DEFINE_SYSREG_RW_FUNCS(sctlr_el2)
+DEFINE_SYSREG_RW_FUNCS(sctlr_el3)
+
+DEFINE_SYSREG_RW_FUNCS(actlr_el1)
+DEFINE_SYSREG_RW_FUNCS(actlr_el2)
+DEFINE_SYSREG_RW_FUNCS(actlr_el3)
+
+DEFINE_SYSREG_RW_FUNCS(esr_el1)
+DEFINE_SYSREG_RW_FUNCS(esr_el2)
+DEFINE_SYSREG_RW_FUNCS(esr_el3)
+
+DEFINE_SYSREG_RW_FUNCS(afsr0_el1)
+DEFINE_SYSREG_RW_FUNCS(afsr0_el2)
+DEFINE_SYSREG_RW_FUNCS(afsr0_el3)
+
+DEFINE_SYSREG_RW_FUNCS(afsr1_el1)
+DEFINE_SYSREG_RW_FUNCS(afsr1_el2)
+DEFINE_SYSREG_RW_FUNCS(afsr1_el3)
+
+DEFINE_SYSREG_RW_FUNCS(far_el1)
+DEFINE_SYSREG_RW_FUNCS(far_el2)
+DEFINE_SYSREG_RW_FUNCS(far_el3)
+
+DEFINE_SYSREG_RW_FUNCS(mair_el1)
+DEFINE_SYSREG_RW_FUNCS(mair_el2)
+DEFINE_SYSREG_RW_FUNCS(mair_el3)
+
+DEFINE_SYSREG_RW_FUNCS(amair_el1)
+DEFINE_SYSREG_RW_FUNCS(amair_el2)
+DEFINE_SYSREG_RW_FUNCS(amair_el3)
+
+DEFINE_SYSREG_READ_FUNC(rvbar_el1)
+DEFINE_SYSREG_READ_FUNC(rvbar_el2)
+DEFINE_SYSREG_READ_FUNC(rvbar_el3)
+
+DEFINE_SYSREG_RW_FUNCS(rmr_el1)
+DEFINE_SYSREG_RW_FUNCS(rmr_el2)
+DEFINE_SYSREG_RW_FUNCS(rmr_el3)
+
+DEFINE_SYSREG_RW_FUNCS(tcr_el1)
+DEFINE_SYSREG_RW_FUNCS(tcr_el2)
+DEFINE_SYSREG_RW_FUNCS(tcr_el3)
+
+DEFINE_SYSREG_RW_FUNCS(ttbr0_el1)
+DEFINE_SYSREG_RW_FUNCS(ttbr0_el2)
+DEFINE_SYSREG_RW_FUNCS(ttbr0_el3)
+
+DEFINE_SYSREG_RW_FUNCS(ttbr1_el1)
+
+DEFINE_SYSREG_RW_FUNCS(cptr_el2)
+DEFINE_SYSREG_RW_FUNCS(cptr_el3)
+
+DEFINE_SYSREG_RW_FUNCS(cpacr_el1)
+DEFINE_SYSREG_RW_FUNCS(cntfrq_el0)
+DEFINE_SYSREG_RW_FUNCS(cntps_ctl_el1)
+DEFINE_SYSREG_RW_FUNCS(cntps_tval_el1)
+DEFINE_SYSREG_RW_FUNCS(cntps_cval_el1)
+DEFINE_SYSREG_READ_FUNC(cntpct_el0)
+DEFINE_SYSREG_RW_FUNCS(cnthctl_el2)
+
+DEFINE_SYSREG_RW_FUNCS(tpidr_el3)
+
+DEFINE_SYSREG_RW_FUNCS(cntvoff_el2)
+
+DEFINE_SYSREG_RW_FUNCS(vpidr_el2)
+DEFINE_SYSREG_RW_FUNCS(vmpidr_el2)
+
+DEFINE_SYSREG_READ_FUNC(isr_el1)
+
+/* GICv3 System Registers */
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1)
+
+
+#define IS_IN_EL(x) \
+       (GET_EL(read_CurrentEl()) == MODE_EL##x)
+
+#define IS_IN_EL1() IS_IN_EL(1)
+#define IS_IN_EL3() IS_IN_EL(3)
+
+/* Previously defined accesor functions with incomplete register names  */
+
+#define read_current_el()      read_CurrentEl()
+
+#define dsb()                  dsbsy()
+
+#define read_midr()            read_midr_el1()
+
+#define read_mpidr()           read_mpidr_el1()
+
+#define read_scr()             read_scr_el3()
+#define write_scr(_v)          write_scr_el3(_v)
+
+#define read_hcr()             read_hcr_el2()
+#define write_hcr(_v)          write_hcr_el2(_v)
+
+#define read_cpacr()           read_cpacr_el1()
+#define write_cpacr(_v)                write_cpacr_el1(_v)
+
+#endif /* __ARCH_HELPERS_H__ */
diff --git a/include/lib/aarch64/xlat_tables.h b/include/lib/aarch64/xlat_tables.h
new file mode 100644 (file)
index 0000000..0b5dbdf
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __XLAT_TABLES_H__
+#define __XLAT_TABLES_H__
+
+
+/*
+ * Flags to override default values used to program system registers while
+ * enabling the MMU.
+ */
+#define DISABLE_DCACHE         (1 << 0)
+
+#ifndef __ASSEMBLY__
+#include <stdint.h>
+
+/* Helper macro to define entries for mmap_region_t. It creates
+ * identity mappings for each region.
+ */
+#define MAP_REGION_FLAT(adr, sz, attr) MAP_REGION(adr, adr, sz, attr)
+
+/* Helper macro to define entries for mmap_region_t. It allows to
+ * re-map address mappings from 'pa' to 'va' for each region.
+ */
+#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)}
+
+/*
+ * Flags for building up memory mapping attributes.
+ * These are organised so that a clear bit gives a more restrictive  mapping
+ * that a set bit, that way a bitwise-and two sets of attributes will never give
+ * an attribute which has greater access rights that any of the original
+ * attributes.
+ */
+typedef enum  {
+       MT_DEVICE       = 0 << 0,
+       MT_MEMORY       = 1 << 0,
+
+       MT_RO           = 0 << 1,
+       MT_RW           = 1 << 1,
+
+       MT_SECURE       = 0 << 2,
+       MT_NS           = 1 << 2
+} mmap_attr_t;
+
+/*
+ * Structure for specifying a single region of memory.
+ */
+typedef struct mmap_region {
+       unsigned long   base_pa;
+       unsigned long   base_va;
+       unsigned long   size;
+       mmap_attr_t     attr;
+} mmap_region_t;
+
+void mmap_add_region(unsigned long base_pa, unsigned long base_va,
+                               unsigned long size, unsigned attr);
+void mmap_add(const mmap_region_t *mm);
+
+void init_xlat_tables(void);
+
+void enable_mmu_el1(uint32_t flags);
+void enable_mmu_el3(uint32_t flags);
+
+#endif /*__ASSEMBLY__*/
+#endif /* __XLAT_TABLES_H__ */
diff --git a/include/lib/bakery_lock.h b/include/lib/bakery_lock.h
new file mode 100644 (file)
index 0000000..9736f85
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BAKERY_LOCK_H__
+#define __BAKERY_LOCK_H__
+
+#include <platform_def.h>
+
+#define BAKERY_LOCK_MAX_CPUS           PLATFORM_CORE_COUNT
+
+#ifndef __ASSEMBLY__
+#include <stdint.h>
+
+#if USE_COHERENT_MEM
+
+typedef struct bakery_lock {
+       int owner;
+       volatile char entering[BAKERY_LOCK_MAX_CPUS];
+       volatile unsigned number[BAKERY_LOCK_MAX_CPUS];
+} bakery_lock_t;
+
+#define NO_OWNER (-1)
+
+void bakery_lock_init(bakery_lock_t *bakery);
+void bakery_lock_get(bakery_lock_t *bakery);
+void bakery_lock_release(bakery_lock_t *bakery);
+int bakery_lock_try(bakery_lock_t *bakery);
+
+#else
+
+typedef struct bakery_info {
+       /*
+        * The lock_data is a bit-field of 2 members:
+        * Bit[0]       : choosing. This field is set when the CPU is
+        *                choosing its bakery number.
+        * Bits[1 - 15] : number. This is the bakery number allocated.
+        */
+       volatile uint16_t lock_data;
+} bakery_info_t;
+
+void bakery_lock_get(unsigned int id, unsigned int offset);
+void bakery_lock_release(unsigned int id, unsigned int offset);
+
+#endif /* __USE_COHERENT_MEM__ */
+#endif /* __ASSEMBLY__ */
+#endif /* __BAKERY_LOCK_H__ */
diff --git a/include/lib/cassert.h b/include/lib/cassert.h
new file mode 100644 (file)
index 0000000..0e5529d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CASSERT_H__
+#define __CASSERT_H__
+
+/*******************************************************************************
+ * Macro to flag a compile time assertion. It uses the preprocessor to generate
+ * an invalid C construct if 'cond' evaluates to false.
+ * The following  compilation error is triggered if the assertion fails:
+ * "error: size of array 'msg' is negative"
+ ******************************************************************************/
+#define CASSERT(cond, msg)     typedef char msg[(cond) ? 1 : -1]
+
+#endif /* __CASSERT_H__ */
diff --git a/include/lib/cpus/aarch64/aem_generic.h b/include/lib/cpus/aarch64/aem_generic.h
new file mode 100644 (file)
index 0000000..2f701d1
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __AEM_GENERIC_H__
+#define __AEM_GENERIC_H__
+
+/* BASE AEM midr for revision 0 */
+#define BASE_AEM_MIDR 0x410FD0F0
+
+/* Foundation AEM midr for revision 0 */
+#define FOUNDATION_AEM_MIDR  0x410FD000
+
+
+#endif /* __AEM_GENERIC_H__ */
diff --git a/include/lib/cpus/aarch64/cortex_a53.h b/include/lib/cpus/aarch64/cortex_a53.h
new file mode 100644 (file)
index 0000000..14821ab
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CORTEX_A53_H__
+#define __CORTEX_A53_H__
+
+/* Cortex-A53 midr for revision 0 */
+#define CORTEX_A53_MIDR 0x410FD030
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define CPUECTLR_EL1                   S3_1_C15_C2_1   /* Instruction def. */
+
+#define CPUECTLR_SMP_BIT               (1 << 6)
+
+#endif /* __CORTEX_A53_H__ */
diff --git a/include/lib/cpus/aarch64/cortex_a57.h b/include/lib/cpus/aarch64/cortex_a57.h
new file mode 100644 (file)
index 0000000..6128b16
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CORTEX_A57_H__
+#define __CORTEX_A57_H__
+
+/* Cortex-A57 midr for revision 0 */
+#define CORTEX_A57_MIDR 0x410FD070
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define CPUECTLR_EL1                   S3_1_C15_C2_1   /* Instruction def. */
+
+#define CPUECTLR_SMP_BIT               (1 << 6)
+#define CPUECTLR_DIS_TWD_ACC_PFTCH_BIT (1 << 38)
+#define CPUECTLR_L2_IPFTCH_DIST_MASK   (0x3 << 35)
+#define CPUECTLR_L2_DPFTCH_DIST_MASK   (0x3 << 32)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CPUACTLR_EL1                   S3_1_C15_C2_0   /* Instruction def. */
+
+#define CPUACTLR_NO_ALLOC_WBWA         (1 << 49)
+#define CPUACTLR_DCC_AS_DCCI           (1 << 44)
+
+/*******************************************************************************
+ * L2 Control register specific definitions.
+ ******************************************************************************/
+#define L2CTLR_EL1                     S3_1_C11_C0_2   /* Instruction def. */
+
+#define L2CTLR_DATA_RAM_LATENCY_SHIFT  0
+#define L2CTLR_TAG_RAM_LATENCY_SHIFT   6
+
+#define L2_DATA_RAM_LATENCY_3_CYCLES   0x2
+#define L2_TAG_RAM_LATENCY_3_CYCLES    0x2
+
+#endif /* __CORTEX_A57_H__ */
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
new file mode 100644 (file)
index 0000000..089f09c
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+
+#define CPU_IMPL_PN_MASK       (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | \
+                               (MIDR_PN_MASK << MIDR_PN_SHIFT)
+
+       /*
+        * Define the offsets to the fields in cpu_ops structure.
+        */
+       .struct 0
+CPU_MIDR: /* cpu_ops midr */
+       .space  8
+/* Reset fn is needed in BL at reset vector */
+#if IMAGE_BL1 || IMAGE_BL31
+CPU_RESET_FUNC: /* cpu_ops reset_func */
+       .space  8
+#endif
+#if IMAGE_BL31 /* The power down core and cluster is needed only in BL3-1 */
+CPU_PWR_DWN_CORE: /* cpu_ops core_pwr_dwn */
+       .space  8
+CPU_PWR_DWN_CLUSTER: /* cpu_ops cluster_pwr_dwn */
+       .space  8
+#endif
+#if (IMAGE_BL31 && CRASH_REPORTING)
+CPU_REG_DUMP: /* cpu specific register dump for crash reporting */
+       .space  8
+#endif
+CPU_OPS_SIZE = .
+
+       /*
+        * Convenience macro to declare cpu_ops structure.
+        * Make sure the structure fields are as per the offsets
+        * defined above.
+        */
+       .macro declare_cpu_ops _name:req, _midr:req, _noresetfunc = 0
+       .section cpu_ops, "a"; .align 3
+       .type cpu_ops_\_name, %object
+       .quad \_midr
+#if IMAGE_BL1 || IMAGE_BL31
+       .if \_noresetfunc
+       .quad 0
+       .else
+       .quad \_name\()_reset_func
+       .endif
+#endif
+#if IMAGE_BL31
+       .quad \_name\()_core_pwr_dwn
+       .quad \_name\()_cluster_pwr_dwn
+#endif
+#if (IMAGE_BL31 && CRASH_REPORTING)
+       .quad \_name\()_cpu_reg_dump
+#endif
+       .endm
diff --git a/include/lib/mmio.h b/include/lib/mmio.h
new file mode 100644 (file)
index 0000000..5b72218
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MMIO_H__
+#define __MMIO_H__
+
+#include <arch_helpers.h>
+#include <stdint.h>
+
+static inline void mmio_write_8(uintptr_t addr, uint8_t value)
+{
+       dsb();
+       isb();
+       *(volatile uint8_t*)addr = value;
+}
+
+static inline uint8_t mmio_read_8(uintptr_t addr)
+{
+       uint8_t val;
+
+       val = *(volatile uint8_t*)addr;
+       dsb();
+       isb();
+       return val;
+}
+
+static inline void mmio_write_32(uintptr_t addr, uint32_t value)
+{
+       dsb();
+       isb();
+       *(volatile uint32_t*)addr = value;
+}
+
+static inline uint32_t mmio_read_32(uintptr_t addr)
+{
+       uint32_t val;
+
+       val = *(volatile uint32_t*)addr;
+       dsb();
+       isb();
+       return val;
+}
+
+static inline void mmio_write_64(uintptr_t addr, uint64_t value)
+{
+       dsb();
+       isb();
+       *(volatile uint64_t*)addr = value;
+}
+
+static inline uint64_t mmio_read_64(uintptr_t addr)
+{
+       uint64_t val;
+
+       val = *(volatile uint64_t*)addr;
+       dsb();
+       isb();
+       return val;
+}
+
+#endif /* __MMIO_H__ */
diff --git a/include/lib/semihosting.h b/include/lib/semihosting.h
new file mode 100644 (file)
index 0000000..b4eecc5
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SEMIHOSTING_H__
+#define __SEMIHOSTING_H__
+
+#include <stdint.h>
+#include <stdio.h> /* For ssize_t */
+
+
+#define SEMIHOSTING_SYS_OPEN            0x01
+#define SEMIHOSTING_SYS_CLOSE           0x02
+#define SEMIHOSTING_SYS_WRITE0          0x04
+#define SEMIHOSTING_SYS_WRITEC          0x03
+#define SEMIHOSTING_SYS_WRITE           0x05
+#define SEMIHOSTING_SYS_READ            0x06
+#define SEMIHOSTING_SYS_READC           0x07
+#define SEMIHOSTING_SYS_SEEK            0x0A
+#define SEMIHOSTING_SYS_FLEN            0x0C
+#define SEMIHOSTING_SYS_REMOVE          0x0E
+#define SEMIHOSTING_SYS_SYSTEM          0x12
+#define SEMIHOSTING_SYS_ERRNO           0x13
+
+#define FOPEN_MODE_R                   0x0
+#define FOPEN_MODE_RB                  0x1
+#define FOPEN_MODE_RPLUS               0x2
+#define FOPEN_MODE_RPLUSB              0x3
+#define FOPEN_MODE_W                   0x4
+#define FOPEN_MODE_WB                  0x5
+#define FOPEN_MODE_WPLUS               0x6
+#define FOPEN_MODE_WPLUSB              0x7
+#define FOPEN_MODE_A                   0x8
+#define FOPEN_MODE_AB                  0x9
+#define FOPEN_MODE_APLUS               0xa
+#define FOPEN_MODE_APLUSB              0xb
+
+long semihosting_connection_supported(void);
+long semihosting_file_open(const char *file_name, size_t mode);
+long semihosting_file_seek(long file_handle, ssize_t offset);
+long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer);
+long semihosting_file_write(long file_handle,
+                           size_t *length,
+                           const uintptr_t buffer);
+long semihosting_file_close(long file_handle);
+long semihosting_file_length(long file_handle);
+long semihosting_system(char *command_line);
+long semihosting_get_flen(const char *file_name);
+long semihosting_download_file(const char *file_name,
+                              size_t buf_size,
+                              uintptr_t buf);
+void semihosting_write_char(char character);
+void semihosting_write_string(char *string);
+char semihosting_read_char(void);
+
+#endif /* __SEMIHOSTING_H__ */
diff --git a/include/lib/spinlock.h b/include/lib/spinlock.h
new file mode 100644 (file)
index 0000000..cb0bc3e
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SPINLOCK_H__
+#define __SPINLOCK_H__
+
+typedef struct spinlock {
+       volatile unsigned int lock;
+} spinlock_t;
+
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __SPINLOCK_H__ */
diff --git a/include/lib/utils.h b/include/lib/utils.h
new file mode 100644 (file)
index 0000000..b6bc9af
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+/* Compute the number of elements in the given array */
+#define ARRAY_SIZE(a)                          \
+       (sizeof(a) / sizeof((a)[0]))
+
+#define IS_POWER_OF_TWO(x)                     \
+       (((x) & ((x) - 1)) == 0)
+
+#define SIZE_FROM_LOG2_WORDS(n)                (4 << (n))
+
+#define BIT(nr)                                (1UL << (nr))
+
+/*
+ * The round_up() macro rounds up a value to the given boundary in a
+ * type-agnostic yet type-safe manner. The boundary must be a power of two.
+ * In other words, it computes the smallest multiple of boundary which is
+ * greater than or equal to value.
+ *
+ * round_down() is similar but rounds the value down instead.
+ */
+#define round_boundary(value, boundary)                \
+       ((__typeof__(value))((boundary) - 1))
+
+#define round_up(value, boundary)              \
+       ((((value) - 1) | round_boundary(value, boundary)) + 1)
+
+#define round_down(value, boundary)            \
+       ((value) & ~round_boundary(value, boundary))
+
+/*
+ * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise.
+ * Both arguments must be unsigned pointer values (i.e. uintptr_t).
+ */
+#define check_uptr_overflow(ptr, inc)          \
+       (((ptr) > UINTPTR_MAX - (inc)) ? 1 : 0)
+
+/*
+ * For those constants to be shared between C and other sources, apply a 'ull'
+ * suffix to the argument only in C, to avoid undefined or unintended behaviour.
+ *
+ * The GNU assembler and linker do not support the 'ull' suffix (it causes the
+ * build process to fail) therefore the suffix is omitted when used in linker
+ * scripts and assembler files.
+*/
+#if defined(__LINKER__) || defined(__ASSEMBLY__)
+# define ULL(_x)       (_x)
+#else
+# define ULL(_x)       (_x##ull)
+#endif
+
+#endif /* __UTILS_H__ */
diff --git a/include/plat/common/plat_config.h b/include/plat/common/plat_config.h
new file mode 100644 (file)
index 0000000..20d3c03
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __PLAT_CONFIG_H__
+#define __PLAT_CONFIG_H__
+
+#define CONFIG_GICC_BASE_OFFSET                0x4
+
+
+#ifndef __ASSEMBLY__
+
+#include <cassert.h>
+
+
+enum plat_config_flags {
+       /* Whether Base FVP memory map is in use */
+       CONFIG_BASE_MMAP                = 0x1,
+       /* Whether CCI should be enabled */
+       CONFIG_HAS_CCI                  = 0x2,
+       /* Whether TZC should be configured */
+       CONFIG_HAS_TZC                  = 0x4
+};
+
+typedef struct plat_config {
+       unsigned int gicd_base;
+       unsigned int gicc_base;
+       unsigned int gich_base;
+       unsigned int gicv_base;
+       unsigned int max_aff0;
+       unsigned int max_aff1;
+       unsigned long flags;
+} plat_config_t;
+
+inline const plat_config_t *get_plat_config();
+
+
+CASSERT(CONFIG_GICC_BASE_OFFSET == __builtin_offsetof(
+       plat_config_t, gicc_base),
+       assert_gicc_base_offset_mismatch);
+
+/* If used, plat_config must be defined and populated in the platform port*/
+extern plat_config_t plat_config;
+
+inline const plat_config_t *get_plat_config()
+{
+       return &plat_config;
+}
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __PLAT_CONFIG_H__ */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
new file mode 100644 (file)
index 0000000..66d7bc9
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+#include <stdint.h>
+
+
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+struct plat_pm_ops;
+struct meminfo;
+struct image_info;
+struct entry_point_info;
+struct bl31_params;
+
+/*******************************************************************************
+ * Function declarations
+ ******************************************************************************/
+/*******************************************************************************
+ * Mandatory common functions
+ ******************************************************************************/
+uint64_t plat_get_syscnt_freq(void);
+int plat_get_image_source(const char *image_name,
+                       uintptr_t *dev_handle,
+                       uintptr_t *image_spec);
+unsigned long plat_get_ns_image_entrypoint(void);
+
+/*******************************************************************************
+ * Mandatory interrupt management functions
+ ******************************************************************************/
+uint32_t plat_ic_get_pending_interrupt_id(void);
+uint32_t plat_ic_get_pending_interrupt_type(void);
+uint32_t plat_ic_acknowledge_interrupt(void);
+uint32_t plat_ic_get_interrupt_type(uint32_t id);
+void plat_ic_end_of_interrupt(uint32_t id);
+uint32_t plat_interrupt_type_to_line(uint32_t type,
+                                    uint32_t security_state);
+
+/*******************************************************************************
+ * Optional common functions (may be overridden)
+ ******************************************************************************/
+unsigned int platform_get_core_pos(unsigned long mpidr);
+unsigned long platform_get_stack(unsigned long mpidr);
+void plat_report_exception(unsigned long);
+int plat_crash_console_init(void);
+int plat_crash_console_putc(int c);
+
+/*******************************************************************************
+ * Mandatory BL1 functions
+ ******************************************************************************/
+void bl1_early_platform_setup(void);
+void bl1_plat_arch_setup(void);
+void bl1_platform_setup(void);
+struct meminfo *bl1_plat_sec_mem_layout(void);
+
+/*
+ * This function allows the platform to change the entrypoint information for
+ * BL2, after BL1 has loaded BL2 into memory but before BL2 is executed.
+ */
+void bl1_plat_set_bl2_ep_info(struct image_info *image,
+                             struct entry_point_info *ep);
+
+/*******************************************************************************
+ * Optional BL1 functions (may be overridden)
+ ******************************************************************************/
+void bl1_init_bl2_mem_layout(const struct meminfo *bl1_mem_layout,
+                            struct meminfo *bl2_mem_layout);
+
+/*******************************************************************************
+ * Mandatory BL2 functions
+ ******************************************************************************/
+void bl2_early_platform_setup(struct meminfo *mem_layout);
+void bl2_plat_arch_setup(void);
+void bl2_platform_setup(void);
+struct meminfo *bl2_plat_sec_mem_layout(void);
+
+/*
+ * This function returns a pointer to the shared memory that the platform has
+ * kept aside to pass trusted firmware related information that BL3-1
+ * could need
+ */
+struct bl31_params *bl2_plat_get_bl31_params(void);
+
+/*
+ * This function returns a pointer to the shared memory that the platform
+ * has kept to point to entry point information of BL31 to BL2
+ */
+struct entry_point_info *bl2_plat_get_bl31_ep_info(void);
+
+/*
+ * This function flushes to main memory all the params that are
+ * passed to BL3-1
+ */
+void bl2_plat_flush_bl31_params(void);
+
+/*
+ * The next 2 functions allow the platform to change the entrypoint information
+ * for the mandatory 3rd level BL images, BL3-1 and BL3-3. This is done after
+ * BL2 has loaded those images into memory but before BL3-1 is executed.
+ */
+void bl2_plat_set_bl31_ep_info(struct image_info *image,
+                              struct entry_point_info *ep);
+
+void bl2_plat_set_bl33_ep_info(struct image_info *image,
+                              struct entry_point_info *ep);
+
+/* Gets the memory layout for BL3-3 */
+void bl2_plat_get_bl33_meminfo(struct meminfo *mem_info);
+
+/*******************************************************************************
+ * Conditionally mandatory BL2 functions: must be implemented if BL3-0 image
+ * is supported
+ ******************************************************************************/
+/* Gets the memory layout for BL3-0 */
+void bl2_plat_get_bl30_meminfo(struct meminfo *mem_info);
+
+/*
+ * This function is called after loading BL3-0 image and it is used to perform
+ * any platform-specific actions required to handle the SCP firmware.
+ */
+int bl2_plat_handle_bl30(struct image_info *bl30_image_info);
+
+/*******************************************************************************
+ * Conditionally mandatory BL2 functions: must be implemented if BL3-2 image
+ * is supported
+ ******************************************************************************/
+void bl2_plat_set_bl32_ep_info(struct image_info *image,
+                              struct entry_point_info *ep);
+
+/* Gets the memory layout for BL3-2 */
+void bl2_plat_get_bl32_meminfo(struct meminfo *mem_info);
+
+/*******************************************************************************
+ * Optional BL2 functions (may be overridden)
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Mandatory BL3-1 functions
+ ******************************************************************************/
+void bl31_early_platform_setup(struct bl31_params *from_bl2,
+                               void *plat_params_from_bl2);
+void bl31_plat_arch_setup(void);
+void bl31_platform_setup(void);
+struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type);
+struct image_info *bl31_plat_get_next_image_image_info(uint32_t type);
+
+/*******************************************************************************
+ * Mandatory PSCI functions (BL3-1)
+ ******************************************************************************/
+int platform_setup_pm(const struct plat_pm_ops **);
+int plat_get_max_afflvl(void);
+unsigned int plat_get_aff_count(unsigned int, unsigned long);
+unsigned int plat_get_aff_state(unsigned int, unsigned long);
+
+/*******************************************************************************
+ * Optional BL3-1 functions (may be overridden)
+ ******************************************************************************/
+void bl31_plat_enable_mmu(uint32_t flags);
+
+/*******************************************************************************
+ * Optional BL3-2 functions (may be overridden)
+ ******************************************************************************/
+void bl32_plat_enable_mmu(uint32_t flags);
+
+/*******************************************************************************
+ * Trusted Boot functions
+ ******************************************************************************/
+int plat_match_rotpk(const unsigned char *, unsigned int);
+
+#endif /* __PLATFORM_H__ */
diff --git a/include/stdlib/assert.h b/include/stdlib/assert.h
new file mode 100644 (file)
index 0000000..5621f8c
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)assert.h    8.2 (Berkeley) 1/21/94
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+
+/*
+ * Unlike other ANSI header files, <assert.h> may usefully be included
+ * multiple times, with and without NDEBUG defined.
+ */
+
+#undef assert
+#undef _assert
+
+#ifdef NDEBUG
+#define        assert(e)       ((void)0)
+#define        _assert(e)      ((void)0)
+#else
+#define        _assert(e)      assert(e)
+
+#define        assert(e)       ((e) ? (void)0 : __assert(__func__, __FILE__, \
+                           __LINE__, #e))
+#endif /* NDEBUG */
+
+#ifndef _ASSERT_H_
+#define _ASSERT_H_
+__BEGIN_DECLS
+void __assert(const char *, const char *, int, const char *) __dead2;
+__END_DECLS
+#endif /* !_ASSERT_H_ */
diff --git a/include/stdlib/inttypes.h b/include/stdlib/inttypes.h
new file mode 100644 (file)
index 0000000..269f3e7
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _INTTYPES_H_
+#define        _INTTYPES_H_
+
+#include <machine/_inttypes.h>
+#include <sys/stdint.h>
+
+typedef struct {
+       intmax_t        quot;           /* Quotient. */
+       intmax_t        rem;            /* Remainder. */
+} imaxdiv_t;
+
+__BEGIN_DECLS
+#ifdef _XLOCALE_H_
+#include <xlocale/_inttypes.h>
+#endif
+intmax_t       imaxabs(intmax_t) __pure2;
+imaxdiv_t      imaxdiv(intmax_t, intmax_t) __pure2;
+
+intmax_t       strtoimax(const char *__restrict, char **__restrict, int);
+uintmax_t      strtoumax(const char *__restrict, char **__restrict, int);
+
+__END_DECLS
+
+#endif /* !_INTTYPES_H_ */
diff --git a/include/stdlib/machine/_inttypes.h b/include/stdlib/machine/_inttypes.h
new file mode 100644 (file)
index 0000000..8dd07d6
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_INTTYPES_H_
+#define _MACHINE_INTTYPES_H_
+
+/*
+ * Trusted Firmware does not depend on any definitions in this file. Content
+ * will be added as needed.
+ */
+
+#endif /* !_MACHINE_INTTYPES_H_ */
diff --git a/include/stdlib/machine/_limits.h b/include/stdlib/machine/_limits.h
new file mode 100644 (file)
index 0000000..49a768b
--- /dev/null
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *     @(#)limits.h    8.3 (Berkeley) 1/4/94
+ * $FreeBSD$
+ */
+
+#ifndef        _MACHINE__LIMITS_H_
+#define        _MACHINE__LIMITS_H_
+
+/*
+ * According to ANSI (section 2.2.4.2), the values below must be usable by
+ * #if preprocessing directives.  Additionally, the expression must have the
+ * same type as would an expression that is an object of the corresponding
+ * type converted according to the integral promotions.  The subtraction for
+ * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an
+ * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2).
+ */
+
+#define        __CHAR_BIT      8               /* number of bits in a char */
+
+#define        __SCHAR_MAX     0x7f            /* max value for a signed char */
+#define        __SCHAR_MIN     (-0x7f-1)       /* min value for a signed char */
+
+#define        __UCHAR_MAX     0xff            /* max value for an unsigned char */
+
+#define        __USHRT_MAX     0xffff          /* max value for an unsigned short */
+#define        __SHRT_MAX      0x7fff          /* max value for a short */
+#define        __SHRT_MIN      (-0x7fff-1)     /* min value for a short */
+
+#define        __UINT_MAX      0xffffffff      /* max value for an unsigned int */
+#define        __INT_MAX       0x7fffffff      /* max value for an int */
+#define        __INT_MIN       (-0x7fffffff-1) /* min value for an int */
+
+#define        __ULONG_MAX     0xffffffffffffffff      /* max for an unsigned long */
+#define        __LONG_MAX      0x7fffffffffffffff      /* max for a long */
+#define        __LONG_MIN      (-0x7fffffffffffffff-1) /* min for a long */
+
+/* Long longs have the same size but not the same type as longs. */
+                                       /* max for an unsigned long long */
+#define        __ULLONG_MAX    0xffffffffffffffffULL
+#define        __LLONG_MAX     0x7fffffffffffffffLL    /* max for a long long */
+#define        __LLONG_MIN     (-0x7fffffffffffffffLL-1) /* min for a long long */
+
+#define        __SSIZE_MAX     __LONG_MAX      /* max value for a ssize_t */
+
+#define        __SIZE_T_MAX    __ULONG_MAX     /* max value for a size_t */
+
+#define        __OFF_MAX       __LONG_MAX      /* max value for an off_t */
+#define        __OFF_MIN       __LONG_MIN      /* min value for an off_t */
+
+/* Quads and longs are the same size.  Ensure they stay in sync. */
+#define        __UQUAD_MAX     (__ULONG_MAX)   /* max value for a uquad_t */
+#define        __QUAD_MAX      (__LONG_MAX)    /* max value for a quad_t */
+#define        __QUAD_MIN      (__LONG_MIN)    /* min value for a quad_t */
+
+#define        __LONG_BIT      64
+#define        __WORD_BIT      32
+
+/* Minimum signal stack size. */
+#define        __MINSIGSTKSZ   (1024 * 4)
+
+#endif /* !_MACHINE__LIMITS_H_ */
diff --git a/include/stdlib/machine/_stdint.h b/include/stdlib/machine/_stdint.h
new file mode 100644 (file)
index 0000000..e36c659
--- /dev/null
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 2001, 2002 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef        _MACHINE__STDINT_H_
+#define        _MACHINE__STDINT_H_
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS)
+
+#define        INT8_C(c)               (c)
+#define        INT16_C(c)              (c)
+#define        INT32_C(c)              (c)
+#define        INT64_C(c)              (c ## L)
+
+#define        UINT8_C(c)              (c)
+#define        UINT16_C(c)             (c)
+#define        UINT32_C(c)             (c ## U)
+#define        UINT64_C(c)             (c ## UL)
+
+#define        INTMAX_C(c)             INT64_C(c)
+#define        UINTMAX_C(c)            UINT64_C(c)
+
+#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.1 Limits of exact-width integer types
+ */
+/* Minimum values of exact-width signed integer types. */
+#define        INT8_MIN        (-0x7f-1)
+#define        INT16_MIN       (-0x7fff-1)
+#define        INT32_MIN       (-0x7fffffff-1)
+#define        INT64_MIN       (-0x7fffffffffffffffL-1)
+
+/* Maximum values of exact-width signed integer types. */
+#define        INT8_MAX        0x7f
+#define        INT16_MAX       0x7fff
+#define        INT32_MAX       0x7fffffff
+#define        INT64_MAX       0x7fffffffffffffffL
+
+/* Maximum values of exact-width unsigned integer types. */
+#define        UINT8_MAX       0xff
+#define        UINT16_MAX      0xffff
+#define        UINT32_MAX      0xffffffffU
+#define        UINT64_MAX      0xffffffffffffffffUL
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.2  Limits of minimum-width integer types
+ */
+/* Minimum values of minimum-width signed integer types. */
+#define        INT_LEAST8_MIN  INT8_MIN
+#define        INT_LEAST16_MIN INT16_MIN
+#define        INT_LEAST32_MIN INT32_MIN
+#define        INT_LEAST64_MIN INT64_MIN
+
+/* Maximum values of minimum-width signed integer types. */
+#define        INT_LEAST8_MAX  INT8_MAX
+#define        INT_LEAST16_MAX INT16_MAX
+#define        INT_LEAST32_MAX INT32_MAX
+#define        INT_LEAST64_MAX INT64_MAX
+
+/* Maximum values of minimum-width unsigned integer types. */
+#define        UINT_LEAST8_MAX  UINT8_MAX
+#define        UINT_LEAST16_MAX UINT16_MAX
+#define        UINT_LEAST32_MAX UINT32_MAX
+#define        UINT_LEAST64_MAX UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.3  Limits of fastest minimum-width integer types
+ */
+/* Minimum values of fastest minimum-width signed integer types. */
+#define        INT_FAST8_MIN   INT32_MIN
+#define        INT_FAST16_MIN  INT32_MIN
+#define        INT_FAST32_MIN  INT32_MIN
+#define        INT_FAST64_MIN  INT64_MIN
+
+/* Maximum values of fastest minimum-width signed integer types. */
+#define        INT_FAST8_MAX   INT32_MAX
+#define        INT_FAST16_MAX  INT32_MAX
+#define        INT_FAST32_MAX  INT32_MAX
+#define        INT_FAST64_MAX  INT64_MAX
+
+/* Maximum values of fastest minimum-width unsigned integer types. */
+#define        UINT_FAST8_MAX  UINT32_MAX
+#define        UINT_FAST16_MAX UINT32_MAX
+#define        UINT_FAST32_MAX UINT32_MAX
+#define        UINT_FAST64_MAX UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.4  Limits of integer types capable of holding object pointers
+ */
+#define        INTPTR_MIN      INT64_MIN
+#define        INTPTR_MAX      INT64_MAX
+#define        UINTPTR_MAX     UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.5  Limits of greatest-width integer types
+ */
+#define        INTMAX_MIN      INT64_MIN
+#define        INTMAX_MAX      INT64_MAX
+#define        UINTMAX_MAX     UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.3  Limits of other integer types
+ */
+/* Limits of ptrdiff_t. */
+#define        PTRDIFF_MIN     INT64_MIN       
+#define        PTRDIFF_MAX     INT64_MAX
+
+/* Limits of sig_atomic_t. */
+#define        SIG_ATOMIC_MIN  INT32_MIN
+#define        SIG_ATOMIC_MAX  INT32_MAX
+
+/* Limit of size_t. */
+#define        SIZE_MAX        UINT64_MAX
+
+#ifndef WCHAR_MIN /* Also possibly defined in <wchar.h> */
+/* Limits of wchar_t. */
+#define        WCHAR_MIN       INT32_MIN
+#define        WCHAR_MAX       INT32_MAX
+#endif
+
+/* Limits of wint_t. */
+#define        WINT_MIN        INT32_MIN
+#define        WINT_MAX        INT32_MAX
+
+#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */
+
+#endif /* !_MACHINE__STDINT_H_ */
diff --git a/include/stdlib/machine/_types.h b/include/stdlib/machine/_types.h
new file mode 100644 (file)
index 0000000..7e993c4
--- /dev/null
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     From: @(#)ansi.h        8.2 (Berkeley) 1/4/94
+ *     From: @(#)types.h       8.3 (Berkeley) 1/5/94
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE__TYPES_H_
+#define        _MACHINE__TYPES_H_
+
+#ifndef _SYS_CDEFS_H_
+#error this file needs sys/cdefs.h as a prerequisite
+#endif
+
+/*
+ * Basic types upon which most other types are built.
+ */
+typedef        __signed char           __int8_t;
+typedef        unsigned char           __uint8_t;
+typedef        short                   __int16_t;
+typedef        unsigned short          __uint16_t;
+typedef        int                     __int32_t;
+typedef        unsigned int            __uint32_t;
+typedef        long                    __int64_t;
+typedef        unsigned long           __uint64_t;
+
+/*
+ * Standard type definitions.
+ */
+typedef        __int32_t       __clock_t;              /* clock()... */
+typedef        __int64_t       __critical_t;
+typedef        double          __double_t;
+typedef        float           __float_t;
+typedef        __int64_t       __intfptr_t;
+typedef        __int64_t       __intmax_t;
+typedef        __int64_t       __intptr_t;
+typedef        __int32_t       __int_fast8_t;
+typedef        __int32_t       __int_fast16_t;
+typedef        __int32_t       __int_fast32_t;
+typedef        __int64_t       __int_fast64_t;
+typedef        __int8_t        __int_least8_t;
+typedef        __int16_t       __int_least16_t;
+typedef        __int32_t       __int_least32_t;
+typedef        __int64_t       __int_least64_t;
+typedef        __int64_t       __ptrdiff_t;            /* ptr1 - ptr2 */
+typedef        __int64_t       __register_t;
+typedef        __int64_t       __segsz_t;              /* segment size (in pages) */
+typedef        __uint64_t      __size_t;               /* sizeof() */
+typedef        __int64_t       __ssize_t;              /* byte count or error */
+typedef        __int64_t       __time_t;               /* time()... */
+typedef        __uint64_t      __uintfptr_t;
+typedef        __uint64_t      __uintmax_t;
+typedef        __uint64_t      __uintptr_t;
+typedef        __uint32_t      __uint_fast8_t;
+typedef        __uint32_t      __uint_fast16_t;
+typedef        __uint32_t      __uint_fast32_t;
+typedef        __uint64_t      __uint_fast64_t;
+typedef        __uint8_t       __uint_least8_t;
+typedef        __uint16_t      __uint_least16_t;
+typedef        __uint32_t      __uint_least32_t;
+typedef        __uint64_t      __uint_least64_t;
+typedef        __uint64_t      __u_register_t;
+typedef        __uint64_t      __vm_offset_t;
+typedef        __int64_t       __vm_ooffset_t;
+typedef        __uint64_t      __vm_paddr_t;
+typedef        __uint64_t      __vm_pindex_t;
+typedef        __uint64_t      __vm_size_t;
+
+/*
+ * Unusual type definitions.
+ */
+#ifdef __GNUCLIKE_BUILTIN_VARARGS
+typedef __builtin_va_list      __va_list;      /* internally known to gcc */
+#else
+typedef        char *                  __va_list;
+#endif /* __GNUCLIKE_BUILTIN_VARARGS */
+#if defined(__GNUCLIKE_BUILTIN_VAALIST) && !defined(__GNUC_VA_LIST) \
+    && !defined(__NO_GNUC_VA_LIST)
+#define __GNUC_VA_LIST
+typedef __va_list              __gnuc_va_list; /* compatibility w/GNU headers*/
+#endif
+
+#endif /* !_MACHINE__TYPES_H_ */
diff --git a/include/stdlib/stddef.h b/include/stdlib/stddef.h
new file mode 100644 (file)
index 0000000..ea88214
--- /dev/null
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)stddef.h    8.1 (Berkeley) 6/2/93
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _STDDEF_H_
+#define _STDDEF_H_
+
+#include <sys/cdefs.h>
+#include <sys/_null.h>
+#include <sys/_types.h>
+
+typedef        __ptrdiff_t     ptrdiff_t;
+
+#if __BSD_VISIBLE
+#ifndef _RUNE_T_DECLARED
+typedef        __rune_t        rune_t;
+#define        _RUNE_T_DECLARED
+#endif
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+#ifndef        __cplusplus
+#ifndef _WCHAR_T_DECLARED
+typedef        __wchar_t       wchar_t;
+#define        _WCHAR_T_DECLARED
+#endif
+#endif
+
+#define        offsetof(type, member)  __offsetof(type, member)
+
+#endif /* _STDDEF_H_ */
diff --git a/include/stdlib/stdio.h b/include/stdlib/stdio.h
new file mode 100644 (file)
index 0000000..60e081b
--- /dev/null
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)stdio.h     8.5 (Berkeley) 4/29/95
+ * $FreeBSD$
+ */
+
+/*
+ * Portions copyright (c) 2013-2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+
+#ifndef        _STDIO_H_
+#define        _STDIO_H_
+
+#include <sys/cdefs.h>
+#include <sys/_null.h>
+#include <sys/_types.h>
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+#ifndef _SSIZE_T_DECLARED
+#define        _SSIZE_T_DECLARED
+typedef        __ssize_t       ssize_t;
+#endif
+
+#define        EOF     (-1)
+
+int     printf(const char * __restrict, ...);
+int     putchar(int);
+int     puts(const char *);
+int     sprintf(char * __restrict, const char * __restrict, ...);
+int     vsprintf(char * __restrict, const char * __restrict,
+          __va_list);
+
+int     sscanf(const char *__restrict, char const *__restrict, ...);
+
+#if __ISO_C_VISIBLE >= 1999
+int     snprintf(char * __restrict, size_t, const char * __restrict,
+          ...) __printflike(3, 4);
+int     vsnprintf(char * __restrict, size_t, const char * __restrict,
+          __va_list) __printflike(3, 0);
+#endif
+
+#endif /* !_STDIO_H_ */
diff --git a/include/stdlib/stdlib.h b/include/stdlib/stdlib.h
new file mode 100644 (file)
index 0000000..b1ac1bf
--- /dev/null
@@ -0,0 +1,313 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)stdlib.h    8.5 (Berkeley) 5/19/95
+ * $FreeBSD$
+ */
+
+#ifndef _STDLIB_H_
+#define        _STDLIB_H_
+
+#include <sys/cdefs.h>
+#include <sys/_null.h>
+#include <sys/_types.h>
+
+#if __BSD_VISIBLE
+#ifndef _RUNE_T_DECLARED
+typedef        __rune_t        rune_t;
+#define        _RUNE_T_DECLARED
+#endif
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+typedef struct {
+       int     quot;           /* quotient */
+       int     rem;            /* remainder */
+} div_t;
+
+typedef struct {
+       long    quot;
+       long    rem;
+} ldiv_t;
+
+#define        EXIT_FAILURE    1
+#define        EXIT_SUCCESS    0
+
+#define        RAND_MAX        0x7ffffffd
+
+__BEGIN_DECLS
+#ifdef _XLOCALE_H_
+#include <xlocale/_stdlib.h>
+#endif
+extern int __mb_cur_max;
+extern int ___mb_cur_max(void);
+#define        MB_CUR_MAX      (___mb_cur_max())
+
+_Noreturn void  abort(void);
+int     abs(int) __pure2;
+int     atexit(void (*)(void));
+double  atof(const char *);
+int     atoi(const char *);
+long    atol(const char *);
+void   *bsearch(const void *, const void *, size_t,
+           size_t, int (*)(const void *, const void *));
+void   *calloc(size_t, size_t) __malloc_like;
+div_t   div(int, int) __pure2;
+_Noreturn void  exit(int);
+void    free(void *);
+char   *getenv(const char *);
+long    labs(long) __pure2;
+ldiv_t  ldiv(long, long) __pure2;
+void   *malloc(size_t) __malloc_like;
+int     mblen(const char *, size_t);
+void    qsort(void *, size_t, size_t,
+           int (*)(const void *, const void *));
+int     rand(void);
+void   *realloc(void *, size_t);
+void    srand(unsigned);
+double  strtod(const char *__restrict, char **__restrict);
+float   strtof(const char *__restrict, char **__restrict);
+long    strtol(const char *__restrict, char **__restrict, int);
+long double
+        strtold(const char *__restrict, char **__restrict);
+unsigned long
+        strtoul(const char *__restrict, char **__restrict, int);
+int     system(const char *);
+
+/*
+ * Functions added in C99 which we make conditionally available in the
+ * BSD^C89 namespace if the compiler supports `long long'.
+ * The #if test is more complicated than it ought to be because
+ * __BSD_VISIBLE implies __ISO_C_VISIBLE == 1999 *even if* `long long'
+ * is not supported in the compilation environment (which therefore means
+ * that it can't really be ISO C99).
+ *
+ * (The only other extension made by C99 in thie header is _Exit().)
+ */
+#if __ISO_C_VISIBLE >= 1999
+#ifdef __LONG_LONG_SUPPORTED
+/* LONGLONG */
+typedef struct {
+       long long quot;
+       long long rem;
+} lldiv_t;
+
+/* LONGLONG */
+long long
+        atoll(const char *);
+/* LONGLONG */
+long long
+        llabs(long long) __pure2;
+/* LONGLONG */
+lldiv_t         lldiv(long long, long long) __pure2;
+/* LONGLONG */
+long long
+        strtoll(const char *__restrict, char **__restrict, int);
+/* LONGLONG */
+unsigned long long
+        strtoull(const char *__restrict, char **__restrict, int);
+#endif /* __LONG_LONG_SUPPORTED */
+
+_Noreturn void  _Exit(int);
+#endif /* __ISO_C_VISIBLE >= 1999 */
+
+/*
+ * If we're in a mode greater than C99, expose C11 functions.
+ */
+#if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L
+void *aligned_alloc(size_t, size_t) __malloc_like;
+int    at_quick_exit(void (*)(void));
+_Noreturn void
+       quick_exit(int);
+#endif /* __ISO_C_VISIBLE >= 2011 */
+/*
+ * Extensions made by POSIX relative to C.
+ */
+#if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE
+char   *realpath(const char *__restrict, char *__restrict);
+#endif
+#if __POSIX_VISIBLE >= 199506
+int     rand_r(unsigned *);                    /* (TSF) */
+#endif
+#if __POSIX_VISIBLE >= 200112
+int     posix_memalign(void **, size_t, size_t); /* (ADV) */
+int     setenv(const char *, const char *, int);
+int     unsetenv(const char *);
+#endif
+
+#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE
+int     getsubopt(char **, char *const *, char **);
+#ifndef _MKDTEMP_DECLARED
+char   *mkdtemp(char *);
+#define        _MKDTEMP_DECLARED
+#endif
+#ifndef _MKSTEMP_DECLARED
+int     mkstemp(char *);
+#define        _MKSTEMP_DECLARED
+#endif
+#endif /* __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE */
+
+/*
+ * The only changes to the XSI namespace in revision 6 were the deletion
+ * of the ttyslot() and valloc() functions, which FreeBSD never declared
+ * in this header.  For revision 7, ecvt(), fcvt(), and gcvt(), which
+ * FreeBSD also does not have, and mktemp(), are to be deleted.
+ */
+#if __XSI_VISIBLE
+/* XXX XSI requires pollution from <sys/wait.h> here.  We'd rather not. */
+long    a64l(const char *);
+double  drand48(void);
+/* char        *ecvt(double, int, int * __restrict, int * __restrict); */
+double  erand48(unsigned short[3]);
+/* char        *fcvt(double, int, int * __restrict, int * __restrict); */
+/* char        *gcvt(double, int, int * __restrict, int * __restrict); */
+int     grantpt(int);
+char   *initstate(unsigned long /* XSI requires u_int */, char *, long);
+long    jrand48(unsigned short[3]);
+char   *l64a(long);
+void    lcong48(unsigned short[7]);
+long    lrand48(void);
+#if !defined(_MKTEMP_DECLARED) && (__BSD_VISIBLE || __XSI_VISIBLE <= 600)
+char   *mktemp(char *);
+#define        _MKTEMP_DECLARED
+#endif
+long    mrand48(void);
+long    nrand48(unsigned short[3]);
+int     posix_openpt(int);
+char   *ptsname(int);
+int     putenv(char *);
+long    random(void);
+unsigned short
+       *seed48(unsigned short[3]);
+#ifndef _SETKEY_DECLARED
+int     setkey(const char *);
+#define        _SETKEY_DECLARED
+#endif
+char   *setstate(/* const */ char *);
+void    srand48(long);
+void    srandom(unsigned long);
+int     unlockpt(int);
+#endif /* __XSI_VISIBLE */
+
+#if __BSD_VISIBLE
+extern const char *malloc_conf;
+extern void (*malloc_message)(void *, const char *);
+
+/*
+ * The alloca() function can't be implemented in C, and on some
+ * platforms it can't be implemented at all as a callable function.
+ * The GNU C compiler provides a built-in alloca() which we can use;
+ * in all other cases, provide a prototype, mainly to pacify various
+ * incarnations of lint.  On platforms where alloca() is not in libc,
+ * programs which use it will fail to link when compiled with non-GNU
+ * compilers.
+ */
+#if __GNUC__ >= 2 || defined(__INTEL_COMPILER)
+#undef  alloca /* some GNU bits try to get cute and define this on their own */
+#define alloca(sz) __builtin_alloca(sz)
+#elif defined(lint)
+void   *alloca(size_t);
+#endif
+
+void    abort2(const char *, int, void **) __dead2;
+__uint32_t
+        arc4random(void);
+void    arc4random_addrandom(unsigned char *, int);
+void    arc4random_buf(void *, size_t);
+void    arc4random_stir(void);
+__uint32_t
+        arc4random_uniform(__uint32_t);
+#ifdef __BLOCKS__
+int     atexit_b(void (^)(void));
+void   *bsearch_b(const void *, const void *, size_t,
+           size_t, int (^)(const void *, const void *));
+#endif
+char   *getbsize(int *, long *);
+                                       /* getcap(3) functions */
+char   *cgetcap(char *, const char *, int);
+int     cgetclose(void);
+int     cgetent(char **, char **, const char *);
+int     cgetfirst(char **, char **);
+int     cgetmatch(const char *, const char *);
+int     cgetnext(char **, char **);
+int     cgetnum(char *, const char *, long *);
+int     cgetset(const char *);
+int     cgetstr(char *, const char *, char **);
+int     cgetustr(char *, const char *, char **);
+
+int     daemon(int, int);
+char   *devname(__dev_t, __mode_t);
+char   *devname_r(__dev_t, __mode_t, char *, int);
+char   *fdevname(int);
+char   *fdevname_r(int, char *, int);
+int     getloadavg(double [], int);
+const char *
+        getprogname(void);
+
+int     heapsort(void *, size_t, size_t, int (*)(const void *, const void *));
+#ifdef __BLOCKS__
+int     heapsort_b(void *, size_t, size_t, int (^)(const void *, const void *));
+void    qsort_b(void *, size_t, size_t,
+           int (^)(const void *, const void *));
+#endif
+int     l64a_r(long, char *, int);
+int     mergesort(void *, size_t, size_t, int (*)(const void *, const void *));
+#ifdef __BLOCKS__
+int     mergesort_b(void *, size_t, size_t, int (^)(const void *, const void *));
+#endif
+int     mkostemp(char *, int);
+int     mkostemps(char *, int, int);
+void    qsort_r(void *, size_t, size_t, void *,
+           int (*)(void *, const void *, const void *));
+int     radixsort(const unsigned char **, int, const unsigned char *,
+           unsigned);
+void    *reallocf(void *, size_t);
+int     rpmatch(const char *);
+void    setprogname(const char *);
+int     sradixsort(const unsigned char **, int, const unsigned char *,
+           unsigned);
+void    sranddev(void);
+void    srandomdev(void);
+long long
+       strtonum(const char *, long long, long long, const char **);
+
+/* Deprecated interfaces, to be removed in FreeBSD 6.0. */
+__int64_t
+        strtoq(const char *, char **, int);
+__uint64_t
+        strtouq(const char *, char **, int);
+
+extern char *suboptarg;                        /* getsubopt(3) external variable */
+#endif /* __BSD_VISIBLE */
+__END_DECLS
+
+#endif /* !_STDLIB_H_ */
diff --git a/include/stdlib/string.h b/include/stdlib/string.h
new file mode 100644 (file)
index 0000000..61e8102
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)string.h    8.1 (Berkeley) 6/2/93
+ * $FreeBSD$
+ */
+
+/*
+ * Portions copyright (c) 2013-2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#ifndef _STRING_H_
+#define        _STRING_H_
+
+#include <sys/cdefs.h>
+#include <sys/_null.h>
+#include <sys/_types.h>
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+__BEGIN_DECLS
+
+void   *memchr(const void *, int, size_t) __pure;
+int     memcmp(const void *, const void *, size_t) __pure;
+void   *memcpy(void * __restrict, const void * __restrict, size_t);
+void   *memmove(void *, const void *, size_t);
+void   *memset(void *, int, size_t);
+
+char   *strchr(const char *, int) __pure;
+int     strcmp(const char *, const char *) __pure;
+size_t  strlen(const char *) __pure;
+int     strncmp(const char *, const char *, size_t) __pure;
+int     strcasecmp(const char *, const char *);
+
+__END_DECLS
+
+#endif /* _STRING_H_ */
diff --git a/include/stdlib/strings.h b/include/stdlib/strings.h
new file mode 100644 (file)
index 0000000..2210df0
--- /dev/null
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _STRINGS_H_
+#define        _STRINGS_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+__BEGIN_DECLS
+#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112
+int     bcmp(const void *, const void *, size_t) __pure;       /* LEGACY */
+void    bcopy(const void *, void *, size_t);                   /* LEGACY */
+void    bzero(void *, size_t);                                 /* LEGACY */
+#endif
+#if __BSD_VISIBLE
+void    explicit_bzero(void *, size_t);
+#endif
+#if __XSI_VISIBLE
+int     ffs(int) __pure2;
+#endif
+#if __BSD_VISIBLE
+int     ffsl(long) __pure2;
+int     ffsll(long long) __pure2;
+int     fls(int) __pure2;
+int     flsl(long) __pure2;
+int     flsll(long long) __pure2;
+#endif
+#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112
+char   *index(const char *, int) __pure;                       /* LEGACY */
+char   *rindex(const char *, int) __pure;                      /* LEGACY */
+#endif
+int     strcasecmp(const char *, const char *) __pure;
+int     strncasecmp(const char *, const char *, size_t) __pure;
+
+#if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_)
+#include <xlocale/_strings.h>
+#endif
+__END_DECLS
+
+#endif /* _STRINGS_H_ */
diff --git a/include/stdlib/sys/_null.h b/include/stdlib/sys/_null.h
new file mode 100644 (file)
index 0000000..92706c6
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef NULL
+
+#if !defined(__cplusplus)
+#define        NULL    ((void *)0)
+#else
+#if __cplusplus >= 201103L
+#define        NULL    nullptr
+#elif defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4
+#define        NULL    __null
+#else
+#if defined(__LP64__)
+#define        NULL    (0L)
+#else
+#define        NULL    0
+#endif /* __LP64__ */
+#endif /* __GNUG__ */
+#endif /* !__cplusplus */
+
+#endif
diff --git a/include/stdlib/sys/_stdint.h b/include/stdlib/sys/_stdint.h
new file mode 100644 (file)
index 0000000..d0f9249
--- /dev/null
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2011 David E. O'Brien <obrien@FreeBSD.org>
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS__STDINT_H_
+#define _SYS__STDINT_H_
+
+#ifndef _INT8_T_DECLARED
+typedef        __int8_t                int8_t;
+#define        _INT8_T_DECLARED
+#endif
+
+#ifndef _INT16_T_DECLARED
+typedef        __int16_t               int16_t;
+#define        _INT16_T_DECLARED
+#endif
+
+#ifndef _INT32_T_DECLARED
+typedef        __int32_t               int32_t;
+#define        _INT32_T_DECLARED
+#endif
+
+#ifndef _INT64_T_DECLARED
+typedef        __int64_t               int64_t;
+#define        _INT64_T_DECLARED
+#endif
+
+#ifndef _UINT8_T_DECLARED
+typedef        __uint8_t               uint8_t;
+#define        _UINT8_T_DECLARED
+#endif
+
+#ifndef _UINT16_T_DECLARED
+typedef        __uint16_t              uint16_t;
+#define        _UINT16_T_DECLARED
+#endif
+
+#ifndef _UINT32_T_DECLARED
+typedef        __uint32_t              uint32_t;
+#define        _UINT32_T_DECLARED
+#endif
+
+#ifndef _UINT64_T_DECLARED
+typedef        __uint64_t              uint64_t;
+#define        _UINT64_T_DECLARED
+#endif
+
+#ifndef _INTPTR_T_DECLARED
+typedef        __intptr_t              intptr_t;
+#define        _INTPTR_T_DECLARED
+#endif
+#ifndef _UINTPTR_T_DECLARED
+typedef        __uintptr_t             uintptr_t;
+#define        _UINTPTR_T_DECLARED
+#endif
+
+#endif /* !_SYS__STDINT_H_ */
diff --git a/include/stdlib/sys/_timespec.h b/include/stdlib/sys/_timespec.h
new file mode 100644 (file)
index 0000000..d51559c
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)time.h      8.5 (Berkeley) 5/4/95
+ * from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp
+ *     $FreeBSD$
+ */
+
+#ifndef _SYS__TIMESPEC_H_
+#define        _SYS__TIMESPEC_H_
+
+#include <sys/_types.h>
+
+#ifndef _TIME_T_DECLARED
+typedef        __time_t        time_t;
+#define        _TIME_T_DECLARED
+#endif
+
+struct timespec {
+       time_t  tv_sec;         /* seconds */
+       long    tv_nsec;        /* and nanoseconds */
+};
+
+#endif /* !_SYS__TIMESPEC_H_ */
diff --git a/include/stdlib/sys/_types.h b/include/stdlib/sys/_types.h
new file mode 100644 (file)
index 0000000..c59afd3
--- /dev/null
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS__TYPES_H_
+#define _SYS__TYPES_H_
+
+#include <sys/cdefs.h>
+#include <machine/_types.h>
+
+/*
+ * Standard type definitions.
+ */
+typedef        __uint32_t      __blksize_t;    /* file block size */
+typedef        __int64_t       __blkcnt_t;     /* file block count */
+typedef        __int32_t       __clockid_t;    /* clock_gettime()... */
+typedef        __uint64_t      __cap_rights_t; /* capability rights */
+typedef        __uint32_t      __fflags_t;     /* file flags */
+typedef        __uint64_t      __fsblkcnt_t;
+typedef        __uint64_t      __fsfilcnt_t;
+typedef        __uint32_t      __gid_t;
+typedef        __int64_t       __id_t;         /* can hold a gid_t, pid_t, or uid_t */
+typedef        __uint32_t      __ino_t;        /* inode number */
+typedef        long            __key_t;        /* IPC key (for Sys V IPC) */
+typedef        __int32_t       __lwpid_t;      /* Thread ID (a.k.a. LWP) */
+typedef        __uint16_t      __mode_t;       /* permissions */
+typedef        int             __accmode_t;    /* access permissions */
+typedef        int             __nl_item;
+typedef        __uint16_t      __nlink_t;      /* link count */
+typedef        __int64_t       __off_t;        /* file offset */
+typedef        __int32_t       __pid_t;        /* process [group] */
+typedef        __int64_t       __rlim_t;       /* resource limit - intentionally */
+                                       /* signed, because of legacy code */
+                                       /* that uses -1 for RLIM_INFINITY */
+typedef        __uint8_t       __sa_family_t;
+typedef        __uint32_t      __socklen_t;
+typedef        long            __suseconds_t;  /* microseconds (signed) */
+typedef        struct __timer  *__timer_t;     /* timer_gettime()... */
+typedef        struct __mq     *__mqd_t;       /* mq_open()... */
+typedef        __uint32_t      __uid_t;
+typedef        unsigned int    __useconds_t;   /* microseconds (unsigned) */
+typedef        int             __cpuwhich_t;   /* which parameter for cpuset. */
+typedef        int             __cpulevel_t;   /* level parameter for cpuset. */
+typedef int            __cpusetid_t;   /* cpuset identifier. */
+
+/*
+ * Unusual type definitions.
+ */
+/*
+ * rune_t is declared to be an ``int'' instead of the more natural
+ * ``unsigned long'' or ``long''.  Two things are happening here.  It is not
+ * unsigned so that EOF (-1) can be naturally assigned to it and used.  Also,
+ * it looks like 10646 will be a 31 bit standard.  This means that if your
+ * ints cannot hold 32 bits, you will be in trouble.  The reason an int was
+ * chosen over a long is that the is*() and to*() routines take ints (says
+ * ANSI C), but they use __ct_rune_t instead of int.
+ *
+ * NOTE: rune_t is not covered by ANSI nor other standards, and should not
+ * be instantiated outside of lib/libc/locale.  Use wchar_t.  wchar_t and
+ * rune_t must be the same type.  Also, wint_t must be no narrower than
+ * wchar_t, and should be able to hold all members of the largest
+ * character set plus one extra value (WEOF), and must be at least 16 bits.
+ */
+typedef        int             __ct_rune_t;    /* arg type for ctype funcs */
+typedef        __ct_rune_t     __rune_t;       /* rune_t (see above) */
+typedef        __ct_rune_t     __wchar_t;      /* wchar_t (see above) */
+typedef        __ct_rune_t     __wint_t;       /* wint_t (see above) */
+
+typedef        __uint32_t      __dev_t;        /* device number */
+
+typedef        __uint32_t      __fixpt_t;      /* fixed point number */
+
+/*
+ * mbstate_t is an opaque object to keep conversion state during multibyte
+ * stream conversions.
+ */
+typedef union {
+       char            __mbstate8[128];
+       __int64_t       _mbstateL;      /* for alignment */
+} __mbstate_t;
+
+#endif /* !_SYS__TYPES_H_ */
diff --git a/include/stdlib/sys/cdefs.h b/include/stdlib/sys/cdefs.h
new file mode 100644 (file)
index 0000000..16fb151
--- /dev/null
@@ -0,0 +1,686 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)cdefs.h     8.8 (Berkeley) 1/9/95
+ * $FreeBSD$
+ */
+
+#ifndef        _SYS_CDEFS_H_
+#define        _SYS_CDEFS_H_
+
+#if defined(__cplusplus)
+#define        __BEGIN_DECLS   extern "C" {
+#define        __END_DECLS     }
+#else
+#define        __BEGIN_DECLS
+#define        __END_DECLS
+#endif
+
+/*
+ * This code has been put in place to help reduce the addition of
+ * compiler specific defines in FreeBSD code.  It helps to aid in
+ * having a compiler-agnostic source tree.
+ */
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+
+#if __GNUC__ >= 3 || defined(__INTEL_COMPILER)
+#define __GNUCLIKE_ASM 3
+#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS
+#else
+#define __GNUCLIKE_ASM 2
+#endif
+#define __GNUCLIKE___TYPEOF 1
+#define __GNUCLIKE___OFFSETOF 1
+#define __GNUCLIKE___SECTION 1
+
+#ifndef __INTEL_COMPILER
+# define __GNUCLIKE_CTOR_SECTION_HANDLING 1
+#endif
+
+#define __GNUCLIKE_BUILTIN_CONSTANT_P 1
+# if defined(__INTEL_COMPILER) && defined(__cplusplus) \
+    && __INTEL_COMPILER < 800
+#  undef __GNUCLIKE_BUILTIN_CONSTANT_P
+# endif
+
+#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3) && !defined(__INTEL_COMPILER)
+# define __GNUCLIKE_BUILTIN_VARARGS 1
+# define __GNUCLIKE_BUILTIN_STDARG 1
+# define __GNUCLIKE_BUILTIN_VAALIST 1
+#endif
+
+#if defined(__GNUC__)
+# define __GNUC_VA_LIST_COMPATIBILITY 1
+#endif
+
+#ifndef __INTEL_COMPILER
+# define __GNUCLIKE_BUILTIN_NEXT_ARG 1
+# define __GNUCLIKE_MATH_BUILTIN_RELOPS
+#endif
+
+#define __GNUCLIKE_BUILTIN_MEMCPY 1
+
+/* XXX: if __GNUC__ >= 2: not tested everywhere originally, where replaced */
+#define __CC_SUPPORTS_INLINE 1
+#define __CC_SUPPORTS___INLINE 1
+#define __CC_SUPPORTS___INLINE__ 1
+
+#define __CC_SUPPORTS___FUNC__ 1
+#define __CC_SUPPORTS_WARNING 1
+
+#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */
+
+#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1
+
+#endif /* __GNUC__ || __INTEL_COMPILER */
+
+/*
+ * Macro to test if we're using a specific version of gcc or later.
+ */
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+#define        __GNUC_PREREQ__(ma, mi) \
+       (__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi))
+#else
+#define        __GNUC_PREREQ__(ma, mi) 0
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky to use if it must work in non-ANSI
+ * mode -- there must be no spaces between its arguments, and for nested
+ * __CONCAT's, all the __CONCAT's must be at the left.  __CONCAT can also
+ * concatenate double-quoted strings produced by the __STRING macro, but
+ * this only works with ANSI C.
+ *
+ * __XSTRING is like __STRING, but it expands any macros in its argument
+ * first.  It is only available with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define        __P(protos)     protos          /* full-blown ANSI C */
+#define        __CONCAT1(x,y)  x ## y
+#define        __CONCAT(x,y)   __CONCAT1(x,y)
+#define        __STRING(x)     #x              /* stringify without expanding x */
+#define        __XSTRING(x)    __STRING(x)     /* expand x, then stringify */
+
+#define        __const         const           /* define reserved names to standard */
+#define        __signed        signed
+#define        __volatile      volatile
+#if defined(__cplusplus)
+#define        __inline        inline          /* convert to C++ keyword */
+#else
+#if !(defined(__CC_SUPPORTS___INLINE))
+#define        __inline                        /* delete GCC keyword */
+#endif /* ! __CC_SUPPORTS___INLINE */
+#endif /* !__cplusplus */
+
+#else  /* !(__STDC__ || __cplusplus) */
+#define        __P(protos)     ()              /* traditional C preprocessor */
+#define        __CONCAT(x,y)   x/**/y
+#define        __STRING(x)     "x"
+
+#if !defined(__CC_SUPPORTS___INLINE)
+#define        __const                         /* delete pseudo-ANSI C keywords */
+#define        __inline
+#define        __signed
+#define        __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef        NO_ANSI_KEYWORDS
+#define        const                           /* delete ANSI C keywords */
+#define        inline
+#define        signed
+#define        volatile
+#endif /* !NO_ANSI_KEYWORDS */
+#endif /* !__CC_SUPPORTS___INLINE */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * Compiler-dependent macros to help declare dead (non-returning) and
+ * pure (no side effects) functions, and unused variables.  They are
+ * null except for versions of gcc that are known to support the features
+ * properly (old versions of gcc-2 supported the dead and pure features
+ * in a different (wrong) way).  If we do not provide an implementation
+ * for a given compiler, let the compile fail if it is told to use
+ * a feature that we cannot live without.
+ */
+#ifdef lint
+#define        __dead2
+#define        __pure2
+#define        __unused
+#define        __packed
+#define        __aligned(x)
+#define        __section(x)
+#else
+#if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER)
+#define        __dead2
+#define        __pure2
+#define        __unused
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 && !defined(__INTEL_COMPILER)
+#define        __dead2         __attribute__((__noreturn__))
+#define        __pure2         __attribute__((__const__))
+#define        __unused
+/* XXX Find out what to do for __packed, __aligned and __section */
+#endif
+#if __GNUC_PREREQ__(2, 7)
+#define        __dead2         __attribute__((__noreturn__))
+#define        __pure2         __attribute__((__const__))
+#define        __unused        __attribute__((__unused__))
+#define        __used          __attribute__((__used__))
+#define        __packed        __attribute__((__packed__))
+#define        __aligned(x)    __attribute__((__aligned__(x)))
+#define        __section(x)    __attribute__((__section__(x)))
+#endif
+#if defined(__INTEL_COMPILER)
+#define __dead2                __attribute__((__noreturn__))
+#define __pure2                __attribute__((__const__))
+#define __unused       __attribute__((__unused__))
+#define __used         __attribute__((__used__))
+#define __packed       __attribute__((__packed__))
+#define __aligned(x)   __attribute__((__aligned__(x)))
+#define __section(x)   __attribute__((__section__(x)))
+#endif
+#endif
+
+#if !__GNUC_PREREQ__(2, 95)
+#define        __alignof(x)    __offsetof(struct { char __a; x __b; }, __b)
+#endif
+
+/*
+ * Keywords added in C11.
+ */
+#if defined(__cplusplus) && __cplusplus >= 201103L
+#define        _Alignas(e)             alignas(e)
+#define        _Alignof(e)             alignof(e)
+#define        _Noreturn               [[noreturn]]
+#define        _Static_assert(e, s)    static_assert(e, s)
+/* FIXME: change this to thread_local when clang in base supports it */
+#define        _Thread_local           __thread
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+/* Do nothing.  They are language keywords. */
+#else
+/* Not supported.  Implement them using our versions. */
+#define        _Alignas(x)             __aligned(x)
+#define        _Alignof(x)             __alignof(x)
+#define        _Noreturn               __dead2
+#define        _Thread_local           __thread
+#ifdef __COUNTER__
+#define        _Static_assert(x, y)    __Static_assert(x, __COUNTER__)
+#define        __Static_assert(x, y)   ___Static_assert(x, y)
+#define        ___Static_assert(x, y)  typedef char __assert_ ## y[(x) ? 1 : -1]
+#else
+#define        _Static_assert(x, y)    struct __hack
+#endif
+#endif
+
+/*
+ * Emulation of C11 _Generic().  Unlike the previously defined C11
+ * keywords, it is not possible to implement this using exactly the same
+ * syntax.  Therefore implement something similar under the name
+ * __generic().  Unlike _Generic(), this macro can only distinguish
+ * between a single type, so it requires nested invocations to
+ * distinguish multiple cases.
+ */
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#define        __generic(expr, t, yes, no)                                     \
+       _Generic(expr, t: yes, default: no)
+#elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus)
+#define        __generic(expr, t, yes, no)                                     \
+       __builtin_choose_expr(                                          \
+           __builtin_types_compatible_p(__typeof(expr), t), yes, no)
+#endif
+
+#if __GNUC_PREREQ__(2, 96)
+#define        __malloc_like   __attribute__((__malloc__))
+#define        __pure          __attribute__((__pure__))
+#else
+#define        __malloc_like
+#define        __pure
+#endif
+
+#if __GNUC_PREREQ__(3, 1) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
+#define        __always_inline __attribute__((__always_inline__))
+#else
+#define        __always_inline
+#endif
+
+#if __GNUC_PREREQ__(3, 1)
+#define        __noinline      __attribute__ ((__noinline__))
+#else
+#define        __noinline
+#endif
+
+#if __GNUC_PREREQ__(3, 3)
+#define __nonnull(x)   __attribute__((__nonnull__(x)))
+#else
+#define __nonnull(x)
+#endif
+
+#if __GNUC_PREREQ__(3, 4)
+#define        __fastcall      __attribute__((__fastcall__))
+#else
+#define        __fastcall
+#endif
+
+#if __GNUC_PREREQ__(4, 1)
+#define        __returns_twice __attribute__((__returns_twice__))
+#else
+#define        __returns_twice
+#endif
+
+/* XXX: should use `#if __STDC_VERSION__ < 199901'. */
+#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER)
+#define        __func__        NULL
+#endif
+
+#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901
+#define        __LONG_LONG_SUPPORTED
+#endif
+
+/* C++11 exposes a load of C99 stuff */
+#if defined(__cplusplus) && __cplusplus >= 201103L
+#define        __LONG_LONG_SUPPORTED
+#ifndef        __STDC_LIMIT_MACROS
+#define        __STDC_LIMIT_MACROS
+#endif
+#ifndef        __STDC_CONSTANT_MACROS
+#define        __STDC_CONSTANT_MACROS
+#endif
+#endif
+
+/*
+ * GCC 2.95 provides `__restrict' as an extension to C90 to support the
+ * C99-specific `restrict' type qualifier.  We happen to use `__restrict' as
+ * a way to define the `restrict' type qualifier without disturbing older
+ * software that is unaware of C99 keywords.
+ */
+#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95)
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901 || defined(lint)
+#define        __restrict
+#else
+#define        __restrict      restrict
+#endif
+#endif
+
+/*
+ * GNU C version 2.96 adds explicit branch prediction so that
+ * the CPU back-end can hint the processor and also so that
+ * code blocks can be reordered such that the predicted path
+ * sees a more linear flow, thus improving cache behavior, etc.
+ *
+ * The following two macros provide us with a way to utilize this
+ * compiler feature.  Use __predict_true() if you expect the expression
+ * to evaluate to true, and __predict_false() if you expect the
+ * expression to evaluate to false.
+ *
+ * A few notes about usage:
+ *
+ *     * Generally, __predict_false() error condition checks (unless
+ *       you have some _strong_ reason to do otherwise, in which case
+ *       document it), and/or __predict_true() `no-error' condition
+ *       checks, assuming you want to optimize for the no-error case.
+ *
+ *     * Other than that, if you don't know the likelihood of a test
+ *       succeeding from empirical or other `hard' evidence, don't
+ *       make predictions.
+ *
+ *     * These are meant to be used in places that are run `a lot'.
+ *       It is wasteful to make predictions in code that is run
+ *       seldomly (e.g. at subsystem initialization time) as the
+ *       basic block reordering that this affects can often generate
+ *       larger code.
+ */
+#if __GNUC_PREREQ__(2, 96)
+#define __predict_true(exp)     __builtin_expect((exp), 1)
+#define __predict_false(exp)    __builtin_expect((exp), 0)
+#else
+#define __predict_true(exp)     (exp)
+#define __predict_false(exp)    (exp)
+#endif
+
+#if __GNUC_PREREQ__(4, 2)
+#define        __hidden        __attribute__((__visibility__("hidden")))
+#define        __exported      __attribute__((__visibility__("default")))
+#else
+#define        __hidden
+#define        __exported
+#endif
+
+/*
+ * We define this here since <stddef.h>, <sys/queue.h>, and <sys/types.h>
+ * require it.
+ */
+#if __GNUC_PREREQ__(4, 1)
+#define __offsetof(type, field)         __builtin_offsetof(type, field)
+#else
+#ifndef __cplusplus
+#define        __offsetof(type, field) \
+       ((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field))
+#else
+#define __offsetof(type, field)                                        \
+  (__offsetof__ (reinterpret_cast <__size_t>                   \
+                 (&reinterpret_cast <const volatile char &>    \
+                  (static_cast<type *> (0)->field))))
+#endif
+#endif
+#define        __rangeof(type, start, end) \
+       (__offsetof(type, end) - __offsetof(type, start))
+
+/*
+ * Given the pointer x to the member m of the struct s, return
+ * a pointer to the containing structure.  When using GCC, we first
+ * assign pointer x to a local variable, to check that its type is
+ * compatible with member m.
+ */
+#if __GNUC_PREREQ__(3, 1)
+#define        __containerof(x, s, m) ({                                       \
+       const volatile __typeof(((s *)0)->m) *__x = (x);                \
+       __DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m));\
+})
+#else
+#define        __containerof(x, s, m)                                          \
+       __DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m))
+#endif
+
+/*
+ * Compiler-dependent macros to declare that functions take printf-like
+ * or scanf-like arguments.  They are null except for versions of gcc
+ * that are known to support the features properly (old versions of gcc-2
+ * didn't permit keeping the keywords out of the application namespace).
+ */
+#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER)
+#define        __printflike(fmtarg, firstvararg)
+#define        __scanflike(fmtarg, firstvararg)
+#define        __format_arg(fmtarg)
+#define        __strfmonlike(fmtarg, firstvararg)
+#define        __strftimelike(fmtarg, firstvararg)
+#else
+#define        __printflike(fmtarg, firstvararg) \
+           __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
+#define        __scanflike(fmtarg, firstvararg) \
+           __attribute__((__format__ (__scanf__, fmtarg, firstvararg)))
+#define        __format_arg(fmtarg)    __attribute__((__format_arg__ (fmtarg)))
+#define        __strfmonlike(fmtarg, firstvararg) \
+           __attribute__((__format__ (__strfmon__, fmtarg, firstvararg)))
+#define        __strftimelike(fmtarg, firstvararg) \
+           __attribute__((__format__ (__strftime__, fmtarg, firstvararg)))
+#endif
+
+/* Compiler-dependent macros that rely on FreeBSD-specific extensions. */
+#if __FreeBSD_cc_version >= 300001 && defined(__GNUC__) && !defined(__INTEL_COMPILER)
+#define        __printf0like(fmtarg, firstvararg) \
+           __attribute__((__format__ (__printf0__, fmtarg, firstvararg)))
+#else
+#define        __printf0like(fmtarg, firstvararg)
+#endif
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+#ifndef __INTEL_COMPILER
+#define        __strong_reference(sym,aliassym)        \
+       extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym)))
+#endif
+#ifdef __STDC__
+#define        __weak_reference(sym,alias)     \
+       __asm__(".weak " #alias);       \
+       __asm__(".equ "  #alias ", " #sym)
+#define        __warn_references(sym,msg)      \
+       __asm__(".section .gnu.warning." #sym); \
+       __asm__(".asciz \"" msg "\"");  \
+       __asm__(".previous")
+#define        __sym_compat(sym,impl,verid)    \
+       __asm__(".symver " #impl ", " #sym "@" #verid)
+#define        __sym_default(sym,impl,verid)   \
+       __asm__(".symver " #impl ", " #sym "@@" #verid)
+#else
+#define        __weak_reference(sym,alias)     \
+       __asm__(".weak alias");         \
+       __asm__(".equ alias, sym")
+#define        __warn_references(sym,msg)      \
+       __asm__(".section .gnu.warning.sym"); \
+       __asm__(".asciz \"msg\"");      \
+       __asm__(".previous")
+#define        __sym_compat(sym,impl,verid)    \
+       __asm__(".symver impl, sym@verid")
+#define        __sym_default(impl,sym,verid)   \
+       __asm__(".symver impl, sym@@verid")
+#endif /* __STDC__ */
+#endif /* __GNUC__ || __INTEL_COMPILER */
+
+#define        __GLOBL1(sym)   __asm__(".globl " #sym)
+#define        __GLOBL(sym)    __GLOBL1(sym)
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+#define        __IDSTRING(name,string) __asm__(".ident\t\"" string "\"")
+#else
+/*
+ * The following definition might not work well if used in header files,
+ * but it should be better than nothing.  If you want a "do nothing"
+ * version, then it should generate some harmless declaration, such as:
+ *    #define __IDSTRING(name,string)  struct __hack
+ */
+#define        __IDSTRING(name,string) static const char name[] __unused = string
+#endif
+
+/*
+ * Embed the rcs id of a source file in the resulting library.  Note that in
+ * more recent ELF binutils, we use .ident allowing the ID to be stripped.
+ * Usage:
+ *     __FBSDID("$FreeBSD$");
+ */
+#ifndef        __FBSDID
+#if !defined(lint) && !defined(STRIP_FBSDID)
+#define        __FBSDID(s)     __IDSTRING(__CONCAT(__rcsid_,__LINE__),s)
+#else
+#define        __FBSDID(s)     struct __hack
+#endif
+#endif
+
+#ifndef        __RCSID
+#ifndef        NO__RCSID
+#define        __RCSID(s)      __IDSTRING(__CONCAT(__rcsid_,__LINE__),s)
+#else
+#define        __RCSID(s)      struct __hack
+#endif
+#endif
+
+#ifndef        __RCSID_SOURCE
+#ifndef        NO__RCSID_SOURCE
+#define        __RCSID_SOURCE(s)       __IDSTRING(__CONCAT(__rcsid_source_,__LINE__),s)
+#else
+#define        __RCSID_SOURCE(s)       struct __hack
+#endif
+#endif
+
+#ifndef        __SCCSID
+#ifndef        NO__SCCSID
+#define        __SCCSID(s)     __IDSTRING(__CONCAT(__sccsid_,__LINE__),s)
+#else
+#define        __SCCSID(s)     struct __hack
+#endif
+#endif
+
+#ifndef        __COPYRIGHT
+#ifndef        NO__COPYRIGHT
+#define        __COPYRIGHT(s)  __IDSTRING(__CONCAT(__copyright_,__LINE__),s)
+#else
+#define        __COPYRIGHT(s)  struct __hack
+#endif
+#endif
+
+#ifndef        __DECONST
+#define        __DECONST(type, var)    ((type)(__uintptr_t)(const void *)(var))
+#endif
+
+#ifndef        __DEVOLATILE
+#define        __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var))
+#endif
+
+#ifndef        __DEQUALIFY
+#define        __DEQUALIFY(type, var)  ((type)(__uintptr_t)(const volatile void *)(var))
+#endif
+
+/*-
+ * The following definitions are an extension of the behavior originally
+ * implemented in <sys/_posix.h>, but with a different level of granularity.
+ * POSIX.1 requires that the macros we test be defined before any standard
+ * header file is included.
+ *
+ * Here's a quick run-down of the versions:
+ *  defined(_POSIX_SOURCE)             1003.1-1988
+ *  _POSIX_C_SOURCE == 1               1003.1-1990
+ *  _POSIX_C_SOURCE == 2               1003.2-1992 C Language Binding Option
+ *  _POSIX_C_SOURCE == 199309          1003.1b-1993
+ *  _POSIX_C_SOURCE == 199506          1003.1c-1995, 1003.1i-1995,
+ *                                     and the omnibus ISO/IEC 9945-1: 1996
+ *  _POSIX_C_SOURCE == 200112          1003.1-2001
+ *  _POSIX_C_SOURCE == 200809          1003.1-2008
+ *
+ * In addition, the X/Open Portability Guide, which is now the Single UNIX
+ * Specification, defines a feature-test macro which indicates the version of
+ * that specification, and which subsumes _POSIX_C_SOURCE.
+ *
+ * Our macros begin with two underscores to avoid namespace screwage.
+ */
+
+/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1. */
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1
+#undef _POSIX_C_SOURCE         /* Probably illegal, but beyond caring now. */
+#define        _POSIX_C_SOURCE         199009
+#endif
+
+/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2. */
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2
+#undef _POSIX_C_SOURCE
+#define        _POSIX_C_SOURCE         199209
+#endif
+
+/* Deal with various X/Open Portability Guides and Single UNIX Spec. */
+#ifdef _XOPEN_SOURCE
+#if _XOPEN_SOURCE - 0 >= 700
+#define        __XSI_VISIBLE           700
+#undef _POSIX_C_SOURCE
+#define        _POSIX_C_SOURCE         200809
+#elif _XOPEN_SOURCE - 0 >= 600
+#define        __XSI_VISIBLE           600
+#undef _POSIX_C_SOURCE
+#define        _POSIX_C_SOURCE         200112
+#elif _XOPEN_SOURCE - 0 >= 500
+#define        __XSI_VISIBLE           500
+#undef _POSIX_C_SOURCE
+#define        _POSIX_C_SOURCE         199506
+#endif
+#endif
+
+/*
+ * Deal with all versions of POSIX.  The ordering relative to the tests above is
+ * important.
+ */
+#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE)
+#define        _POSIX_C_SOURCE         198808
+#endif
+#ifdef _POSIX_C_SOURCE
+#if _POSIX_C_SOURCE >= 200809
+#define        __POSIX_VISIBLE         200809
+#define        __ISO_C_VISIBLE         1999
+#elif _POSIX_C_SOURCE >= 200112
+#define        __POSIX_VISIBLE         200112
+#define        __ISO_C_VISIBLE         1999
+#elif _POSIX_C_SOURCE >= 199506
+#define        __POSIX_VISIBLE         199506
+#define        __ISO_C_VISIBLE         1990
+#elif _POSIX_C_SOURCE >= 199309
+#define        __POSIX_VISIBLE         199309
+#define        __ISO_C_VISIBLE         1990
+#elif _POSIX_C_SOURCE >= 199209
+#define        __POSIX_VISIBLE         199209
+#define        __ISO_C_VISIBLE         1990
+#elif _POSIX_C_SOURCE >= 199009
+#define        __POSIX_VISIBLE         199009
+#define        __ISO_C_VISIBLE         1990
+#else
+#define        __POSIX_VISIBLE         198808
+#define        __ISO_C_VISIBLE         0
+#endif /* _POSIX_C_SOURCE */
+#else
+/*-
+ * Deal with _ANSI_SOURCE:
+ * If it is defined, and no other compilation environment is explicitly
+ * requested, then define our internal feature-test macros to zero.  This
+ * makes no difference to the preprocessor (undefined symbols in preprocessing
+ * expressions are defined to have value zero), but makes it more convenient for
+ * a test program to print out the values.
+ *
+ * If a program mistakenly defines _ANSI_SOURCE and some other macro such as
+ * _POSIX_C_SOURCE, we will assume that it wants the broader compilation
+ * environment (and in fact we will never get here).
+ */
+#if defined(_ANSI_SOURCE)      /* Hide almost everything. */
+#define        __POSIX_VISIBLE         0
+#define        __XSI_VISIBLE           0
+#define        __BSD_VISIBLE           0
+#define        __ISO_C_VISIBLE         1990
+#elif defined(_C99_SOURCE)     /* Localism to specify strict C99 env. */
+#define        __POSIX_VISIBLE         0
+#define        __XSI_VISIBLE           0
+#define        __BSD_VISIBLE           0
+#define        __ISO_C_VISIBLE         1999
+#else                          /* Default environment: show everything. */
+#define        __POSIX_VISIBLE         200809
+#define        __XSI_VISIBLE           700
+#define        __BSD_VISIBLE           1
+#define        __ISO_C_VISIBLE         1999
+#endif
+#endif
+
+#ifndef        __has_feature
+#define        __has_feature(x) 0
+#endif
+#ifndef        __has_include
+#define        __has_include(x) 0
+#endif
+#ifndef        __has_builtin
+#define        __has_builtin(x) 0
+#endif
+
+#if defined(__mips) || defined(__powerpc64__) || defined(__arm__)
+#define __NO_TLS 1
+#endif
+
+#endif /* !_SYS_CDEFS_H_ */
diff --git a/include/stdlib/sys/ctype.h b/include/stdlib/sys/ctype.h
new file mode 100644 (file)
index 0000000..f2758b7
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1982, 1988, 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Portions copyright (c) 2009-2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#ifndef _SYS_CTYPE_H_
+#define        _SYS_CTYPE_H_
+
+#define isspace(c)     ((c) == ' ' || ((c) >= '\t' && (c) <= '\r'))
+#define isascii(c)     (((c) & ~0x7f) == 0)
+#define isupper(c)     ((c) >= 'A' && (c) <= 'Z')
+#define islower(c)     ((c) >= 'a' && (c) <= 'z')
+#define isalpha(c)     (isupper(c) || islower(c))
+#define isdigit(c)     ((c) >= '0' && (c) <= '9')
+#define isxdigit(c)    (isdigit(c) \
+                         || ((c) >= 'A' && (c) <= 'F') \
+                         || ((c) >= 'a' && (c) <= 'f'))
+#define isprint(c)     ((c) >= ' ' && (c) <= '~')
+
+#define toupper(c)     ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
+#define tolower(c)     ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
+
+#endif /* !_SYS_CTYPE_H_ */
diff --git a/include/stdlib/sys/errno.h b/include/stdlib/sys/errno.h
new file mode 100644 (file)
index 0000000..f595514
--- /dev/null
@@ -0,0 +1,193 @@
+/*-
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)errno.h     8.5 (Berkeley) 1/21/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_ERRNO_H_
+#define _SYS_ERRNO_H_
+
+#ifndef _KERNEL
+#include <sys/cdefs.h>
+__BEGIN_DECLS
+int *  __error(void);
+__END_DECLS
+#define        errno           (* __error())
+#endif
+
+#define        EPERM           1               /* Operation not permitted */
+#define        ENOENT          2               /* No such file or directory */
+#define        ESRCH           3               /* No such process */
+#define        EINTR           4               /* Interrupted system call */
+#define        EIO             5               /* Input/output error */
+#define        ENXIO           6               /* Device not configured */
+#define        E2BIG           7               /* Argument list too long */
+#define        ENOEXEC         8               /* Exec format error */
+#define        EBADF           9               /* Bad file descriptor */
+#define        ECHILD          10              /* No child processes */
+#define        EDEADLK         11              /* Resource deadlock avoided */
+                                       /* 11 was EAGAIN */
+#define        ENOMEM          12              /* Cannot allocate memory */
+#define        EACCES          13              /* Permission denied */
+#define        EFAULT          14              /* Bad address */
+#ifndef _POSIX_SOURCE
+#define        ENOTBLK         15              /* Block device required */
+#endif
+#define        EBUSY           16              /* Device busy */
+#define        EEXIST          17              /* File exists */
+#define        EXDEV           18              /* Cross-device link */
+#define        ENODEV          19              /* Operation not supported by device */
+#define        ENOTDIR         20              /* Not a directory */
+#define        EISDIR          21              /* Is a directory */
+#define        EINVAL          22              /* Invalid argument */
+#define        ENFILE          23              /* Too many open files in system */
+#define        EMFILE          24              /* Too many open files */
+#define        ENOTTY          25              /* Inappropriate ioctl for device */
+#ifndef _POSIX_SOURCE
+#define        ETXTBSY         26              /* Text file busy */
+#endif
+#define        EFBIG           27              /* File too large */
+#define        ENOSPC          28              /* No space left on device */
+#define        ESPIPE          29              /* Illegal seek */
+#define        EROFS           30              /* Read-only filesystem */
+#define        EMLINK          31              /* Too many links */
+#define        EPIPE           32              /* Broken pipe */
+
+/* math software */
+#define        EDOM            33              /* Numerical argument out of domain */
+#define        ERANGE          34              /* Result too large */
+
+/* non-blocking and interrupt i/o */
+#define        EAGAIN          35              /* Resource temporarily unavailable */
+#ifndef _POSIX_SOURCE
+#define        EWOULDBLOCK     EAGAIN          /* Operation would block */
+#define        EINPROGRESS     36              /* Operation now in progress */
+#define        EALREADY        37              /* Operation already in progress */
+
+/* ipc/network software -- argument errors */
+#define        ENOTSOCK        38              /* Socket operation on non-socket */
+#define        EDESTADDRREQ    39              /* Destination address required */
+#define        EMSGSIZE        40              /* Message too long */
+#define        EPROTOTYPE      41              /* Protocol wrong type for socket */
+#define        ENOPROTOOPT     42              /* Protocol not available */
+#define        EPROTONOSUPPORT 43              /* Protocol not supported */
+#define        ESOCKTNOSUPPORT 44              /* Socket type not supported */
+#define        EOPNOTSUPP      45              /* Operation not supported */
+#define        ENOTSUP         EOPNOTSUPP      /* Operation not supported */
+#define        EPFNOSUPPORT    46              /* Protocol family not supported */
+#define        EAFNOSUPPORT    47              /* Address family not supported by protocol family */
+#define        EADDRINUSE      48              /* Address already in use */
+#define        EADDRNOTAVAIL   49              /* Can't assign requested address */
+
+/* ipc/network software -- operational errors */
+#define        ENETDOWN        50              /* Network is down */
+#define        ENETUNREACH     51              /* Network is unreachable */
+#define        ENETRESET       52              /* Network dropped connection on reset */
+#define        ECONNABORTED    53              /* Software caused connection abort */
+#define        ECONNRESET      54              /* Connection reset by peer */
+#define        ENOBUFS         55              /* No buffer space available */
+#define        EISCONN         56              /* Socket is already connected */
+#define        ENOTCONN        57              /* Socket is not connected */
+#define        ESHUTDOWN       58              /* Can't send after socket shutdown */
+#define        ETOOMANYREFS    59              /* Too many references: can't splice */
+#define        ETIMEDOUT       60              /* Operation timed out */
+#define        ECONNREFUSED    61              /* Connection refused */
+
+#define        ELOOP           62              /* Too many levels of symbolic links */
+#endif /* _POSIX_SOURCE */
+#define        ENAMETOOLONG    63              /* File name too long */
+
+/* should be rearranged */
+#ifndef _POSIX_SOURCE
+#define        EHOSTDOWN       64              /* Host is down */
+#define        EHOSTUNREACH    65              /* No route to host */
+#endif /* _POSIX_SOURCE */
+#define        ENOTEMPTY       66              /* Directory not empty */
+
+/* quotas & mush */
+#ifndef _POSIX_SOURCE
+#define        EPROCLIM        67              /* Too many processes */
+#define        EUSERS          68              /* Too many users */
+#define        EDQUOT          69              /* Disc quota exceeded */
+
+/* Network File System */
+#define        ESTALE          70              /* Stale NFS file handle */
+#define        EREMOTE         71              /* Too many levels of remote in path */
+#define        EBADRPC         72              /* RPC struct is bad */
+#define        ERPCMISMATCH    73              /* RPC version wrong */
+#define        EPROGUNAVAIL    74              /* RPC prog. not avail */
+#define        EPROGMISMATCH   75              /* Program version wrong */
+#define        EPROCUNAVAIL    76              /* Bad procedure for program */
+#endif /* _POSIX_SOURCE */
+
+#define        ENOLCK          77              /* No locks available */
+#define        ENOSYS          78              /* Function not implemented */
+
+#ifndef _POSIX_SOURCE
+#define        EFTYPE          79              /* Inappropriate file type or format */
+#define        EAUTH           80              /* Authentication error */
+#define        ENEEDAUTH       81              /* Need authenticator */
+#define        EIDRM           82              /* Identifier removed */
+#define        ENOMSG          83              /* No message of desired type */
+#define        EOVERFLOW       84              /* Value too large to be stored in data type */
+#define        ECANCELED       85              /* Operation canceled */
+#define        EILSEQ          86              /* Illegal byte sequence */
+#define        ENOATTR         87              /* Attribute not found */
+
+#define        EDOOFUS         88              /* Programming error */
+#endif /* _POSIX_SOURCE */
+
+#define        EBADMSG         89              /* Bad message */
+#define        EMULTIHOP       90              /* Multihop attempted */
+#define        ENOLINK         91              /* Link has been severed */
+#define        EPROTO          92              /* Protocol error */
+
+#ifndef _POSIX_SOURCE
+#define        ENOTCAPABLE     93              /* Capabilities insufficient */
+#define        ECAPMODE        94              /* Not permitted in capability mode */
+#endif /* _POSIX_SOURCE */
+
+#ifndef _POSIX_SOURCE
+#define        ELAST           94              /* Must be equal largest errno */
+#endif /* _POSIX_SOURCE */
+
+#ifdef _KERNEL
+/* pseudo-errors returned inside kernel to modify return to process */
+#define        ERESTART        (-1)            /* restart syscall */
+#define        EJUSTRETURN     (-2)            /* don't modify regs, just return */
+#define        ENOIOCTL        (-3)            /* ioctl not handled by this layer */
+#define        EDIRIOCTL       (-4)            /* do direct ioctl in GEOM */
+#endif
+
+#endif
diff --git a/include/stdlib/sys/limits.h b/include/stdlib/sys/limits.h
new file mode 100644 (file)
index 0000000..c56a337
--- /dev/null
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_LIMITS_H_
+#define        _SYS_LIMITS_H_
+
+#include <sys/cdefs.h>
+#include <machine/_limits.h>
+
+#define        CHAR_BIT        __CHAR_BIT      /* number of bits in a char */
+
+#define        SCHAR_MAX       __SCHAR_MAX     /* max value for a signed char */
+#define        SCHAR_MIN       __SCHAR_MIN     /* min value for a signed char */
+
+#define        UCHAR_MAX       __UCHAR_MAX     /* max value for an unsigned char */
+
+#ifdef __CHAR_UNSIGNED__
+#define        CHAR_MAX        UCHAR_MAX       /* max value for a char */
+#define        CHAR_MIN        0               /* min value for a char */
+#else
+#define        CHAR_MAX        SCHAR_MAX
+#define        CHAR_MIN        SCHAR_MIN
+#endif
+
+#define        USHRT_MAX       __USHRT_MAX     /* max value for an unsigned short */
+#define        SHRT_MAX        __SHRT_MAX      /* max value for a short */
+#define        SHRT_MIN        __SHRT_MIN      /* min value for a short */
+
+#define        UINT_MAX        __UINT_MAX      /* max value for an unsigned int */
+#define        INT_MAX         __INT_MAX       /* max value for an int */
+#define        INT_MIN         __INT_MIN       /* min value for an int */
+
+#define        ULONG_MAX       __ULONG_MAX     /* max for an unsigned long */
+#define        LONG_MAX        __LONG_MAX      /* max for a long */
+#define        LONG_MIN        __LONG_MIN      /* min for a long */
+
+#ifdef __LONG_LONG_SUPPORTED
+#define        ULLONG_MAX      __ULLONG_MAX    /* max for an unsigned long long */
+#define        LLONG_MAX       __LLONG_MAX     /* max for a long long */
+#define        LLONG_MIN       __LLONG_MIN     /* min for a long long */
+#endif
+
+#if __POSIX_VISIBLE || __XSI_VISIBLE
+#define        SSIZE_MAX       __SSIZE_MAX     /* max value for an ssize_t */
+#endif
+
+#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
+#define        SIZE_T_MAX      __SIZE_T_MAX    /* max value for a size_t */
+
+#define        OFF_MAX         __OFF_MAX       /* max value for an off_t */
+#define        OFF_MIN         __OFF_MIN       /* min value for an off_t */
+#endif
+
+#if __BSD_VISIBLE
+#define        GID_MAX         UINT_MAX        /* max value for a gid_t */
+#define        UID_MAX         UINT_MAX        /* max value for a uid_t */
+
+#define        UQUAD_MAX       (__UQUAD_MAX)   /* max value for a uquad_t */
+#define        QUAD_MAX        (__QUAD_MAX)    /* max value for a quad_t */
+#define        QUAD_MIN        (__QUAD_MIN)    /* min value for a quad_t */
+#endif
+
+#if __XSI_VISIBLE || __POSIX_VISIBLE >= 200809
+#define        LONG_BIT        __LONG_BIT
+#define        WORD_BIT        __WORD_BIT
+#endif
+
+#if __POSIX_VISIBLE
+#define        MQ_PRIO_MAX     64
+#endif
+
+#endif /* !_SYS_LIMITS_H_ */
diff --git a/include/stdlib/sys/stdarg.h b/include/stdlib/sys/stdarg.h
new file mode 100644 (file)
index 0000000..c315dfc
--- /dev/null
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2002 David E. O'Brien.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_STDARG_H_
+#define        _MACHINE_STDARG_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#ifndef _VA_LIST_DECLARED
+#define        _VA_LIST_DECLARED
+typedef        __va_list       va_list;
+#endif
+
+#ifdef __GNUCLIKE_BUILTIN_STDARG
+
+#define        va_start(ap, last) \
+       __builtin_va_start((ap), (last))
+
+#define        va_arg(ap, type) \
+       __builtin_va_arg((ap), type)
+
+#define        __va_copy(dest, src) \
+       __builtin_va_copy((dest), (src))
+
+#if __ISO_C_VISIBLE >= 1999
+#define        va_copy(dest, src) \
+       __va_copy(dest, src)
+#endif
+
+#define        va_end(ap) \
+       __builtin_va_end(ap)
+
+#elif defined(lint)
+/* Provide a fake implementation for lint's benefit */
+#define        __va_size(type) \
+       (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long))
+#define        va_start(ap, last) \
+       ((ap) = (va_list)&(last) + __va_size(last))
+#define        va_arg(ap, type) \
+       (*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
+#define        va_end(ap)
+
+#else
+#error this file needs to be ported to your compiler
+#endif
+
+#endif /* !_MACHINE_STDARG_H_ */
diff --git a/include/stdlib/sys/stdint.h b/include/stdlib/sys/stdint.h
new file mode 100644 (file)
index 0000000..aa5ac81
--- /dev/null
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_STDINT_H_
+#define _SYS_STDINT_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#include <machine/_stdint.h>
+#include <sys/_stdint.h>
+
+typedef        __int_least8_t          int_least8_t;
+typedef        __int_least16_t         int_least16_t;
+typedef        __int_least32_t         int_least32_t;
+typedef        __int_least64_t         int_least64_t;
+
+typedef        __uint_least8_t         uint_least8_t;
+typedef        __uint_least16_t        uint_least16_t;
+typedef        __uint_least32_t        uint_least32_t;
+typedef        __uint_least64_t        uint_least64_t;
+
+typedef        __int_fast8_t           int_fast8_t;
+typedef        __int_fast16_t          int_fast16_t;
+typedef        __int_fast32_t          int_fast32_t;
+typedef        __int_fast64_t          int_fast64_t;
+
+typedef        __uint_fast8_t          uint_fast8_t;
+typedef        __uint_fast16_t         uint_fast16_t;
+typedef        __uint_fast32_t         uint_fast32_t;
+typedef        __uint_fast64_t         uint_fast64_t;
+
+#ifndef _INTMAX_T_DECLARED
+typedef        __intmax_t              intmax_t;
+#define        _INTMAX_T_DECLARED
+#endif
+#ifndef _UINTMAX_T_DECLARED
+typedef        __uintmax_t             uintmax_t;
+#define        _UINTMAX_T_DECLARED
+#endif
+
+/* GNU and Darwin define this and people seem to think it's portable */
+#if defined(UINTPTR_MAX) && defined(UINT64_MAX) && (UINTPTR_MAX == UINT64_MAX)
+#define        __WORDSIZE              64
+#else
+#define        __WORDSIZE              32
+#endif
+
+#endif /* !_SYS_STDINT_H_ */
diff --git a/include/stdlib/sys/timespec.h b/include/stdlib/sys/timespec.h
new file mode 100644 (file)
index 0000000..2505cef
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)time.h      8.5 (Berkeley) 5/4/95
+ * from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp
+ *     $FreeBSD$
+ */
+
+#ifndef _SYS_TIMESPEC_H_
+#define _SYS_TIMESPEC_H_
+
+#include <sys/cdefs.h>
+#include <sys/_timespec.h>
+
+#if __BSD_VISIBLE
+#define        TIMEVAL_TO_TIMESPEC(tv, ts)                                     \
+       do {                                                            \
+               (ts)->tv_sec = (tv)->tv_sec;                            \
+               (ts)->tv_nsec = (tv)->tv_usec * 1000;                   \
+       } while (0)
+#define        TIMESPEC_TO_TIMEVAL(tv, ts)                                     \
+       do {                                                            \
+               (tv)->tv_sec = (ts)->tv_sec;                            \
+               (tv)->tv_usec = (ts)->tv_nsec / 1000;                   \
+       } while (0)
+
+#endif /* __BSD_VISIBLE */
+
+/*
+ * Structure defined by POSIX.1b to be like a itimerval, but with
+ * timespecs. Used in the timer_*() system calls.
+ */
+struct itimerspec {
+       struct timespec  it_interval;
+       struct timespec  it_value;
+};
+
+#endif /* _SYS_TIMESPEC_H_ */
diff --git a/include/stdlib/sys/types.h b/include/stdlib/sys/types.h
new file mode 100644 (file)
index 0000000..ae2ea33
--- /dev/null
@@ -0,0 +1,245 @@
+/*-
+ * Copyright (c) 1982, 1986, 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)types.h     8.6 (Berkeley) 2/19/95
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_TYPES_H_
+#define        _SYS_TYPES_H_
+
+#include <sys/cdefs.h>
+
+/* Machine type dependent parameters. */
+#include <sys/_types.h>
+
+#if __BSD_VISIBLE
+typedef        unsigned char   u_char;
+typedef        unsigned short  u_short;
+typedef        unsigned int    u_int;
+typedef        unsigned long   u_long;
+#ifndef _KERNEL
+typedef        unsigned short  ushort;         /* Sys V compatibility */
+typedef        unsigned int    uint;           /* Sys V compatibility */
+#endif
+#endif
+
+/*
+ * XXX POSIX sized integrals that should appear only in <sys/stdint.h>.
+ */
+#include <sys/_stdint.h>
+
+typedef __uint8_t      u_int8_t;       /* unsigned integrals (deprecated) */
+typedef __uint16_t     u_int16_t;
+typedef __uint32_t     u_int32_t;
+typedef __uint64_t     u_int64_t;
+
+typedef        __uint64_t      u_quad_t;       /* quads (deprecated) */
+typedef        __int64_t       quad_t;
+typedef        quad_t          *qaddr_t;
+
+typedef        char            *caddr_t;       /* core address */
+typedef        const char      *c_caddr_t;     /* core address, pointer to const */
+
+#ifndef _BLKSIZE_T_DECLARED
+typedef        __blksize_t     blksize_t;
+#define        _BLKSIZE_T_DECLARED
+#endif
+
+typedef        __cpuwhich_t    cpuwhich_t;
+typedef        __cpulevel_t    cpulevel_t;
+typedef        __cpusetid_t    cpusetid_t;
+
+#ifndef _BLKCNT_T_DECLARED
+typedef        __blkcnt_t      blkcnt_t;
+#define        _BLKCNT_T_DECLARED
+#endif
+
+#ifndef _CLOCK_T_DECLARED
+typedef        __clock_t       clock_t;
+#define        _CLOCK_T_DECLARED
+#endif
+
+#ifndef _CLOCKID_T_DECLARED
+typedef        __clockid_t     clockid_t;
+#define        _CLOCKID_T_DECLARED
+#endif
+
+typedef        __critical_t    critical_t;     /* Critical section value */
+typedef        __int64_t       daddr_t;        /* disk address */
+
+#ifndef _DEV_T_DECLARED
+typedef        __dev_t         dev_t;          /* device number or struct cdev */
+#define        _DEV_T_DECLARED
+#endif
+
+#ifndef _FFLAGS_T_DECLARED
+typedef        __fflags_t      fflags_t;       /* file flags */
+#define        _FFLAGS_T_DECLARED
+#endif
+
+typedef        __fixpt_t       fixpt_t;        /* fixed point number */
+
+#ifndef _FSBLKCNT_T_DECLARED           /* for statvfs() */
+typedef        __fsblkcnt_t    fsblkcnt_t;
+typedef        __fsfilcnt_t    fsfilcnt_t;
+#define        _FSBLKCNT_T_DECLARED
+#endif
+
+#ifndef _GID_T_DECLARED
+typedef        __gid_t         gid_t;          /* group id */
+#define        _GID_T_DECLARED
+#endif
+
+#ifndef _IN_ADDR_T_DECLARED
+typedef        __uint32_t      in_addr_t;      /* base type for internet address */
+#define        _IN_ADDR_T_DECLARED
+#endif
+
+#ifndef _IN_PORT_T_DECLARED
+typedef        __uint16_t      in_port_t;
+#define        _IN_PORT_T_DECLARED
+#endif
+
+#ifndef _ID_T_DECLARED
+typedef        __id_t          id_t;           /* can hold a uid_t or pid_t */
+#define        _ID_T_DECLARED
+#endif
+
+#ifndef _INO_T_DECLARED
+typedef        __ino_t         ino_t;          /* inode number */
+#define        _INO_T_DECLARED
+#endif
+
+#ifndef _KEY_T_DECLARED
+typedef        __key_t         key_t;          /* IPC key (for Sys V IPC) */
+#define        _KEY_T_DECLARED
+#endif
+
+#ifndef _LWPID_T_DECLARED
+typedef        __lwpid_t       lwpid_t;        /* Thread ID (a.k.a. LWP) */
+#define        _LWPID_T_DECLARED
+#endif
+
+#ifndef _MODE_T_DECLARED
+typedef        __mode_t        mode_t;         /* permissions */
+#define        _MODE_T_DECLARED
+#endif
+
+#ifndef _ACCMODE_T_DECLARED
+typedef        __accmode_t     accmode_t;      /* access permissions */
+#define        _ACCMODE_T_DECLARED
+#endif
+
+#ifndef _NLINK_T_DECLARED
+typedef        __nlink_t       nlink_t;        /* link count */
+#define        _NLINK_T_DECLARED
+#endif
+
+#ifndef _OFF_T_DECLARED
+typedef        __off_t         off_t;          /* file offset */
+#define        _OFF_T_DECLARED
+#endif
+
+#ifndef _PID_T_DECLARED
+typedef        __pid_t         pid_t;          /* process id */
+#define        _PID_T_DECLARED
+#endif
+
+typedef        __register_t    register_t;
+
+#ifndef _RLIM_T_DECLARED
+typedef        __rlim_t        rlim_t;         /* resource limit */
+#define        _RLIM_T_DECLARED
+#endif
+
+typedef        __int64_t       sbintime_t;
+
+typedef        __segsz_t       segsz_t;        /* segment size (in pages) */
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+#ifndef _SSIZE_T_DECLARED
+typedef        __ssize_t       ssize_t;
+#define        _SSIZE_T_DECLARED
+#endif
+
+#ifndef _SUSECONDS_T_DECLARED
+typedef        __suseconds_t   suseconds_t;    /* microseconds (signed) */
+#define        _SUSECONDS_T_DECLARED
+#endif
+
+#ifndef _TIME_T_DECLARED
+typedef        __time_t        time_t;
+#define        _TIME_T_DECLARED
+#endif
+
+#ifndef _TIMER_T_DECLARED
+typedef        __timer_t       timer_t;
+#define        _TIMER_T_DECLARED
+#endif
+
+#ifndef _MQD_T_DECLARED
+typedef        __mqd_t mqd_t;
+#define        _MQD_T_DECLARED
+#endif
+
+typedef        __u_register_t  u_register_t;
+
+#ifndef _UID_T_DECLARED
+typedef        __uid_t         uid_t;          /* user id */
+#define        _UID_T_DECLARED
+#endif
+
+#ifndef _USECONDS_T_DECLARED
+typedef        __useconds_t    useconds_t;     /* microseconds (unsigned) */
+#define        _USECONDS_T_DECLARED
+#endif
+
+#ifndef _CAP_RIGHTS_T_DECLARED
+#define        _CAP_RIGHTS_T_DECLARED
+struct cap_rights;
+
+typedef        struct cap_rights       cap_rights_t;
+#endif
+
+typedef        __vm_offset_t   vm_offset_t;
+typedef        __vm_ooffset_t  vm_ooffset_t;
+typedef        __vm_paddr_t    vm_paddr_t;
+typedef        __vm_pindex_t   vm_pindex_t;
+typedef        __vm_size_t     vm_size_t;
+
+#endif /* !_SYS_TYPES_H_ */
diff --git a/include/stdlib/sys/uuid.h b/include/stdlib/sys/uuid.h
new file mode 100644 (file)
index 0000000..5c4767b
--- /dev/null
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Portions copyright (c) 2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#ifndef _SYS_UUID_H_
+#define _SYS_UUID_H_
+
+#include <sys/cdefs.h>
+
+/* Length of a node address (an IEEE 802 address). */
+#define        _UUID_NODE_LEN          6
+
+/*
+ * See also:
+ *      http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
+ *      http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
+ *
+ * A DCE 1.1 compatible source representation of UUIDs.
+ */
+struct uuid {
+       uint32_t        time_low;
+       uint16_t        time_mid;
+       uint16_t        time_hi_and_version;
+       uint8_t         clock_seq_hi_and_reserved;
+       uint8_t         clock_seq_low;
+       uint8_t         node[_UUID_NODE_LEN];
+};
+
+/* XXX namespace pollution? */
+typedef struct uuid uuid_t;
+
+#endif /* _SYS_UUID_H_ */
diff --git a/include/stdlib/time.h b/include/stdlib/time.h
new file mode 100644 (file)
index 0000000..08200cf
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)time.h      8.3 (Berkeley) 1/21/94
+ */
+
+/*
+ * $FreeBSD$
+ */
+
+#ifndef _TIME_H_
+#define        _TIME_H_
+
+#include <sys/cdefs.h>
+#include <sys/_null.h>
+#include <sys/_types.h>
+
+#if __POSIX_VISIBLE > 0 && __POSIX_VISIBLE < 200112 || __BSD_VISIBLE
+/*
+ * Frequency of the clock ticks reported by times().  Deprecated - use
+ * sysconf(_SC_CLK_TCK) instead.  (Removed in 1003.1-2001.)
+ */
+#define        CLK_TCK         128
+#endif
+
+/* Frequency of the clock ticks reported by clock().  */
+#define        CLOCKS_PER_SEC  128
+
+#ifndef _CLOCK_T_DECLARED
+typedef        __clock_t       clock_t;
+#define        _CLOCK_T_DECLARED
+#endif
+
+#ifndef _TIME_T_DECLARED
+typedef        __time_t        time_t;
+#define        _TIME_T_DECLARED
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+#if __POSIX_VISIBLE >= 199309
+/*
+ * New in POSIX 1003.1b-1993.
+ */
+#ifndef _CLOCKID_T_DECLARED
+typedef        __clockid_t     clockid_t;
+#define        _CLOCKID_T_DECLARED
+#endif
+
+#ifndef _TIMER_T_DECLARED
+typedef        __timer_t       timer_t;
+#define        _TIMER_T_DECLARED
+#endif
+
+#include <sys/timespec.h>
+#endif /* __POSIX_VISIBLE >= 199309 */
+
+#if __POSIX_VISIBLE >= 200112
+#ifndef _PID_T_DECLARED
+typedef        __pid_t         pid_t;
+#define        _PID_T_DECLARED
+#endif
+#endif
+
+/* These macros are also in sys/time.h. */
+#if !defined(CLOCK_REALTIME) && __POSIX_VISIBLE >= 200112
+#define CLOCK_REALTIME 0
+#ifdef __BSD_VISIBLE
+#define CLOCK_VIRTUAL  1
+#define CLOCK_PROF     2
+#endif
+#define CLOCK_MONOTONIC        4
+#define CLOCK_UPTIME   5               /* FreeBSD-specific. */
+#define CLOCK_UPTIME_PRECISE   7       /* FreeBSD-specific. */
+#define CLOCK_UPTIME_FAST      8       /* FreeBSD-specific. */
+#define CLOCK_REALTIME_PRECISE 9       /* FreeBSD-specific. */
+#define CLOCK_REALTIME_FAST    10      /* FreeBSD-specific. */
+#define CLOCK_MONOTONIC_PRECISE        11      /* FreeBSD-specific. */
+#define CLOCK_MONOTONIC_FAST   12      /* FreeBSD-specific. */
+#define CLOCK_SECOND   13              /* FreeBSD-specific. */
+#define CLOCK_THREAD_CPUTIME_ID        14
+#define        CLOCK_PROCESS_CPUTIME_ID        15
+#endif /* !defined(CLOCK_REALTIME) && __POSIX_VISIBLE >= 200112 */
+
+#if !defined(TIMER_ABSTIME) && __POSIX_VISIBLE >= 200112
+#if __BSD_VISIBLE
+#define TIMER_RELTIME  0x0     /* relative timer */
+#endif
+#define TIMER_ABSTIME  0x1     /* absolute timer */
+#endif /* !defined(TIMER_ABSTIME) && __POSIX_VISIBLE >= 200112 */
+
+struct tm {
+       int     tm_sec;         /* seconds after the minute [0-60] */
+       int     tm_min;         /* minutes after the hour [0-59] */
+       int     tm_hour;        /* hours since midnight [0-23] */
+       int     tm_mday;        /* day of the month [1-31] */
+       int     tm_mon;         /* months since January [0-11] */
+       int     tm_year;        /* years since 1900 */
+       int     tm_wday;        /* days since Sunday [0-6] */
+       int     tm_yday;        /* days since January 1 [0-365] */
+       int     tm_isdst;       /* Daylight Savings Time flag */
+       long    tm_gmtoff;      /* offset from UTC in seconds */
+       char    *tm_zone;       /* timezone abbreviation */
+};
+
+#if __POSIX_VISIBLE
+extern char *tzname[];
+#endif
+
+__BEGIN_DECLS
+char *asctime(const struct tm *);
+clock_t clock(void);
+char *ctime(const time_t *);
+double difftime(time_t, time_t);
+/* XXX missing: getdate() */
+struct tm *gmtime(const time_t *);
+struct tm *localtime(const time_t *);
+time_t mktime(struct tm *);
+size_t strftime(char *__restrict, size_t, const char *__restrict,
+    const struct tm *__restrict);
+time_t time(time_t *);
+#if __POSIX_VISIBLE >= 200112
+struct sigevent;
+int timer_create(clockid_t, struct sigevent *__restrict, timer_t *__restrict);
+int timer_delete(timer_t);
+int timer_gettime(timer_t, struct itimerspec *);
+int timer_getoverrun(timer_t);
+int timer_settime(timer_t, int, const struct itimerspec *__restrict,
+       struct itimerspec *__restrict);
+#endif
+#if __POSIX_VISIBLE
+void tzset(void);
+#endif
+
+#if __POSIX_VISIBLE >= 199309
+int clock_getres(clockid_t, struct timespec *);
+int clock_gettime(clockid_t, struct timespec *);
+int clock_settime(clockid_t, const struct timespec *);
+/* XXX missing: clock_nanosleep() */
+int nanosleep(const struct timespec *, struct timespec *);
+#endif /* __POSIX_VISIBLE >= 199309 */
+
+#if __POSIX_VISIBLE >= 200112
+int clock_getcpuclockid(pid_t, clockid_t *);
+#endif
+
+#if __POSIX_VISIBLE >= 199506
+char *asctime_r(const struct tm *, char *);
+char *ctime_r(const time_t *, char *);
+struct tm *gmtime_r(const time_t *, struct tm *);
+struct tm *localtime_r(const time_t *, struct tm *);
+#endif
+
+#if __XSI_VISIBLE
+char *strptime(const char *__restrict, const char *__restrict,
+    struct tm *__restrict);
+#endif
+
+#if __BSD_VISIBLE
+char *timezone(int, int);      /* XXX XSI conflict */
+void tzsetwall(void);
+time_t timelocal(struct tm * const);
+time_t timegm(struct tm * const);
+#endif /* __BSD_VISIBLE */
+
+#if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_)
+#include <xlocale/_time.h>
+#endif
+__END_DECLS
+
+#endif /* !_TIME_H_ */
diff --git a/include/stdlib/xlocale/_strings.h b/include/stdlib/xlocale/_strings.h
new file mode 100644 (file)
index 0000000..da1cff3
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2011, 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+/*
+ * This file is included from both strings.h and xlocale.h.  We need to expose
+ * the declarations unconditionally if we are included from xlocale.h, but only
+ * if we are in POSIX2008 mode if included from string.h.
+ */
+
+#ifndef _XLOCALE_STRINGS1_H
+#define _XLOCALE_STRINGS1_H
+
+/*
+ * POSIX2008 functions
+ */
+int     strcasecmp_l(const char *, const char *, locale_t);
+int     strncasecmp_l(const char *, const char *, size_t, locale_t);
+#endif /* _XLOCALE_STRINGS1_H */
diff --git a/include/stdlib/xlocale/_time.h b/include/stdlib/xlocale/_time.h
new file mode 100644 (file)
index 0000000..6da49a4
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2011, 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by David Chisnall under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+/*
+ * This file is included from both locale.h and xlocale.h.  We need to expose
+ * the declarations unconditionally if we are included from xlocale.h, but only
+ * if we are in POSIX2008 mode if included from locale.h.
+ */
+#ifndef _XLOCALE_LOCALE1_H
+#define _XLOCALE_LOCALE1_H
+
+size_t  strftime_l(char *__restrict, size_t, const char *__restrict,
+           const struct tm *__restrict, locale_t) __strftimelike(3, 0);
+
+#endif /* _XLOCALE_LOCALE1_H */
+
+#ifdef _XLOCALE_H_
+#ifndef _XLOCALE_LOCALE2_H
+#define _XLOCALE_LOCALE2_H
+
+char   *strptime_l(const char *__restrict, const char *__restrict,
+               struct tm *__restrict, locale_t);
+
+#endif /* _XLOCALE_LOCALE2_H */
+#endif /* _XLOCALE_H_ */
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
new file mode 100644 (file)
index 0000000..dc60102
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+       .globl  flush_dcache_range
+       .globl  inv_dcache_range
+       .globl  dcsw_op_louis
+       .globl  dcsw_op_all
+       .globl  dcsw_op_level1
+       .globl  dcsw_op_level2
+       .globl  dcsw_op_level3
+
+       /* ------------------------------------------
+        * Clean+Invalidate from base address till
+        * size. 'x0' = addr, 'x1' = size
+        * ------------------------------------------
+        */
+func flush_dcache_range
+       dcache_line_size x2, x3
+       add     x1, x0, x1
+       sub     x3, x2, #1
+       bic     x0, x0, x3
+flush_loop:
+       dc      civac, x0
+       add     x0, x0, x2
+       cmp     x0, x1
+       b.lo    flush_loop
+       dsb     sy
+       ret
+
+
+       /* ------------------------------------------
+        * Invalidate from base address till
+        * size. 'x0' = addr, 'x1' = size
+        * ------------------------------------------
+        */
+func inv_dcache_range
+       dcache_line_size x2, x3
+       add     x1, x0, x1
+       sub     x3, x2, #1
+       bic     x0, x0, x3
+inv_loop:
+       dc      ivac, x0
+       add     x0, x0, x2
+       cmp     x0, x1
+       b.lo    inv_loop
+       dsb     sy
+       ret
+
+
+       /* ---------------------------------------------------------------
+        * Data cache operations by set/way to the level specified
+        *
+        * The main function, do_dcsw_op requires:
+        * x0: The operation type (0-2), as defined in arch.h
+        * x3: The last cache level to operate on
+        * x9: clidr_el1
+        * x10: The cache level to begin operation from
+        * and will carry out the operation on each data cache from level 0
+        * to the level in x3 in sequence
+        *
+        * The dcsw_op macro sets up the x3 and x9 parameters based on
+        * clidr_el1 cache information before invoking the main function
+        * ---------------------------------------------------------------
+        */
+
+       .macro  dcsw_op shift, fw, ls
+       mrs     x9, clidr_el1
+       ubfx    x3, x9, \shift, \fw
+       lsl     x3, x3, \ls
+       mov     x10, xzr
+       b       do_dcsw_op
+       .endm
+
+func do_dcsw_op
+       cbz     x3, exit
+       adr     x14, dcsw_loop_table    // compute inner loop address
+       add     x14, x14, x0, lsl #5    // inner loop is 8x32-bit instructions
+       mov     x0, x9
+       mov     w8, #1
+loop1:
+       add     x2, x10, x10, lsr #1    // work out 3x current cache level
+       lsr     x1, x0, x2              // extract cache type bits from clidr
+       and     x1, x1, #7              // mask the bits for current cache only
+       cmp     x1, #2                  // see what cache we have at this level
+       b.lt    level_done              // nothing to do if no cache or icache
+
+       msr     csselr_el1, x10         // select current cache level in csselr
+       isb                             // isb to sych the new cssr&csidr
+       mrs     x1, ccsidr_el1          // read the new ccsidr
+       and     x2, x1, #7              // extract the length of the cache lines
+       add     x2, x2, #4              // add 4 (line length offset)
+       ubfx    x4, x1, #3, #10         // maximum way number
+       clz     w5, w4                  // bit position of way size increment
+       lsl     w9, w4, w5              // w9 = aligned max way number
+       lsl     w16, w8, w5             // w16 = way number loop decrement
+       orr     w9, w10, w9             // w9 = combine way and cache number
+       ubfx    w6, w1, #13, #15        // w6 = max set number
+       lsl     w17, w8, w2             // w17 = set number loop decrement
+       dsb     sy                      // barrier before we start this level
+       br      x14                     // jump to DC operation specific loop
+
+       .macro  dcsw_loop _op
+loop2_\_op:
+       lsl     w7, w6, w2              // w7 = aligned max set number
+
+loop3_\_op:
+       orr     w11, w9, w7             // combine cache, way and set number
+       dc      \_op, x11
+       subs    w7, w7, w17             // decrement set number
+       b.ge    loop3_\_op
+
+       subs    x9, x9, x16             // decrement way number
+       b.ge    loop2_\_op
+
+       b       level_done
+       .endm
+
+level_done:
+       add     x10, x10, #2            // increment cache number
+       cmp     x3, x10
+       b.gt    loop1
+       msr     csselr_el1, xzr         // select cache level 0 in csselr
+       dsb     sy                      // barrier to complete final cache operation
+       isb
+exit:
+       ret
+
+dcsw_loop_table:
+       dcsw_loop isw
+       dcsw_loop cisw
+       dcsw_loop csw
+
+
+func dcsw_op_louis
+       dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
+
+
+func dcsw_op_all
+       dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
+
+       /* ---------------------------------------------------------------
+        *  Helper macro for data cache operations by set/way for the
+        *  level specified
+        * ---------------------------------------------------------------
+        */
+       .macro dcsw_op_level level
+       mrs     x9, clidr_el1
+       mov     x3, \level
+       sub     x10, x3, #2
+       b       do_dcsw_op
+       .endm
+
+       /* ---------------------------------------------------------------
+        * Data cache operations by set/way for level 1 cache
+        *
+        * The main function, do_dcsw_op requires:
+        * x0: The operation type (0-2), as defined in arch.h
+        * ---------------------------------------------------------------
+        */
+func dcsw_op_level1
+       dcsw_op_level #(1 << LEVEL_SHIFT)
+
+       /* ---------------------------------------------------------------
+        * Data cache operations by set/way for level 2 cache
+        *
+        * The main function, do_dcsw_op requires:
+        * x0: The operation type (0-2), as defined in arch.h
+        * ---------------------------------------------------------------
+        */
+func dcsw_op_level2
+       dcsw_op_level #(2 << LEVEL_SHIFT)
+
+       /* ---------------------------------------------------------------
+        * Data cache operations by set/way for level 3 cache
+        *
+        * The main function, do_dcsw_op requires:
+        * x0: The operation type (0-2), as defined in arch.h
+        * ---------------------------------------------------------------
+        */
+func dcsw_op_level3
+       dcsw_op_level #(3 << LEVEL_SHIFT)
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S
new file mode 100644 (file)
index 0000000..f605bf4
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+
+       .globl  get_afflvl_shift
+       .globl  mpidr_mask_lower_afflvls
+       .globl  eret
+       .globl  smc
+
+       .globl  zeromem16
+       .globl  memcpy16
+
+       .globl  disable_mmu_el3
+       .globl  disable_mmu_icache_el3
+
+#if SUPPORT_VFP
+       .globl  enable_vfp
+#endif
+
+func get_afflvl_shift
+       cmp     x0, #3
+       cinc    x0, x0, eq
+       mov     x1, #MPIDR_AFFLVL_SHIFT
+       lsl     x0, x0, x1
+       ret
+
+func mpidr_mask_lower_afflvls
+       cmp     x1, #3
+       cinc    x1, x1, eq
+       mov     x2, #MPIDR_AFFLVL_SHIFT
+       lsl     x2, x1, x2
+       lsr     x0, x0, x2
+       lsl     x0, x0, x2
+       ret
+
+
+func eret
+       eret
+
+
+func smc
+       smc     #0
+
+/* -----------------------------------------------------------------------
+ * void zeromem16(void *mem, unsigned int length);
+ *
+ * Initialise a memory region to 0.
+ * The memory address must be 16-byte aligned.
+ * -----------------------------------------------------------------------
+ */
+func zeromem16
+#if ASM_ASSERTION
+       tst     x0, #0xf
+       ASM_ASSERT(eq)
+#endif
+       add     x2, x0, x1
+/* zero 16 bytes at a time */
+z_loop16:
+       sub     x3, x2, x0
+       cmp     x3, #16
+       b.lt    z_loop1
+       stp     xzr, xzr, [x0], #16
+       b       z_loop16
+/* zero byte per byte */
+z_loop1:
+       cmp     x0, x2
+       b.eq    z_end
+       strb    wzr, [x0], #1
+       b       z_loop1
+z_end: ret
+
+
+/* --------------------------------------------------------------------------
+ * void memcpy16(void *dest, const void *src, unsigned int length)
+ *
+ * Copy length bytes from memory area src to memory area dest.
+ * The memory areas should not overlap.
+ * Destination and source addresses must be 16-byte aligned.
+ * --------------------------------------------------------------------------
+ */
+func memcpy16
+#if ASM_ASSERTION
+       orr     x3, x0, x1
+       tst     x3, #0xf
+       ASM_ASSERT(eq)
+#endif
+/* copy 16 bytes at a time */
+m_loop16:
+       cmp     x2, #16
+       b.lt    m_loop1
+       ldp     x3, x4, [x1], #16
+       stp     x3, x4, [x0], #16
+       sub     x2, x2, #16
+       b       m_loop16
+/* copy byte per byte */
+m_loop1:
+       cbz     x2, m_end
+       ldrb    w3, [x1], #1
+       strb    w3, [x0], #1
+       subs    x2, x2, #1
+       b.ne    m_loop1
+m_end: ret
+
+/* ---------------------------------------------------------------------------
+ * Disable the MMU at EL3
+ * This is implemented in assembler to ensure that the data cache is cleaned
+ * and invalidated after the MMU is disabled without any intervening cacheable
+ * data accesses
+ * ---------------------------------------------------------------------------
+ */
+
+func disable_mmu_el3
+       mov     x1, #(SCTLR_M_BIT | SCTLR_C_BIT)
+do_disable_mmu:
+       mrs     x0, sctlr_el3
+       bic     x0, x0, x1
+       msr     sctlr_el3, x0
+       isb                             // ensure MMU is off
+       mov     x0, #DCCISW             // DCache clean and invalidate
+       b       dcsw_op_all
+
+
+func disable_mmu_icache_el3
+       mov     x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT)
+       b       do_disable_mmu
+
+/* ---------------------------------------------------------------------------
+ * Enable the use of VFP at EL3
+ * ---------------------------------------------------------------------------
+ */
+#if SUPPORT_VFP
+func enable_vfp
+       mrs     x0, cpacr_el1
+       orr     x0, x0, #CPACR_VFP_BITS
+       msr     cpacr_el1, x0
+       mrs     x0, cptr_el3
+       mov     x1, #AARCH64_CPTR_TFP
+       bic     x0, x0, x1
+       msr     cptr_el3, x0
+       isb
+       ret
+#endif
diff --git a/lib/aarch64/xlat_helpers.c b/lib/aarch64/xlat_helpers.c
new file mode 100644 (file)
index 0000000..d401ffc
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <assert.h>
+
+/*******************************************************************************
+ * Helper to create a level 1/2 table descriptor which points to a level 2/3
+ * table.
+ ******************************************************************************/
+unsigned long create_table_desc(unsigned long *next_table_ptr)
+{
+       unsigned long desc = (unsigned long) next_table_ptr;
+
+       /* Clear the last 12 bits */
+       desc >>= FOUR_KB_SHIFT;
+       desc <<= FOUR_KB_SHIFT;
+
+       desc |= TABLE_DESC;
+
+       return desc;
+}
+
+/*******************************************************************************
+ * Helper to create a level 1/2/3 block descriptor which maps the va to addr
+ ******************************************************************************/
+unsigned long create_block_desc(unsigned long desc,
+                               unsigned long addr,
+                               unsigned int level)
+{
+       switch (level) {
+       case LEVEL1:
+               desc |= (addr << FIRST_LEVEL_DESC_N) | BLOCK_DESC;
+               break;
+       case LEVEL2:
+               desc |= (addr << SECOND_LEVEL_DESC_N) | BLOCK_DESC;
+               break;
+       case LEVEL3:
+               desc |= (addr << THIRD_LEVEL_DESC_N) | TABLE_DESC;
+               break;
+       default:
+               assert(0);
+       }
+
+       return desc;
+}
+
+/*******************************************************************************
+ * Helper to create a level 1/2/3 block descriptor which maps the va to output_
+ * addr with Device nGnRE attributes.
+ ******************************************************************************/
+unsigned long create_device_block(unsigned long output_addr,
+                                 unsigned int level,
+                                 unsigned int ns)
+{
+       unsigned long upper_attrs, lower_attrs, desc;
+
+       lower_attrs = LOWER_ATTRS(ACCESS_FLAG | OSH | AP_RW);
+       lower_attrs |= LOWER_ATTRS(ns | ATTR_DEVICE_INDEX);
+       upper_attrs = UPPER_ATTRS(XN);
+       desc = upper_attrs | lower_attrs;
+
+       return create_block_desc(desc, output_addr, level);
+}
+
+/*******************************************************************************
+ * Helper to create a level 1/2/3 block descriptor which maps the va to output_
+ * addr with inner-shareable normal wbwa read-only memory attributes.
+ ******************************************************************************/
+unsigned long create_romem_block(unsigned long output_addr,
+                                unsigned int level,
+                                unsigned int ns)
+{
+       unsigned long upper_attrs, lower_attrs, desc;
+
+       lower_attrs = LOWER_ATTRS(ACCESS_FLAG | ISH | AP_RO);
+       lower_attrs |= LOWER_ATTRS(ns | ATTR_IWBWA_OWBWA_NTR_INDEX);
+       upper_attrs = UPPER_ATTRS(0ull);
+       desc = upper_attrs | lower_attrs;
+
+       return create_block_desc(desc, output_addr, level);
+}
+
+/*******************************************************************************
+ * Helper to create a level 1/2/3 block descriptor which maps the va to output_
+ * addr with inner-shareable normal wbwa read-write memory attributes.
+ ******************************************************************************/
+unsigned long create_rwmem_block(unsigned long output_addr,
+                                unsigned int level,
+                                unsigned int ns)
+{
+       unsigned long upper_attrs, lower_attrs, desc;
+
+       lower_attrs = LOWER_ATTRS(ACCESS_FLAG | ISH | AP_RW);
+       lower_attrs |= LOWER_ATTRS(ns | ATTR_IWBWA_OWBWA_NTR_INDEX);
+       upper_attrs = UPPER_ATTRS(XN);
+       desc = upper_attrs | lower_attrs;
+
+       return create_block_desc(desc, output_addr, level);
+}
diff --git a/lib/aarch64/xlat_tables.c b/lib/aarch64/xlat_tables.c
new file mode 100644 (file)
index 0000000..ddc9ba8
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <cassert.h>
+#include <platform_def.h>
+#include <string.h>
+#include <xlat_tables.h>
+
+
+#ifndef DEBUG_XLAT_TABLE
+#define DEBUG_XLAT_TABLE 0
+#endif
+
+#if DEBUG_XLAT_TABLE
+#define debug_print(...) printf(__VA_ARGS__)
+#else
+#define debug_print(...) ((void)0)
+#endif
+
+CASSERT(ADDR_SPACE_SIZE > 0, assert_valid_addr_space_size);
+
+#define UNSET_DESC     ~0ul
+
+#define NUM_L1_ENTRIES (ADDR_SPACE_SIZE >> L1_XLAT_ADDRESS_SHIFT)
+
+static uint64_t l1_xlation_table[NUM_L1_ENTRIES]
+__aligned(NUM_L1_ENTRIES * sizeof(uint64_t));
+
+static uint64_t xlat_tables[MAX_XLAT_TABLES][XLAT_TABLE_ENTRIES]
+__aligned(XLAT_TABLE_SIZE) __attribute__((section("xlat_table")));
+
+static unsigned next_xlat;
+static unsigned long max_pa;
+static unsigned long max_va;
+static unsigned long tcr_ps_bits;
+
+/*
+ * Array of all memory regions stored in order of ascending base address.
+ * The list is terminated by the first entry with size == 0.
+ */
+static mmap_region_t mmap[MAX_MMAP_REGIONS + 1];
+
+
+static void print_mmap(void)
+{
+#if DEBUG_XLAT_TABLE
+       debug_print("mmap:\n");
+       mmap_region_t *mm = mmap;
+       while (mm->size) {
+               debug_print(" %010lx %010lx %10lx %x\n", mm->base_va,
+                                       mm->base_pa, mm->size, mm->attr);
+               ++mm;
+       };
+       debug_print("\n");
+#endif
+}
+
+void mmap_add_region(unsigned long base_pa, unsigned long base_va,
+                       unsigned long size, unsigned attr)
+{
+       mmap_region_t *mm = mmap;
+       mmap_region_t *mm_last = mm + sizeof(mmap) / sizeof(mmap[0]) - 1;
+       unsigned long pa_end = base_pa + size - 1;
+       unsigned long va_end = base_va + size - 1;
+
+       assert(IS_PAGE_ALIGNED(base_pa));
+       assert(IS_PAGE_ALIGNED(base_va));
+       assert(IS_PAGE_ALIGNED(size));
+
+       if (!size)
+               return;
+
+       /* Find correct place in mmap to insert new region */
+       while (mm->base_va < base_va && mm->size)
+               ++mm;
+
+       /* Make room for new region by moving other regions up by one place */
+       memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm);
+
+       /* Check we haven't lost the empty sentinal from the end of the array */
+       assert(mm_last->size == 0);
+
+       mm->base_pa = base_pa;
+       mm->base_va = base_va;
+       mm->size = size;
+       mm->attr = attr;
+
+       if (pa_end > max_pa)
+               max_pa = pa_end;
+       if (va_end > max_va)
+               max_va = va_end;
+}
+
+void mmap_add(const mmap_region_t *mm)
+{
+       while (mm->size) {
+               mmap_add_region(mm->base_pa, mm->base_va, mm->size, mm->attr);
+               ++mm;
+       }
+}
+
+static unsigned long mmap_desc(unsigned attr, unsigned long addr_pa,
+                                       unsigned level)
+{
+       unsigned long desc = addr_pa;
+
+       desc |= level == 3 ? TABLE_DESC : BLOCK_DESC;
+
+       desc |= attr & MT_NS ? LOWER_ATTRS(NS) : 0;
+
+       desc |= attr & MT_RW ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
+
+       desc |= LOWER_ATTRS(ACCESS_FLAG);
+
+       if (attr & MT_MEMORY) {
+               desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
+               if (attr & MT_RW)
+                       desc |= UPPER_ATTRS(XN);
+       } else {
+               desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH);
+               desc |= UPPER_ATTRS(XN);
+       }
+
+       debug_print(attr & MT_MEMORY ? "MEM" : "DEV");
+       debug_print(attr & MT_RW ? "-RW" : "-RO");
+       debug_print(attr & MT_NS ? "-NS" : "-S");
+
+       return desc;
+}
+
+static int mmap_region_attr(mmap_region_t *mm, unsigned long base_va,
+                                       unsigned long size)
+{
+       int attr = mm->attr;
+
+       for (;;) {
+               ++mm;
+
+               if (!mm->size)
+                       return attr; /* Reached end of list */
+
+               if (mm->base_va >= base_va + size)
+                       return attr; /* Next region is after area so end */
+
+               if (mm->base_va + mm->size <= base_va)
+                       continue; /* Next region has already been overtaken */
+
+               if ((mm->attr & attr) == attr)
+                       continue; /* Region doesn't override attribs so skip */
+
+               attr &= mm->attr;
+
+               if (mm->base_va > base_va ||
+                       mm->base_va + mm->size < base_va + size)
+                       return -1; /* Region doesn't fully cover our area */
+       }
+}
+
+static mmap_region_t *init_xlation_table(mmap_region_t *mm,
+                                       unsigned long base_va,
+                                       unsigned long *table, unsigned level)
+{
+       unsigned level_size_shift = L1_XLAT_ADDRESS_SHIFT - (level - 1) *
+                                               XLAT_TABLE_ENTRIES_SHIFT;
+       unsigned level_size = 1 << level_size_shift;
+       unsigned long level_index_mask = XLAT_TABLE_ENTRIES_MASK << level_size_shift;
+
+       assert(level <= 3);
+
+       debug_print("New xlat table:\n");
+
+       do  {
+               unsigned long desc = UNSET_DESC;
+
+               if (mm->base_va + mm->size <= base_va) {
+                       /* Area now after the region so skip it */
+                       ++mm;
+                       continue;
+               }
+
+               debug_print("      %010lx %8lx " + 6 - 2 * level, base_va,
+                               level_size);
+
+               if (mm->base_va >= base_va + level_size) {
+                       /* Next region is after area so nothing to map yet */
+                       desc = INVALID_DESC;
+               } else if (mm->base_va <= base_va && mm->base_va + mm->size >=
+                               base_va + level_size) {
+                       /* Next region covers all of area */
+                       int attr = mmap_region_attr(mm, base_va, level_size);
+                       if (attr >= 0)
+                               desc = mmap_desc(attr,
+                                       base_va - mm->base_va + mm->base_pa,
+                                       level);
+               }
+               /* else Next region only partially covers area, so need */
+
+               if (desc == UNSET_DESC) {
+                       /* Area not covered by a region so need finer table */
+                       unsigned long *new_table = xlat_tables[next_xlat++];
+                       assert(next_xlat <= MAX_XLAT_TABLES);
+                       desc = TABLE_DESC | (unsigned long)new_table;
+
+                       /* Recurse to fill in new table */
+                       mm = init_xlation_table(mm, base_va,
+                                               new_table, level+1);
+               }
+
+               debug_print("\n");
+
+               *table++ = desc;
+               base_va += level_size;
+       } while (mm->size && (base_va & level_index_mask));
+
+       return mm;
+}
+
+static unsigned int calc_physical_addr_size_bits(unsigned long max_addr)
+{
+       /* Physical address can't exceed 48 bits */
+       assert((max_addr & ADDR_MASK_48_TO_63) == 0);
+
+       /* 48 bits address */
+       if (max_addr & ADDR_MASK_44_TO_47)
+               return TCR_PS_BITS_256TB;
+
+       /* 44 bits address */
+       if (max_addr & ADDR_MASK_42_TO_43)
+               return TCR_PS_BITS_16TB;
+
+       /* 42 bits address */
+       if (max_addr & ADDR_MASK_40_TO_41)
+               return TCR_PS_BITS_4TB;
+
+       /* 40 bits address */
+       if (max_addr & ADDR_MASK_36_TO_39)
+               return TCR_PS_BITS_1TB;
+
+       /* 36 bits address */
+       if (max_addr & ADDR_MASK_32_TO_35)
+               return TCR_PS_BITS_64GB;
+
+       return TCR_PS_BITS_4GB;
+}
+
+void init_xlat_tables(void)
+{
+       print_mmap();
+       init_xlation_table(mmap, 0, l1_xlation_table, 1);
+       tcr_ps_bits = calc_physical_addr_size_bits(max_pa);
+       assert(max_va < ADDR_SPACE_SIZE);
+}
+
+/*******************************************************************************
+ * Macro generating the code for the function enabling the MMU in the given
+ * exception level, assuming that the pagetables have already been created.
+ *
+ *   _el:              Exception level at which the function will run
+ *   _tcr_extra:       Extra bits to set in the TCR register. This mask will
+ *                     be OR'ed with the default TCR value.
+ *   _tlbi_fct:                Function to invalidate the TLBs at the current
+ *                     exception level
+ ******************************************************************************/
+#define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct)               \
+       void enable_mmu_el##_el(uint32_t flags)                         \
+       {                                                               \
+               uint64_t mair, tcr, ttbr;                               \
+               uint32_t sctlr;                                         \
+                                                                       \
+               assert(IS_IN_EL(_el));                                  \
+               assert((read_sctlr_el##_el() & SCTLR_M_BIT) == 0);      \
+                                                                       \
+               /* Set attributes in the right indices of the MAIR */   \
+               mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);   \
+               mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,             \
+                               ATTR_IWBWA_OWBWA_NTR_INDEX);            \
+               write_mair_el##_el(mair);                               \
+                                                                       \
+               /* Invalidate TLBs at the current exception level */    \
+               _tlbi_fct();                                            \
+                                                                       \
+               /* Set TCR bits as well. */                             \
+               /* Inner & outer WBWA & shareable + T0SZ = 32 */        \
+               tcr = TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA |      \
+                       TCR_RGN_INNER_WBA |                             \
+                       (64 - __builtin_ctzl(ADDR_SPACE_SIZE));         \
+               tcr |= _tcr_extra;                                      \
+               write_tcr_el##_el(tcr);                                 \
+                                                                       \
+               /* Set TTBR bits as well */                             \
+               ttbr = (uint64_t) l1_xlation_table;                     \
+               write_ttbr0_el##_el(ttbr);                              \
+                                                                       \
+               /* Ensure all translation table writes have drained */  \
+               /* into memory, the TLB invalidation is complete, */    \
+               /* and translation register writes are committed */     \
+               /* before enabling the MMU */                           \
+               dsb();                                                  \
+               isb();                                                  \
+                                                                       \
+               sctlr = read_sctlr_el##_el();                           \
+               sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT;                   \
+                                                                       \
+               if (flags & DISABLE_DCACHE)                             \
+                       sctlr &= ~SCTLR_C_BIT;                          \
+               else                                                    \
+                       sctlr |= SCTLR_C_BIT;                           \
+                                                                       \
+               write_sctlr_el##_el(sctlr);                             \
+                                                                       \
+               /* Ensure the MMU enable takes effect immediately */    \
+               isb();                                                  \
+       }
+
+/* Define EL1 and EL3 variants of the function enabling the MMU */
+DEFINE_ENABLE_MMU_EL(1,
+               (tcr_ps_bits << TCR_EL1_IPS_SHIFT),
+               tlbivmalle1)
+DEFINE_ENABLE_MMU_EL(3,
+               TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT),
+               tlbialle3)
diff --git a/lib/cpus/aarch64/aem_generic.S b/lib/cpus/aarch64/aem_generic.S
new file mode 100644 (file)
index 0000000..58a64a6
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <aem_generic.h>
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+func aem_generic_core_pwr_dwn
+       /* ---------------------------------------------
+        * Disable the Data Cache.
+        * ---------------------------------------------
+        */
+       mrs     x1, sctlr_el3
+       bic     x1, x1, #SCTLR_C_BIT
+       msr     sctlr_el3, x1
+       isb
+
+       mov     x0, #DCCISW
+
+       /* ---------------------------------------------
+        * Flush L1 cache to PoU.
+        * ---------------------------------------------
+        */
+       b       dcsw_op_louis
+
+
+func aem_generic_cluster_pwr_dwn
+       /* ---------------------------------------------
+        * Disable the Data Cache.
+        * ---------------------------------------------
+        */
+       mrs     x1, sctlr_el3
+       bic     x1, x1, #SCTLR_C_BIT
+       msr     sctlr_el3, x1
+       isb
+
+       /* ---------------------------------------------
+        * Flush L1 and L2 caches to PoC.
+        * ---------------------------------------------
+        */
+       mov     x0, #DCCISW
+       b       dcsw_op_all
+
+       /* ---------------------------------------------
+        * This function provides cpu specific
+        * register information for crash reporting.
+        * It needs to return with x6 pointing to
+        * a list of register names in ascii and
+        * x8 - x15 having values of registers to be
+        * reported.
+        * ---------------------------------------------
+        */
+func aem_generic_cpu_reg_dump
+       mov     x6, #0 /* no registers to report */
+       ret
+
+
+/* cpu_ops for Base AEM FVP */
+declare_cpu_ops aem_generic, BASE_AEM_MIDR, 1
+
+/* cpu_ops for Foundation FVP */
+declare_cpu_ops aem_generic, FOUNDATION_AEM_MIDR, 1
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
new file mode 100644 (file)
index 0000000..188f3c1
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a53.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+       /* ---------------------------------------------
+        * Disable L1 data cache and unified L2 cache
+        * ---------------------------------------------
+        */
+func cortex_a53_disable_dcache
+       mrs     x1, sctlr_el3
+       bic     x1, x1, #SCTLR_C_BIT
+       msr     sctlr_el3, x1
+       isb
+       ret
+
+       /* ---------------------------------------------
+        * Disable intra-cluster coherency
+        * ---------------------------------------------
+        */
+func cortex_a53_disable_smp
+       mrs     x0, CPUECTLR_EL1
+       bic     x0, x0, #CPUECTLR_SMP_BIT
+       msr     CPUECTLR_EL1, x0
+       isb
+       dsb     sy
+       ret
+
+func cortex_a53_reset_func
+       /* ---------------------------------------------
+        * As a bare minimum enable the SMP bit if it is
+        * not already set.
+        * Clobbers : x0
+        * ---------------------------------------------
+        */
+       mrs     x0, CPUECTLR_EL1
+       tst     x0, #CPUECTLR_SMP_BIT
+       b.ne    skip_smp_setup
+       orr     x0, x0, #CPUECTLR_SMP_BIT
+       msr     CPUECTLR_EL1, x0
+       isb
+skip_smp_setup:
+       ret
+
+func cortex_a53_core_pwr_dwn
+       mov     x18, x30
+
+       /* ---------------------------------------------
+        * Turn off caches.
+        * ---------------------------------------------
+        */
+       bl      cortex_a53_disable_dcache
+
+       /* ---------------------------------------------
+        * Flush L1 caches.
+        * ---------------------------------------------
+        */
+       mov     x0, #DCCISW
+       bl      dcsw_op_level1
+
+       /* ---------------------------------------------
+        * Come out of intra cluster coherency
+        * ---------------------------------------------
+        */
+       mov     x30, x18
+       b       cortex_a53_disable_smp
+
+func cortex_a53_cluster_pwr_dwn
+       mov     x18, x30
+
+       /* ---------------------------------------------
+        * Turn off caches.
+        * ---------------------------------------------
+        */
+       bl      cortex_a53_disable_dcache
+
+       /* ---------------------------------------------
+        * Flush L1 caches.
+        * ---------------------------------------------
+        */
+       mov     x0, #DCCISW
+       bl      dcsw_op_level1
+
+       /* ---------------------------------------------
+        * Disable the optional ACP.
+        * ---------------------------------------------
+        */
+       bl      plat_disable_acp
+
+       /* ---------------------------------------------
+        * Flush L2 caches.
+        * ---------------------------------------------
+        */
+       mov     x0, #DCCISW
+       bl      dcsw_op_level2
+
+       /* ---------------------------------------------
+        * Come out of intra cluster coherency
+        * ---------------------------------------------
+        */
+       mov     x30, x18
+       b       cortex_a53_disable_smp
+
+       /* ---------------------------------------------
+        * This function provides cortex_a53 specific
+        * register information for crash reporting.
+        * It needs to return with x6 pointing to
+        * a list of register names in ascii and
+        * x8 - x15 having values of registers to be
+        * reported.
+        * ---------------------------------------------
+        */
+.section .rodata.cortex_a53_regs, "aS"
+cortex_a53_regs:  /* The ascii list of register names to be reported */
+       .asciz  "cpuectlr_el1", ""
+
+func cortex_a53_cpu_reg_dump
+       adr     x6, cortex_a53_regs
+       mrs     x8, CPUECTLR_EL1
+       ret
+
+declare_cpu_ops cortex_a53, CORTEX_A53_MIDR
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
new file mode 100644 (file)
index 0000000..eb6c736
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <bl_common.h>
+#include <cortex_a57.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+       /* ---------------------------------------------
+        * Disable L1 data cache and unified L2 cache
+        * ---------------------------------------------
+        */
+func cortex_a57_disable_dcache
+       mrs     x1, sctlr_el3
+       bic     x1, x1, #SCTLR_C_BIT
+       msr     sctlr_el3, x1
+       isb
+       ret
+
+       /* ---------------------------------------------
+        * Disable all types of L2 prefetches.
+        * ---------------------------------------------
+        */
+func cortex_a57_disable_l2_prefetch
+       mrs     x0, CPUECTLR_EL1
+       orr     x0, x0, #CPUECTLR_DIS_TWD_ACC_PFTCH_BIT
+       mov     x1, #CPUECTLR_L2_IPFTCH_DIST_MASK
+       orr     x1, x1, #CPUECTLR_L2_DPFTCH_DIST_MASK
+       bic     x0, x0, x1
+       msr     CPUECTLR_EL1, x0
+       isb
+       dsb     ish
+       ret
+
+       /* ---------------------------------------------
+        * Disable intra-cluster coherency
+        * ---------------------------------------------
+        */
+func cortex_a57_disable_smp
+       mrs     x0, CPUECTLR_EL1
+       bic     x0, x0, #CPUECTLR_SMP_BIT
+       msr     CPUECTLR_EL1, x0
+       ret
+
+       /* ---------------------------------------------
+        * Disable debug interfaces
+        * ---------------------------------------------
+        */
+func cortex_a57_disable_ext_debug
+       mov     x0, #1
+       msr     osdlr_el1, x0
+       isb
+       dsb     sy
+       ret
+
+       /* --------------------------------------------------
+        * Errata Workaround for Cortex A57 Errata #806969.
+        * This applies only to revision r0p0 of Cortex A57.
+        * Inputs:
+        * x0: variant[4:7] and revision[0:3] of current cpu.
+        * Clobbers : x0 - x5
+        * --------------------------------------------------
+        */
+func errata_a57_806969_wa
+       /*
+        * Compare x0 against revision r0p0
+        */
+       cbz     x0, apply_806969
+#if DEBUG
+       b       print_revision_warning
+#else
+       ret
+#endif
+apply_806969:
+       /*
+        * Test if errata has already been applied in an earlier
+        * invocation of the reset handler and does not need to
+        * be applied again.
+        */
+       mrs     x1, CPUACTLR_EL1
+       tst     x1, #CPUACTLR_NO_ALLOC_WBWA
+       b.ne    skip_806969
+       orr     x1, x1, #CPUACTLR_NO_ALLOC_WBWA
+       msr     CPUACTLR_EL1, x1
+skip_806969:
+       ret
+
+
+       /* ---------------------------------------------------
+        * Errata Workaround for Cortex A57 Errata #813420.
+        * This applies only to revision r0p0 of Cortex A57.
+        * Inputs:
+        * x0: variant[4:7] and revision[0:3] of current cpu.
+        * Clobbers : x0 - x5
+        * ---------------------------------------------------
+        */
+func errata_a57_813420_wa
+       /*
+        * Compare x0 against revision r0p0
+        */
+       cbz     x0, apply_813420
+#if DEBUG
+       b       print_revision_warning
+#else
+       ret
+#endif
+apply_813420:
+       /*
+        * Test if errata has already been applied in an earlier
+        * invocation of the reset handler and does not need to
+        * be applied again.
+        */
+       mrs     x1, CPUACTLR_EL1
+       tst     x1, #CPUACTLR_DCC_AS_DCCI
+       b.ne    skip_813420
+       orr     x1, x1, #CPUACTLR_DCC_AS_DCCI
+       msr     CPUACTLR_EL1, x1
+skip_813420:
+       ret
+
+       /* -------------------------------------------------
+        * The CPU Ops reset function for Cortex-A57.
+        * Clobbers: x0-x5, x15, x19, x30
+        * -------------------------------------------------
+        */
+func cortex_a57_reset_func
+       mov     x19, x30
+       mrs     x0, midr_el1
+
+       /*
+        * Extract the variant[20:23] and revision[0:3] from x0
+        * and pack it in x15[0:7] as variant[4:7] and revision[0:3].
+        * First extract x0[16:23] to x15[0:7] and zero fill the rest.
+        * Then extract x0[0:3] into x15[0:3] retaining other bits.
+        */
+       ubfx    x15, x0, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
+       bfxil   x15, x0, #MIDR_REV_SHIFT, #MIDR_REV_BITS
+
+#if ERRATA_A57_806969
+       mov     x0, x15
+       bl      errata_a57_806969_wa
+#endif
+
+#if ERRATA_A57_813420
+       mov     x0, x15
+       bl      errata_a57_813420_wa
+#endif
+
+       /* ---------------------------------------------
+        * As a bare minimum enable the SMP bit if it is
+        * not already set.
+        * ---------------------------------------------
+        */
+       mrs     x0, CPUECTLR_EL1
+       tst     x0, #CPUECTLR_SMP_BIT
+       b.ne    skip_smp_setup
+       orr     x0, x0, #CPUECTLR_SMP_BIT
+       msr     CPUECTLR_EL1, x0
+skip_smp_setup:
+       isb
+       ret     x19
+
+       /* ----------------------------------------------------
+        * The CPU Ops core power down function for Cortex-A57.
+        * ----------------------------------------------------
+        */
+func cortex_a57_core_pwr_dwn
+       mov     x18, x30
+
+       /* ---------------------------------------------
+        * Turn off caches.
+        * ---------------------------------------------
+        */
+       bl      cortex_a57_disable_dcache
+
+       /* ---------------------------------------------
+        * Disable the L2 prefetches.
+        * ---------------------------------------------
+        */
+       bl      cortex_a57_disable_l2_prefetch
+
+       /* ---------------------------------------------
+        * Flush L1 caches.
+        * ---------------------------------------------
+        */
+       mov     x0, #DCCISW
+       bl      dcsw_op_level1
+
+       /* ---------------------------------------------
+        * Come out of intra cluster coherency
+        * ---------------------------------------------
+        */
+       bl      cortex_a57_disable_smp
+
+       /* ---------------------------------------------
+        * Force the debug interfaces to be quiescent
+        * ---------------------------------------------
+        */
+       mov     x30, x18
+       b       cortex_a57_disable_ext_debug
+
+       /* -------------------------------------------------------
+        * The CPU Ops cluster power down function for Cortex-A57.
+        * -------------------------------------------------------
+        */
+func cortex_a57_cluster_pwr_dwn
+       mov     x18, x30
+
+       /* ---------------------------------------------
+        * Turn off caches.
+        * ---------------------------------------------
+        */
+       bl      cortex_a57_disable_dcache
+
+       /* ---------------------------------------------
+        * Disable the L2 prefetches.
+        * ---------------------------------------------
+        */
+       bl      cortex_a57_disable_l2_prefetch
+
+#if !SKIP_A57_L1_FLUSH_PWR_DWN
+       /* -------------------------------------------------
+        * Flush the L1 caches.
+        * -------------------------------------------------
+        */
+       mov     x0, #DCCISW
+       bl      dcsw_op_level1
+#endif
+       /* ---------------------------------------------
+        * Disable the optional ACP.
+        * ---------------------------------------------
+        */
+       bl      plat_disable_acp
+
+       /* -------------------------------------------------
+        * Flush the L2 caches.
+        * -------------------------------------------------
+        */
+       mov     x0, #DCCISW
+       bl      dcsw_op_level2
+
+       /* ---------------------------------------------
+        * Come out of intra cluster coherency
+        * ---------------------------------------------
+        */
+       bl      cortex_a57_disable_smp
+
+       /* ---------------------------------------------
+        * Force the debug interfaces to be quiescent
+        * ---------------------------------------------
+        */
+       mov     x30, x18
+       b       cortex_a57_disable_ext_debug
+
+       /* ---------------------------------------------
+        * This function provides cortex_a57 specific
+        * register information for crash reporting.
+        * It needs to return with x6 pointing to
+        * a list of register names in ascii and
+        * x8 - x15 having values of registers to be
+        * reported.
+        * ---------------------------------------------
+        */
+.section .rodata.cortex_a57_regs, "aS"
+cortex_a57_regs:  /* The ascii list of register names to be reported */
+       .asciz  "cpuectlr_el1", ""
+
+func cortex_a57_cpu_reg_dump
+       adr     x6, cortex_a57_regs
+       mrs     x8, CPUECTLR_EL1
+       ret
+
+
+declare_cpu_ops cortex_a57, CORTEX_A57_MIDR
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
new file mode 100644 (file)
index 0000000..bebe7c0
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <cpu_macros.S>
+#if IMAGE_BL31
+#include <cpu_data.h>
+#endif
+
+ /* Reset fn is needed in BL at reset vector */
+#if IMAGE_BL1 || IMAGE_BL31
+       /*
+        * The reset handler common to all platforms.  After a matching
+        * cpu_ops structure entry is found, the correponding reset_handler
+        * in the cpu_ops is invoked.
+        * Clobbers: x0 - x19, x30
+        */
+       .globl  reset_handler
+func reset_handler
+       mov     x19, x30
+
+       /* The plat_reset_handler can clobber x0 - x18, x30 */
+       bl      plat_reset_handler
+
+       /* Get the matching cpu_ops pointer */
+       bl      get_cpu_ops_ptr
+#if ASM_ASSERTION
+       cmp     x0, #0
+       ASM_ASSERT(ne)
+#endif
+
+       /* Get the cpu_ops reset handler */
+       ldr     x2, [x0, #CPU_RESET_FUNC]
+       mov     x30, x19
+       cbz     x2, 1f
+
+       /* The cpu_ops reset handler can clobber x0 - x19, x30 */
+       br      x2
+1:
+       ret
+
+#endif /* IMAGE_BL1 || IMAGE_BL31 */
+
+#if IMAGE_BL31 /* The power down core and cluster is needed only in  BL31 */
+       /*
+        * The prepare core power down function for all platforms.  After
+        * the cpu_ops pointer is retrieved from cpu_data, the corresponding
+        * pwr_dwn_core in the cpu_ops is invoked.
+        */
+       .globl  prepare_core_pwr_dwn
+func prepare_core_pwr_dwn
+       mrs     x1, tpidr_el3
+       ldr     x0, [x1, #CPU_DATA_CPU_OPS_PTR]
+#if ASM_ASSERTION
+       cmp     x0, #0
+       ASM_ASSERT(ne)
+#endif
+
+       /* Get the cpu_ops core_pwr_dwn handler */
+       ldr     x1, [x0, #CPU_PWR_DWN_CORE]
+       br      x1
+
+       /*
+        * The prepare cluster power down function for all platforms.  After
+        * the cpu_ops pointer is retrieved from cpu_data, the corresponding
+        * pwr_dwn_cluster in the cpu_ops is invoked.
+        */
+       .globl  prepare_cluster_pwr_dwn
+func prepare_cluster_pwr_dwn
+       mrs     x1, tpidr_el3
+       ldr     x0, [x1, #CPU_DATA_CPU_OPS_PTR]
+#if ASM_ASSERTION
+       cmp     x0, #0
+       ASM_ASSERT(ne)
+#endif
+
+       /* Get the cpu_ops cluster_pwr_dwn handler */
+       ldr     x1, [x0, #CPU_PWR_DWN_CLUSTER]
+       br      x1
+
+
+       /*
+        * Initializes the cpu_ops_ptr if not already initialized
+        * in cpu_data. This can be called without a runtime stack.
+        * clobbers: x0 - x6, x10
+        */
+       .globl  init_cpu_ops
+func init_cpu_ops
+       mrs     x6, tpidr_el3
+       ldr     x0, [x6, #CPU_DATA_CPU_OPS_PTR]
+       cbnz    x0, 1f
+       mov     x10, x30
+       bl      get_cpu_ops_ptr
+#if ASM_ASSERTION
+       cmp     x0, #0
+       ASM_ASSERT(ne)
+#endif
+       str     x0, [x6, #CPU_DATA_CPU_OPS_PTR]!
+
+       /*
+        * Make sure that any pre-fetched cache copies are invalidated.
+        * Ensure that we are running with cache disable else we
+        * invalidate our own update.
+        */
+#if ASM_ASSERTION
+       mrs     x1, sctlr_el3
+       tst     x1, #SCTLR_C_BIT
+       ASM_ASSERT(eq)
+#endif
+       dc      ivac, x6
+       mov x30, x10
+1:
+       ret
+#endif /* IMAGE_BL31 */
+
+#if IMAGE_BL31 && CRASH_REPORTING
+       /*
+        * The cpu specific registers which need to be reported in a crash
+        * are reported via cpu_ops cpu_reg_dump function. After a matching
+        * cpu_ops structure entry is found, the correponding cpu_reg_dump
+        * in the cpu_ops is invoked.
+        */
+       .globl  do_cpu_reg_dump
+func do_cpu_reg_dump
+       mov     x16, x30
+
+       /* Get the matching cpu_ops pointer */
+       bl      get_cpu_ops_ptr
+       cbz     x0, 1f
+
+       /* Get the cpu_ops cpu_reg_dump */
+       ldr     x2, [x0, #CPU_REG_DUMP]
+       cbz     x2, 1f
+       blr     x2
+1:
+       mov     x30, x16
+       ret
+#endif
+
+       /*
+        * The below function returns the cpu_ops structure matching the
+        * midr of the core. It reads the MIDR_EL1 and finds the matching
+        * entry in cpu_ops entries. Only the implementation and part number
+        * are used to match the entries.
+        * Return :
+        *     x0 - The matching cpu_ops pointer on Success
+        *     x0 - 0 on failure.
+        * Clobbers : x0 - x5
+        */
+       .globl  get_cpu_ops_ptr
+func get_cpu_ops_ptr
+       /* Get the cpu_ops start and end locations */
+       adr     x4, (__CPU_OPS_START__ + CPU_MIDR)
+       adr     x5, (__CPU_OPS_END__ + CPU_MIDR)
+
+       /* Initialize the return parameter */
+       mov     x0, #0
+
+       /* Read the MIDR_EL1 */
+       mrs     x2, midr_el1
+       mov_imm x3, CPU_IMPL_PN_MASK
+
+       /* Retain only the implementation and part number using mask */
+       and     w2, w2, w3
+1:
+       /* Check if we have reached end of list */
+       cmp     x4, x5
+       b.eq    error_exit
+
+       /* load the midr from the cpu_ops */
+       ldr     x1, [x4], #CPU_OPS_SIZE
+       and     w1, w1, w3
+
+       /* Check if midr matches to midr of this core */
+       cmp     w1, w2
+       b.ne    1b
+
+       /* Subtract the increment and offset to get the cpu-ops pointer */
+       sub     x0, x4, #(CPU_OPS_SIZE + CPU_MIDR)
+error_exit:
+       ret
+
+#if DEBUG
+       /*
+        * This function prints a warning message to the crash console
+        * if the CPU revision/part number does not match the errata
+        * workaround enabled in the build.
+        * Clobber: x30, x0 - x5
+        */
+.section .rodata.rev_warn_str, "aS"
+rev_warn_str:
+       .asciz "Warning: Skipping Errata workaround for non matching CPU revision number.\n"
+
+       .globl  print_revision_warning
+func print_revision_warning
+       mov     x5, x30
+       /* Ensure the console is initialized */
+       bl      plat_crash_console_init
+       /* Check if the console is initialized */
+       cbz     x0, 1f
+       /* The console is initialized */
+       adr     x4, rev_warn_str
+       bl      asm_print_str
+1:
+       ret     x5
+#endif
+
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
new file mode 100644 (file)
index 0000000..1c5512e
--- /dev/null
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 2014, 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.
+#
+
+# Cortex A57 specific optimisation to skip L1 cache flush when
+# cluster is powered down.
+SKIP_A57_L1_FLUSH_PWR_DWN      ?=0
+
+# Process SKIP_A57_L1_FLUSH_PWR_DWN flag
+$(eval $(call assert_boolean,SKIP_A57_L1_FLUSH_PWR_DWN))
+$(eval $(call add_define,SKIP_A57_L1_FLUSH_PWR_DWN))
+
+
+# CPU Errata Build flags. These should be enabled by the
+# platform if the errata needs to be applied.
+
+# Flag to apply errata 806969 during reset. This errata applies only to
+# revision r0p0 of the Cortex A57 cpu.
+ERRATA_A57_806969      ?=0
+
+# Flag to apply errata 813420 during reset. This errata applies only to
+# revision r0p0 of the Cortex A57 cpu.
+ERRATA_A57_813420      ?=0
+
+# Process ERRATA_A57_806969 flag
+$(eval $(call assert_boolean,ERRATA_A57_806969))
+$(eval $(call add_define,ERRATA_A57_806969))
+
+# Process ERRATA_A57_813420 flag
+$(eval $(call assert_boolean,ERRATA_A57_813420))
+$(eval $(call add_define,ERRATA_A57_813420))
diff --git a/lib/locks/bakery/bakery_lock_coherent.c b/lib/locks/bakery/bakery_lock_coherent.c
new file mode 100644 (file)
index 0000000..5d538ce
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bakery_lock.h>
+#include <cpu_data.h>
+#include <platform.h>
+#include <string.h>
+
+/*
+ * Functions in this file implement Bakery Algorithm for mutual exclusion with the
+ * bakery lock data structures in coherent memory.
+ *
+ * ARM architecture offers a family of exclusive access instructions to
+ * efficiently implement mutual exclusion with hardware support. However, as
+ * well as depending on external hardware, the these instructions have defined
+ * behavior only on certain memory types (cacheable and Normal memory in
+ * particular; see ARMv8 Architecture Reference Manual section B2.10). Use cases
+ * in trusted firmware are such that mutual exclusion implementation cannot
+ * expect that accesses to the lock have the specific type required by the
+ * architecture for these primitives to function (for example, not all
+ * contenders may have address translation enabled).
+ *
+ * This implementation does not use mutual exclusion primitives. It expects
+ * memory regions where the locks reside to be fully ordered and coherent
+ * (either by disabling address translation, or by assigning proper attributes
+ * when translation is enabled).
+ *
+ * Note that the ARM architecture guarantees single-copy atomicity for aligned
+ * accesses regardless of status of address translation.
+ */
+
+#define assert_bakery_entry_valid(entry, bakery) do {  \
+       assert(bakery);                                 \
+       assert(entry < BAKERY_LOCK_MAX_CPUS);           \
+} while (0)
+
+/* Convert a ticket to priority */
+#define PRIORITY(t, pos)       (((t) << 8) | (pos))
+
+
+/* Initialize Bakery Lock to reset ownership and all ticket values */
+void bakery_lock_init(bakery_lock_t *bakery)
+{
+       assert(bakery);
+
+       /* All ticket values need to be 0 */
+       memset(bakery, 0, sizeof(*bakery));
+       bakery->owner = NO_OWNER;
+}
+
+
+/* Obtain a ticket for a given CPU */
+static unsigned int bakery_get_ticket(bakery_lock_t *bakery, unsigned int me)
+{
+       unsigned int my_ticket, their_ticket;
+       unsigned int they;
+
+       /*
+        * Flag that we're busy getting our ticket. All CPUs are iterated in the
+        * order of their ordinal position to decide the maximum ticket value
+        * observed so far. Our priority is set to be greater than the maximum
+        * observed priority
+        *
+        * Note that it's possible that more than one contender gets the same
+        * ticket value. That's OK as the lock is acquired based on the priority
+        * value, not the ticket value alone.
+        */
+       my_ticket = 0;
+       bakery->entering[me] = 1;
+       for (they = 0; they < BAKERY_LOCK_MAX_CPUS; they++) {
+               their_ticket = bakery->number[they];
+               if (their_ticket > my_ticket)
+                       my_ticket = their_ticket;
+       }
+
+       /*
+        * Compute ticket; then signal to other contenders waiting for us to
+        * finish calculating our ticket value that we're done
+        */
+       ++my_ticket;
+       bakery->number[me] = my_ticket;
+       bakery->entering[me] = 0;
+
+       return my_ticket;
+}
+
+
+/*
+ * Acquire bakery lock
+ *
+ * Contending CPUs need first obtain a non-zero ticket and then calculate
+ * priority value. A contending CPU iterate over all other CPUs in the platform,
+ * which may be contending for the same lock, in the order of their ordinal
+ * position (CPU0, CPU1 and so on). A non-contending CPU will have its ticket
+ * (and priority) value as 0. The contending CPU compares its priority with that
+ * of others'. The CPU with the highest priority (lowest numerical value)
+ * acquires the lock
+ */
+void bakery_lock_get(bakery_lock_t *bakery)
+{
+       unsigned int they, me;
+       unsigned int my_ticket, my_prio, their_ticket;
+
+       me = platform_get_core_pos(read_mpidr_el1());
+
+       assert_bakery_entry_valid(me, bakery);
+
+       /* Prevent recursive acquisition */
+       assert(bakery->owner != me);
+
+       /* Get a ticket */
+       my_ticket = bakery_get_ticket(bakery, me);
+
+       /*
+        * Now that we got our ticket, compute our priority value, then compare
+        * with that of others, and proceed to acquire the lock
+        */
+       my_prio = PRIORITY(my_ticket, me);
+       for (they = 0; they < BAKERY_LOCK_MAX_CPUS; they++) {
+               if (me == they)
+                       continue;
+
+               /* Wait for the contender to get their ticket */
+               while (bakery->entering[they])
+                       ;
+
+               /*
+                * If the other party is a contender, they'll have non-zero
+                * (valid) ticket value. If they do, compare priorities
+                */
+               their_ticket = bakery->number[they];
+               if (their_ticket && (PRIORITY(their_ticket, they) < my_prio)) {
+                       /*
+                        * They have higher priority (lower value). Wait for
+                        * their ticket value to change (either release the lock
+                        * to have it dropped to 0; or drop and probably content
+                        * again for the same lock to have an even higher value)
+                        */
+                       do {
+                               wfe();
+                       } while (their_ticket == bakery->number[they]);
+               }
+       }
+
+       /* Lock acquired */
+       bakery->owner = me;
+}
+
+
+/* Release the lock and signal contenders */
+void bakery_lock_release(bakery_lock_t *bakery)
+{
+       unsigned int me = platform_get_core_pos(read_mpidr_el1());
+
+       assert_bakery_entry_valid(me, bakery);
+       assert(bakery->owner == me);
+
+       /*
+        * Release lock by resetting ownership and ticket. Then signal other
+        * waiting contenders
+        */
+       bakery->owner = NO_OWNER;
+       bakery->number[me] = 0;
+       dsb();
+       sev();
+}
diff --git a/lib/locks/bakery/bakery_lock_normal.c b/lib/locks/bakery/bakery_lock_normal.c
new file mode 100644 (file)
index 0000000..a325fd4
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bakery_lock.h>
+#include <cpu_data.h>
+#include <platform.h>
+#include <string.h>
+
+/*
+ * Functions in this file implement Bakery Algorithm for mutual exclusion with the
+ * bakery lock data structures in cacheable and Normal memory.
+ *
+ * ARM architecture offers a family of exclusive access instructions to
+ * efficiently implement mutual exclusion with hardware support. However, as
+ * well as depending on external hardware, these instructions have defined
+ * behavior only on certain memory types (cacheable and Normal memory in
+ * particular; see ARMv8 Architecture Reference Manual section B2.10). Use cases
+ * in trusted firmware are such that mutual exclusion implementation cannot
+ * expect that accesses to the lock have the specific type required by the
+ * architecture for these primitives to function (for example, not all
+ * contenders may have address translation enabled).
+ *
+ * This implementation does not use mutual exclusion primitives. It expects
+ * memory regions where the locks reside to be cacheable and Normal.
+ *
+ * Note that the ARM architecture guarantees single-copy atomicity for aligned
+ * accesses regardless of status of address translation.
+ */
+
+/* Convert a ticket to priority */
+#define PRIORITY(t, pos)       (((t) << 8) | (pos))
+
+#define CHOOSING_TICKET                0x1
+#define CHOOSING_DONE          0x0
+
+#define bakery_is_choosing(info)       (info & 0x1)
+#define bakery_ticket_number(info)     ((info >> 1) & 0x7FFF)
+#define make_bakery_data(choosing, number) \
+               (((choosing & 0x1) | (number << 1)) & 0xFFFF)
+
+/* This macro assumes that the bakery_info array is located at the offset specified */
+#define get_my_bakery_info(offset, id)         \
+       (((bakery_info_t *) (((uint8_t *)_cpu_data()) + offset)) + id)
+
+#define get_bakery_info_by_index(offset, id, ix)       \
+       (((bakery_info_t *) (((uint8_t *)_cpu_data_by_index(ix)) + offset)) + id)
+
+#define write_cache_op(addr, cached)   \
+                               do {    \
+                                       (cached ? dccvac((uint64_t)addr) :\
+                                               dcivac((uint64_t)addr));\
+                                               dsbish();\
+                               } while (0)
+
+#define read_cache_op(addr, cached)    if (cached) \
+                                           dccivac((uint64_t)addr)
+
+static unsigned int bakery_get_ticket(int id, unsigned int offset,
+                                               unsigned int me, int is_cached)
+{
+       unsigned int my_ticket, their_ticket;
+       unsigned int they;
+       bakery_info_t *my_bakery_info, *their_bakery_info;
+
+       /*
+        * Obtain a reference to the bakery information for this cpu and ensure
+        * it is not NULL.
+        */
+       my_bakery_info = get_my_bakery_info(offset, id);
+       assert(my_bakery_info);
+
+       /*
+        * Tell other contenders that we are through the bakery doorway i.e.
+        * going to allocate a ticket for this cpu.
+        */
+       my_ticket = 0;
+       my_bakery_info->lock_data = make_bakery_data(CHOOSING_TICKET, my_ticket);
+
+       write_cache_op(my_bakery_info, is_cached);
+
+       /*
+        * Iterate through the bakery information of each contender to allocate
+        * the highest ticket number for this cpu.
+        */
+       for (they = 0; they < BAKERY_LOCK_MAX_CPUS; they++) {
+               if (me == they)
+                       continue;
+
+               /*
+                * Get a reference to the other contender's bakery info and
+                * ensure that a stale copy is not read.
+                */
+               their_bakery_info = get_bakery_info_by_index(offset, id, they);
+               assert(their_bakery_info);
+
+               read_cache_op(their_bakery_info, is_cached);
+
+               /*
+                * Update this cpu's ticket number if a higher ticket number is
+                * seen
+                */
+               their_ticket = bakery_ticket_number(their_bakery_info->lock_data);
+               if (their_ticket > my_ticket)
+                       my_ticket = their_ticket;
+       }
+
+       /*
+        * Compute ticket; then signal to other contenders waiting for us to
+        * finish calculating our ticket value that we're done
+        */
+       ++my_ticket;
+       my_bakery_info->lock_data = make_bakery_data(CHOOSING_DONE, my_ticket);
+
+       write_cache_op(my_bakery_info, is_cached);
+
+       return my_ticket;
+}
+
+void bakery_lock_get(unsigned int id, unsigned int offset)
+{
+       unsigned int they, me, is_cached;
+       unsigned int my_ticket, my_prio, their_ticket;
+       bakery_info_t *their_bakery_info;
+       uint16_t their_bakery_data;
+
+       me = platform_get_core_pos(read_mpidr_el1());
+
+       is_cached = read_sctlr_el3() & SCTLR_C_BIT;
+
+       /* Get a ticket */
+       my_ticket = bakery_get_ticket(id, offset, me, is_cached);
+
+       /*
+        * Now that we got our ticket, compute our priority value, then compare
+        * with that of others, and proceed to acquire the lock
+        */
+       my_prio = PRIORITY(my_ticket, me);
+       for (they = 0; they < BAKERY_LOCK_MAX_CPUS; they++) {
+               if (me == they)
+                       continue;
+
+               /*
+                * Get a reference to the other contender's bakery info and
+                * ensure that a stale copy is not read.
+                */
+               their_bakery_info = get_bakery_info_by_index(offset, id, they);
+               assert(their_bakery_info);
+               read_cache_op(their_bakery_info, is_cached);
+
+               their_bakery_data = their_bakery_info->lock_data;
+
+               /* Wait for the contender to get their ticket */
+               while (bakery_is_choosing(their_bakery_data)) {
+                       read_cache_op(their_bakery_info, is_cached);
+                       their_bakery_data = their_bakery_info->lock_data;
+               }
+
+               /*
+                * If the other party is a contender, they'll have non-zero
+                * (valid) ticket value. If they do, compare priorities
+                */
+               their_ticket = bakery_ticket_number(their_bakery_data);
+               if (their_ticket && (PRIORITY(their_ticket, they) < my_prio)) {
+                       /*
+                        * They have higher priority (lower value). Wait for
+                        * their ticket value to change (either release the lock
+                        * to have it dropped to 0; or drop and probably content
+                        * again for the same lock to have an even higher value)
+                        */
+                       do {
+                               wfe();
+                               read_cache_op(their_bakery_info, is_cached);
+                       } while (their_ticket
+                               == bakery_ticket_number(their_bakery_info->lock_data));
+               }
+       }
+}
+
+void bakery_lock_release(unsigned int id, unsigned int offset)
+{
+       bakery_info_t *my_bakery_info;
+       unsigned int is_cached = read_sctlr_el3() & SCTLR_C_BIT;
+
+       my_bakery_info = get_my_bakery_info(offset, id);
+       my_bakery_info->lock_data = 0;
+       write_cache_op(my_bakery_info, is_cached);
+       sev();
+}
diff --git a/lib/locks/exclusive/spinlock.S b/lib/locks/exclusive/spinlock.S
new file mode 100644 (file)
index 0000000..5eae2b0
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm_macros.S>
+
+       .globl  spin_lock
+       .globl  spin_unlock
+
+
+func spin_lock
+       mov     w2, #1
+       sevl
+l1:    wfe
+l2:    ldaxr   w1, [x0]
+       cbnz    w1, l1
+       stxr    w1, w2, [x0]
+       cbnz    w1, l2
+       ret
+
+
+func spin_unlock
+       stlr    wzr, [x0]
+       ret
diff --git a/lib/semihosting/aarch64/semihosting_call.S b/lib/semihosting/aarch64/semihosting_call.S
new file mode 100644 (file)
index 0000000..e6a9675
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm_macros.S>
+
+       .globl  semihosting_call
+
+func semihosting_call
+       hlt     #0xf000
+       ret
diff --git a/lib/semihosting/semihosting.c b/lib/semihosting/semihosting.c
new file mode 100644 (file)
index 0000000..849ec12
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <semihosting.h>
+#include <string.h>
+
+#ifndef SEMIHOSTING_SUPPORTED
+#define SEMIHOSTING_SUPPORTED  1
+#endif
+
+long semihosting_call(unsigned long operation,
+                       void *system_block_address);
+
+typedef struct {
+       const char *file_name;
+       unsigned long mode;
+       size_t name_length;
+} smh_file_open_block_t;
+
+typedef struct {
+       long handle;
+       uintptr_t buffer;
+       size_t length;
+} smh_file_read_write_block_t;
+
+typedef struct {
+       long handle;
+       ssize_t location;
+} smh_file_seek_block_t;
+
+typedef struct {
+       char *command_line;
+       size_t command_length;
+} smh_system_block_t;
+
+long semihosting_connection_supported(void)
+{
+       return SEMIHOSTING_SUPPORTED;
+}
+
+long semihosting_file_open(const char *file_name, size_t mode)
+{
+       smh_file_open_block_t open_block;
+
+       open_block.file_name = file_name;
+       open_block.mode = mode;
+       open_block.name_length = strlen(file_name);
+
+       return semihosting_call(SEMIHOSTING_SYS_OPEN,
+                               (void *) &open_block);
+}
+
+long semihosting_file_seek(long file_handle, ssize_t offset)
+{
+       smh_file_seek_block_t seek_block;
+       long result;
+
+       seek_block.handle = file_handle;
+       seek_block.location = offset;
+
+       result = semihosting_call(SEMIHOSTING_SYS_SEEK,
+                                 (void *) &seek_block);
+
+       if (result)
+               result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0);
+
+       return result;
+}
+
+long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer)
+{
+       smh_file_read_write_block_t read_block;
+       long result = -EINVAL;
+
+       if ((length == NULL) || (buffer == (uintptr_t)NULL))
+               return result;
+
+       read_block.handle = file_handle;
+       read_block.buffer = buffer;
+       read_block.length = *length;
+
+       result = semihosting_call(SEMIHOSTING_SYS_READ,
+                                 (void *) &read_block);
+
+       if (result == *length) {
+               return -EINVAL;
+       } else if (result < *length) {
+               *length -= result;
+               return 0;
+       } else
+               return result;
+}
+
+long semihosting_file_write(long file_handle,
+                           size_t *length,
+                           const uintptr_t buffer)
+{
+       smh_file_read_write_block_t write_block;
+
+       if ((length == NULL) || (buffer == (uintptr_t)NULL))
+               return -EINVAL;
+
+       write_block.handle = file_handle;
+       write_block.buffer = (uintptr_t)buffer; /* cast away const */
+       write_block.length = *length;
+
+       *length = semihosting_call(SEMIHOSTING_SYS_WRITE,
+                                  (void *) &write_block);
+
+       return *length;
+}
+
+long semihosting_file_close(long file_handle)
+{
+       return semihosting_call(SEMIHOSTING_SYS_CLOSE,
+                               (void *) &file_handle);
+}
+
+long semihosting_file_length(long file_handle)
+{
+       return semihosting_call(SEMIHOSTING_SYS_FLEN,
+                               (void *) &file_handle);
+}
+
+char semihosting_read_char(void)
+{
+       return semihosting_call(SEMIHOSTING_SYS_READC, NULL);
+}
+
+void semihosting_write_char(char character)
+{
+       semihosting_call(SEMIHOSTING_SYS_WRITEC, (void *) &character);
+}
+
+void semihosting_write_string(char *string)
+{
+       semihosting_call(SEMIHOSTING_SYS_WRITE0, (void *) string);
+}
+
+long semihosting_system(char *command_line)
+{
+       smh_system_block_t system_block;
+
+       system_block.command_line = command_line;
+       system_block.command_length = strlen(command_line);
+
+       return semihosting_call(SEMIHOSTING_SYS_SYSTEM,
+                               (void *) &system_block);
+}
+
+long semihosting_get_flen(const char *file_name)
+{
+       long file_handle;
+       size_t length;
+
+       assert(semihosting_connection_supported());
+
+       file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB);
+       if (file_handle == -1)
+               return file_handle;
+
+       /* Find the length of the file */
+       length = semihosting_file_length(file_handle);
+
+       return semihosting_file_close(file_handle) ? -1 : length;
+}
+
+long semihosting_download_file(const char *file_name,
+                             size_t buf_size,
+                             uintptr_t buf)
+{
+       long ret = -EINVAL;
+       size_t length;
+       long file_handle;
+
+       /* Null pointer check */
+       if (!buf)
+               return ret;
+
+       assert(semihosting_connection_supported());
+
+       file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB);
+       if (file_handle == -1)
+               return ret;
+
+       /* Find the actual length of the file */
+       length = semihosting_file_length(file_handle);
+       if (length == -1)
+               goto semihosting_fail;
+
+       /* Signal error if we do not have enough space for the file */
+       if (length > buf_size)
+               goto semihosting_fail;
+
+       /*
+        * A successful read will return 0 in which case we pass back
+        * the actual number of bytes read. Else we pass a negative
+        * value indicating an error.
+        */
+       ret = semihosting_file_read(file_handle, &length, buf);
+       if (ret)
+               goto semihosting_fail;
+       else
+               ret = length;
+
+semihosting_fail:
+       semihosting_file_close(file_handle);
+       return ret;
+}
diff --git a/lib/stdlib/abort.c b/lib/stdlib/abort.c
new file mode 100644 (file)
index 0000000..862bf9c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+
+/*
+ * This is a basic implementation. This could be improved.
+ */
+void abort (void)
+{
+       ERROR("ABORT\n");
+       panic();
+}
diff --git a/lib/stdlib/assert.c b/lib/stdlib/assert.c
new file mode 100644 (file)
index 0000000..90a1afe
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+
+/*
+ * This is a basic implementation. This could be improved.
+ */
+void __assert (const char *function, const char *file, unsigned int line,
+               const char *assertion)
+{
+       tf_printf("ASSERT: %s <%d> : %s\n", function, line, assertion);
+       while(1);
+}
diff --git a/lib/stdlib/exit.c b/lib/stdlib/exit.c
new file mode 100644 (file)
index 0000000..3e77591
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+
+void exit(int v)
+{
+       ERROR("EXIT\n");
+       panic();
+}
diff --git a/lib/stdlib/mem.c b/lib/stdlib/mem.c
new file mode 100644 (file)
index 0000000..f1f335a
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h> /* size_t */
+
+/*
+ * Fill @count bytes of memory pointed to by @dst with @val
+ */
+void *memset(void *dst, int val, size_t count)
+{
+       char *ptr = dst;
+
+       while (count--)
+               *ptr++ = val;
+
+       return dst;
+}
+
+/*
+ * Compare @len bytes of @s1 and @s2
+ */
+int memcmp(const void *s1, const void *s2, size_t len)
+{
+       const char *s = s1;
+       const char *d = s2;
+       char dc;
+       char sc;
+
+       while (len--) {
+               sc = *s++;
+               dc = *d++;
+               if (sc - dc)
+                       return (sc - dc);
+       }
+
+       return 0;
+}
+
+/*
+ * Copy @len bytes from @src to @dst
+ */
+void *memcpy(void *dst, const void *src, size_t len)
+{
+       const char *s = src;
+       char *d = dst;
+
+       while (len--)
+               *d++ = *s++;
+
+       return dst;
+}
+
+/*
+ * Move @len bytes from @src to @dst
+ */
+void *memmove(void *dst, const void *src, size_t len)
+{
+       /*
+        * The following test makes use of unsigned arithmetic overflow to
+        * more efficiently test the condition !(src <= dst && dst < str+len).
+        * It also avoids the situation where the more explicit test would give
+        * incorrect results were the calculation str+len to overflow (though
+        * that issue is probably moot as such usage is probably undefined
+        * behaviour and a bug anyway.
+        */
+       if ((size_t)dst - (size_t)src >= len) {
+               /* destination not in source data, so can safely use memcpy */
+               return memcpy(dst, src, len);
+       } else {
+               /* copy backwards... */
+               const char *end = dst;
+               const char *s = (const char *)src + len;
+               char *d = (char *)dst + len;
+               while (d != end)
+                       *--d = *--s;
+       }
+       return dst;
+}
+
+/*
+ * Scan @len bytes of @src for value @c
+ */
+void *memchr(const void *src, int c, size_t len)
+{
+       const char *s = src;
+
+       while (len--) {
+               if (*s == c)
+                       return (void *) s;
+               s++;
+       }
+
+       return NULL;
+}
diff --git a/lib/stdlib/printf.c b/lib/stdlib/printf.c
new file mode 100644 (file)
index 0000000..323ec0f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* Choose max of 128 chars for now. */
+#define PRINT_BUFFER_SIZE 128
+int printf(const char *fmt, ...)
+{
+       va_list args;
+       char buf[PRINT_BUFFER_SIZE];
+       int count;
+
+       va_start(args, fmt);
+       vsnprintf(buf, sizeof(buf) - 1, fmt, args);
+       va_end(args);
+
+       /* Use putchar directly as 'puts()' adds a newline. */
+       buf[PRINT_BUFFER_SIZE - 1] = '\0';
+       count = 0;
+       while (buf[count])
+       {
+               if (putchar(buf[count]) != EOF) {
+                       count++;
+               } else {
+                       count = EOF;
+                       break;
+               }
+       }
+
+       return count;
+}
diff --git a/lib/stdlib/putchar.c b/lib/stdlib/putchar.c
new file mode 100644 (file)
index 0000000..85e4fbd
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <console.h>
+
+/* Putchar() should either return the character printed or EOF in case of error.
+ * Our current console_putc() function assumes success and returns the
+ * character. Write all other printing functions in terms of putchar(), if
+ * possible, so they all benefit when this is improved.
+ */
+int putchar(int c)
+{
+       int res;
+       if (console_putc((unsigned char)c) >= 0)
+               res = c;
+       else
+               res = EOF;
+
+       return res;
+}
diff --git a/lib/stdlib/puts.c b/lib/stdlib/puts.c
new file mode 100644 (file)
index 0000000..ca88fc5
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+int puts(const char *s)
+{
+       int count = 0;
+       while(*s)
+       {
+               if (putchar(*s++) != EOF) {
+                       count++;
+               } else {
+                       count = EOF;
+                       break;
+               }
+       }
+
+       /* According to the puts(3) manpage, the function should write a
+        * trailing newline.
+        */
+       if ((count != EOF) && (putchar('\n') != EOF))
+               count++;
+       else
+               count = EOF;
+
+       return count;
+}
diff --git a/lib/stdlib/sscanf.c b/lib/stdlib/sscanf.c
new file mode 100644 (file)
index 0000000..e9f5c4a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+/*
+ * TODO: This is not a real implementation of the sscanf() function. It just
+ * returns the number of expected arguments based on the number of '%' found
+ * in the format string.
+ */
+int
+sscanf(const char *__restrict str, char const *__restrict fmt, ...)
+{
+       int ret = 0;
+
+       while (*fmt != '\0') {
+               if (*fmt++ == '%') {
+                       ret++;
+               }
+       }
+
+       return ret;
+}
diff --git a/lib/stdlib/std.c b/lib/stdlib/std.c
new file mode 100644 (file)
index 0000000..5f6ef75
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* Include the various implemented functions */
+#include "abort.c"
+#include "assert.c"
+#include "exit.c"
+#include "mem.c"
+#include "printf.c"
+#include "putchar.c"
+#include "puts.c"
+#include "sscanf.c"
+#include "strchr.c"
+#include "strcmp.c"
+#include "strlen.c"
+#include "strncmp.c"
+#include "subr_prf.c"
diff --git a/lib/stdlib/strchr.c b/lib/stdlib/strchr.c
new file mode 100644 (file)
index 0000000..4247dcd
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions copyright (c) 2013-2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <sys/cdefs.h>
+#include <stddef.h>
+#include <string.h>
+
+char *
+strchr(const char *p, int ch)
+{
+       char c;
+
+       c = ch;
+       for (;; ++p) {
+               if (*p == c)
+                       return ((char *)p);
+               if (*p == '\0')
+                       return (NULL);
+       }
+       /* NOTREACHED */
+}
diff --git a/lib/stdlib/strcmp.c b/lib/stdlib/strcmp.c
new file mode 100644 (file)
index 0000000..bb86e0f
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions copyright (c) 2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/ctype.h>
+#include <string.h>
+
+/*
+ * Compare strings.
+ */
+int
+strcmp(const char *s1, const char *s2)
+{
+       while (*s1 == *s2++)
+               if (*s1++ == '\0')
+                       return 0;
+       return *(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1);
+}
+
+int
+strcasecmp(const char *s1, const char *s2)
+{
+       const unsigned char *us1 = (const unsigned char *)s1;
+       const unsigned char *us2 = (const unsigned char *)s2;
+
+       while (tolower(*us1) == tolower(*us2)) {
+               if (*us1++ == '\0')
+                       return 0;
+               us2++;
+       }
+       return tolower(*us1) - tolower(*us2);
+}
diff --git a/lib/stdlib/strlen.c b/lib/stdlib/strlen.c
new file mode 100644 (file)
index 0000000..23c3d39
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions copyright (c) 2009-2014, ARM Limited and Contributors. All rights reserved.
+ */
+
+#include <stddef.h>
+
+size_t
+strlen(str)
+       const char *str;
+{
+       register const char *s;
+
+       for (s = str; *s; ++s);
+       return(s - str);
+}
diff --git a/lib/stdlib/strncmp.c b/lib/stdlib/strncmp.c
new file mode 100644 (file)
index 0000000..f45f4a2
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions copyright (c) 2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <sys/cdefs.h>
+#include <string.h>
+
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+
+       if (n == 0)
+               return 0;
+       do {
+               if (*s1 != *s2++)
+                       return (*(const unsigned char *)s1 -
+                               *(const unsigned char *)(s2 - 1));
+               if (*s1++ == '\0')
+                       break;
+       } while (--n != 0);
+       return 0;
+}
diff --git a/lib/stdlib/subr_prf.c b/lib/stdlib/subr_prf.c
new file mode 100644 (file)
index 0000000..c103562
--- /dev/null
@@ -0,0 +1,548 @@
+/*-
+ * Copyright (c) 1986, 1988, 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)subr_prf.c  8.3 (Berkeley) 1/21/94
+ */
+
+/*
+ * Portions copyright (c) 2009-2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+
+typedef unsigned char u_char;
+typedef unsigned int u_int;
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+typedef unsigned long u_long;
+typedef unsigned short u_short;
+
+static inline int imax(int a, int b) { return (a > b ? a : b); }
+
+/*
+ * Note that stdarg.h and the ANSI style va_start macro is used for both
+ * ANSI and traditional C compilers.
+ */
+
+#define TOCONS 0x01
+#define TOTTY  0x02
+#define TOLOG  0x04
+
+/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
+#define MAXNBUF        (sizeof(intmax_t) * 8 + 1)
+
+struct putchar_arg {
+       int     flags;
+       int     pri;
+       struct  tty *tty;
+       char    *p_bufr;
+       size_t  n_bufr;
+       char    *p_next;
+       size_t  remain;
+};
+
+struct snprintf_arg {
+       char    *str;
+       size_t  remain;
+};
+
+extern int log_open;
+
+static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
+static void  snprintf_func(int ch, void *arg);
+static int kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap);
+
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+
+static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+#define hex2ascii(hex) (hex2ascii_data[hex])
+
+/*
+ * Scaled down version of sprintf(3).
+ */
+int
+sprintf(char *buf, const char *cfmt, ...)
+{
+       int retval;
+       va_list ap;
+
+       va_start(ap, cfmt);
+       retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
+       buf[retval] = '\0';
+       va_end(ap);
+       return (retval);
+}
+
+/*
+ * Scaled down version of vsprintf(3).
+ */
+int
+vsprintf(char *buf, const char *cfmt, va_list ap)
+{
+       int retval;
+
+       retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
+       buf[retval] = '\0';
+       return (retval);
+}
+
+/*
+ * Scaled down version of snprintf(3).
+ */
+int
+snprintf(char *str, size_t size, const char *format, ...)
+{
+       int retval;
+       va_list ap;
+
+       va_start(ap, format);
+       retval = vsnprintf(str, size, format, ap);
+       va_end(ap);
+       return(retval);
+}
+
+/*
+ * Scaled down version of vsnprintf(3).
+ */
+int
+vsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+       struct snprintf_arg info;
+       int retval;
+
+       info.str = str;
+       info.remain = size;
+       retval = kvprintf(format, snprintf_func, &info, 10, ap);
+       if (info.remain >= 1)
+               *info.str++ = '\0';
+       return (retval);
+}
+
+static void
+snprintf_func(int ch, void *arg)
+{
+       struct snprintf_arg *const info = arg;
+
+       if (info->remain >= 2) {
+               *info->str++ = ch;
+               info->remain--;
+       }
+}
+
+
+/*
+ * Kernel version which takes radix argument vsnprintf(3).
+ */
+int
+vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
+{
+       struct snprintf_arg info;
+       int retval;
+
+       info.str = str;
+       info.remain = size;
+       retval = kvprintf(format, snprintf_func, &info, radix, ap);
+       if (info.remain >= 1)
+               *info.str++ = '\0';
+       return (retval);
+}
+
+
+/*
+ * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
+ * order; return an optional length and a pointer to the last character
+ * written in the buffer (i.e., the first character of the string).
+ * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
+ */
+static char *
+ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
+{
+       char *p, c;
+
+       p = nbuf;
+       *p = '\0';
+       do {
+               c = hex2ascii(num % base);
+               *++p = upper ? toupper(c) : c;
+       } while (num /= base);
+       if (lenp)
+               *lenp = p - nbuf;
+       return (p);
+}
+
+/*
+ * Scaled down version of printf(3).
+ *
+ * Two additional formats:
+ *
+ * The format %b is supported to decode error registers.
+ * Its usage is:
+ *
+ *     printf("reg=%b\n", regval, "<base><arg>*");
+ *
+ * where <base> is the output base expressed as a control character, e.g.
+ * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
+ * the first of which gives the bit number to be inspected (origin 1), and
+ * the next characters (up to a control character, i.e. a character <= 32),
+ * give the name of the register.  Thus:
+ *
+ *     kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
+ *
+ * would produce output:
+ *
+ *     reg=3<BITTWO,BITONE>
+ *
+ * XXX:  %D  -- Hexdump, takes pointer and separator string:
+ *             ("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
+ *             ("%*D", len, ptr, " " -> XX XX XX XX ...
+ */
+int
+kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
+{
+#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
+       char nbuf[MAXNBUF];
+       char *d;
+       const char *p, *percent, *q;
+       u_char *up;
+       int ch, n;
+       uintmax_t num;
+       int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
+       int cflag, hflag, jflag, tflag, zflag;
+       int dwidth, upper;
+       char padc;
+       int stop = 0, retval = 0;
+
+       num = 0;
+       if (!func)
+               d = (char *) arg;
+       else
+               d = NULL;
+
+       if (fmt == NULL)
+               fmt = "(fmt null)\n";
+
+       if (radix < 2 || radix > 36)
+               radix = 10;
+
+       for (;;) {
+               padc = ' ';
+               width = 0;
+               while ((ch = (u_char)*fmt++) != '%' || stop) {
+                       if (ch == '\0')
+                               return (retval);
+                       PCHAR(ch);
+               }
+               percent = fmt - 1;
+               qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
+               sign = 0; dot = 0; dwidth = 0; upper = 0;
+               cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
+reswitch:      switch (ch = (u_char)*fmt++) {
+               case '.':
+                       dot = 1;
+                       goto reswitch;
+               case '#':
+                       sharpflag = 1;
+                       goto reswitch;
+               case '+':
+                       sign = 1;
+                       goto reswitch;
+               case '-':
+                       ladjust = 1;
+                       goto reswitch;
+               case '%':
+                       PCHAR(ch);
+                       break;
+               case '*':
+                       if (!dot) {
+                               width = va_arg(ap, int);
+                               if (width < 0) {
+                                       ladjust = !ladjust;
+                                       width = -width;
+                               }
+                       } else {
+                               dwidth = va_arg(ap, int);
+                       }
+                       goto reswitch;
+               case '0':
+                       if (!dot) {
+                               padc = '0';
+                               goto reswitch;
+                       }
+               case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                               for (n = 0;; ++fmt) {
+                                       n = n * 10 + ch - '0';
+                                       ch = *fmt;
+                                       if (ch < '0' || ch > '9')
+                                               break;
+                               }
+                       if (dot)
+                               dwidth = n;
+                       else
+                               width = n;
+                       goto reswitch;
+               case 'b':
+                       num = (u_int)va_arg(ap, int);
+                       p = va_arg(ap, char *);
+                       for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
+                               PCHAR(*q--);
+
+                       if (num == 0)
+                               break;
+
+                       for (tmp = 0; *p;) {
+                               n = *p++;
+                               if (num & (1 << (n - 1))) {
+                                       PCHAR(tmp ? ',' : '<');
+                                       for (; (n = *p) > ' '; ++p)
+                                               PCHAR(n);
+                                       tmp = 1;
+                               } else
+                                       for (; *p > ' '; ++p)
+                                               continue;
+                       }
+                       if (tmp)
+                               PCHAR('>');
+                       break;
+               case 'c':
+                       PCHAR(va_arg(ap, int));
+                       break;
+               case 'D':
+                       up = va_arg(ap, u_char *);
+                       p = va_arg(ap, char *);
+                       if (!width)
+                               width = 16;
+                       while(width--) {
+                               PCHAR(hex2ascii(*up >> 4));
+                               PCHAR(hex2ascii(*up & 0x0f));
+                               up++;
+                               if (width)
+                                       for (q=p;*q;q++)
+                                               PCHAR(*q);
+                       }
+                       break;
+               case 'd':
+               case 'i':
+                       base = 10;
+                       sign = 1;
+                       goto handle_sign;
+               case 'h':
+                       if (hflag) {
+                               hflag = 0;
+                               cflag = 1;
+                       } else
+                               hflag = 1;
+                       goto reswitch;
+               case 'j':
+                       jflag = 1;
+                       goto reswitch;
+               case 'l':
+                       if (lflag) {
+                               lflag = 0;
+                               qflag = 1;
+                       } else
+                               lflag = 1;
+                       goto reswitch;
+               case 'n':
+                       if (jflag)
+                               *(va_arg(ap, intmax_t *)) = retval;
+                       else if (qflag)
+                               *(va_arg(ap, quad_t *)) = retval;
+                       else if (lflag)
+                               *(va_arg(ap, long *)) = retval;
+                       else if (zflag)
+                               *(va_arg(ap, size_t *)) = retval;
+                       else if (hflag)
+                               *(va_arg(ap, short *)) = retval;
+                       else if (cflag)
+                               *(va_arg(ap, char *)) = retval;
+                       else
+                               *(va_arg(ap, int *)) = retval;
+                       break;
+               case 'o':
+                       base = 8;
+                       goto handle_nosign;
+               case 'p':
+                       base = 16;
+                       sharpflag = (width == 0);
+                       sign = 0;
+                       num = (uintptr_t)va_arg(ap, void *);
+                       goto number;
+               case 'q':
+                       qflag = 1;
+                       goto reswitch;
+               case 'r':
+                       base = radix;
+                       if (sign)
+                               goto handle_sign;
+                       goto handle_nosign;
+               case 's':
+                       p = va_arg(ap, char *);
+                       if (p == NULL)
+                               p = "(null)";
+                       if (!dot)
+                               n = strlen (p);
+                       else
+                               for (n = 0; n < dwidth && p[n]; n++)
+                                       continue;
+
+                       width -= n;
+
+                       if (!ladjust && width > 0)
+                               while (width--)
+                                       PCHAR(padc);
+                       while (n--)
+                               PCHAR(*p++);
+                       if (ladjust && width > 0)
+                               while (width--)
+                                       PCHAR(padc);
+                       break;
+               case 't':
+                       tflag = 1;
+                       goto reswitch;
+               case 'u':
+                       base = 10;
+                       goto handle_nosign;
+               case 'X':
+                       upper = 1;
+               case 'x':
+                       base = 16;
+                       goto handle_nosign;
+               case 'y':
+                       base = 16;
+                       sign = 1;
+                       goto handle_sign;
+               case 'z':
+                       zflag = 1;
+                       goto reswitch;
+handle_nosign:
+                       sign = 0;
+                       if (jflag)
+                               num = va_arg(ap, uintmax_t);
+                       else if (qflag)
+                               num = va_arg(ap, u_quad_t);
+                       else if (tflag)
+                               num = va_arg(ap, ptrdiff_t);
+                       else if (lflag)
+                               num = va_arg(ap, u_long);
+                       else if (zflag)
+                               num = va_arg(ap, size_t);
+                       else if (hflag)
+                               num = (u_short)va_arg(ap, int);
+                       else if (cflag)
+                               num = (u_char)va_arg(ap, int);
+                       else
+                               num = va_arg(ap, u_int);
+                       goto number;
+handle_sign:
+                       if (jflag)
+                               num = va_arg(ap, intmax_t);
+                       else if (qflag)
+                               num = va_arg(ap, quad_t);
+                       else if (tflag)
+                               num = va_arg(ap, ptrdiff_t);
+                       else if (lflag)
+                               num = va_arg(ap, long);
+                       else if (zflag)
+                               num = va_arg(ap, ssize_t);
+                       else if (hflag)
+                               num = (short)va_arg(ap, int);
+                       else if (cflag)
+                               num = (char)va_arg(ap, int);
+                       else
+                               num = va_arg(ap, int);
+number:
+                       if (sign && (intmax_t)num < 0) {
+                               neg = 1;
+                               num = -(intmax_t)num;
+                       }
+                       p = ksprintn(nbuf, num, base, &n, upper);
+                       tmp = 0;
+                       if (sharpflag && num != 0) {
+                               if (base == 8)
+                                       tmp++;
+                               else if (base == 16)
+                                       tmp += 2;
+                       }
+                       if (neg)
+                               tmp++;
+
+                       if (!ladjust && padc == '0')
+                               dwidth = width - tmp;
+                       width -= tmp + imax(dwidth, n);
+                       dwidth -= n;
+                       if (!ladjust)
+                               while (width-- > 0)
+                                       PCHAR(' ');
+                       if (neg)
+                               PCHAR('-');
+                       if (sharpflag && num != 0) {
+                               if (base == 8) {
+                                       PCHAR('0');
+                               } else if (base == 16) {
+                                       PCHAR('0');
+                                       PCHAR('x');
+                               }
+                       }
+                       while (dwidth-- > 0)
+                               PCHAR('0');
+
+                       while (*p)
+                               PCHAR(*p--);
+
+                       if (ladjust)
+                               while (width-- > 0)
+                                       PCHAR(' ');
+
+                       break;
+               default:
+                       while (percent < fmt)
+                               PCHAR(*percent++);
+                       /*
+                        * Since we ignore an formatting argument it is no 
+                        * longer safe to obey the remaining formatting
+                        * arguments as the arguments will no longer match
+                        * the format specs.
+                        */
+                       stop = 1;
+                       break;
+               }
+       }
+#undef PCHAR
+}
diff --git a/license.md b/license.md
new file mode 100644 (file)
index 0000000..941b741
--- /dev/null
@@ -0,0 +1,26 @@
+Copyright (c) 2013-2014, 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.
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
new file mode 100644 (file)
index 0000000..90574fd
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <xlat_tables.h>
+
+/*
+ * The following 2 platform setup functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak bl31_plat_enable_mmu
+#pragma weak bl32_plat_enable_mmu
+
+void bl31_plat_enable_mmu(uint32_t flags)
+{
+       enable_mmu_el3(flags);
+}
+
+void bl32_plat_enable_mmu(uint32_t flags)
+{
+       enable_mmu_el1(flags);
+}
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
new file mode 100644 (file)
index 0000000..c236fd7
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+
+       .weak   platform_get_core_pos
+       .weak   platform_check_mpidr
+       .weak   plat_report_exception
+       .weak   plat_crash_console_init
+       .weak   plat_crash_console_putc
+       .weak   plat_reset_handler
+       .weak   plat_disable_acp
+
+       /* -----------------------------------------------------
+        *  int platform_get_core_pos(int mpidr);
+        *  With this function: CorePos = (ClusterId * 4) +
+        *                                CoreId
+        * -----------------------------------------------------
+        */
+func platform_get_core_pos
+       and     x1, x0, #MPIDR_CPU_MASK
+       and     x0, x0, #MPIDR_CLUSTER_MASK
+       add     x0, x1, x0, LSR #6
+       ret
+
+       /* -----------------------------------------------------
+        * Placeholder function which should be redefined by
+        * each platform.
+        * -----------------------------------------------------
+        */
+func platform_check_mpidr
+       mov     x0, xzr
+       ret
+
+       /* -----------------------------------------------------
+        * Placeholder function which should be redefined by
+        * each platform.
+        * -----------------------------------------------------
+        */
+func plat_report_exception
+       ret
+
+       /* -----------------------------------------------------
+        * Placeholder function which should be redefined by
+        * each platform.
+        * -----------------------------------------------------
+        */
+func plat_crash_console_init
+       mov     x0, #0
+       ret
+
+       /* -----------------------------------------------------
+        * Placeholder function which should be redefined by
+        * each platform.
+        * -----------------------------------------------------
+        */
+func plat_crash_console_putc
+       ret
+
+       /* -----------------------------------------------------
+        * Placeholder function which should be redefined by
+        * each platform. This function should preserve x10.
+        * -----------------------------------------------------
+        */
+func plat_reset_handler
+       ret
+
+       /* -----------------------------------------------------
+        * Placeholder function which should be redefined by
+        * each platform. This function is allowed to use
+        * registers x0 - x17.
+        * -----------------------------------------------------
+        */
+func plat_disable_acp
+       ret
diff --git a/plat/common/aarch64/platform_mp_stack.S b/plat/common/aarch64/platform_mp_stack.S
new file mode 100644 (file)
index 0000000..8eb1aa6
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+
+       .local  platform_normal_stacks
+       .weak   platform_set_stack
+       .weak   platform_get_stack
+
+
+       /* -----------------------------------------------------
+        * unsigned long platform_get_stack (unsigned long mpidr)
+        *
+        * For a given CPU, this function returns the stack
+        * pointer for a stack allocated in device memory.
+        * -----------------------------------------------------
+        */
+func platform_get_stack
+       mov x10, x30 // lr
+       get_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+       ret x10
+
+       /* -----------------------------------------------------
+        * void platform_set_stack (unsigned long mpidr)
+        *
+        * For a given CPU, this function sets the stack pointer
+        * to a stack allocated in normal memory.
+        * -----------------------------------------------------
+        */
+func platform_set_stack
+       mov x9, x30 // lr
+       bl  platform_get_stack
+       mov sp, x0
+       ret x9
+
+       /* -----------------------------------------------------
+        * Per-cpu stacks in normal memory. Each cpu gets a
+        * stack of PLATFORM_STACK_SIZE bytes.
+        * -----------------------------------------------------
+        */
+declare_stack platform_normal_stacks, tzfw_normal_stacks, \
+               PLATFORM_STACK_SIZE, PLATFORM_CORE_COUNT
diff --git a/plat/common/aarch64/platform_up_stack.S b/plat/common/aarch64/platform_up_stack.S
new file mode 100644 (file)
index 0000000..73b74b2
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+
+       .local  platform_normal_stacks
+       .globl  platform_set_stack
+       .globl  platform_get_stack
+
+       /* -----------------------------------------------------
+        * unsigned long platform_get_stack (unsigned long)
+        *
+        * For cold-boot BL images, only the primary CPU needs a
+        * stack. This function returns the stack pointer for a
+        * stack allocated in device memory.
+        * -----------------------------------------------------
+        */
+func platform_get_stack
+       get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+       ret
+
+       /* -----------------------------------------------------
+        * void platform_set_stack (unsigned long)
+        *
+        * For cold-boot BL images, only the primary CPU needs a
+        * stack. This function sets the stack pointer to a stack
+        * allocated in normal memory.
+        * -----------------------------------------------------
+        */
+func platform_set_stack
+       get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+       mov sp, x0
+       ret
+
+       /* -----------------------------------------------------
+        * Single cpu stack in normal memory.
+        * Used for C code during boot, PLATFORM_STACK_SIZE bytes
+        * are allocated
+        * -----------------------------------------------------
+        */
+declare_stack platform_normal_stacks, tzfw_normal_stacks, \
+               PLATFORM_STACK_SIZE, 1
diff --git a/plat/common/plat_gic.c b/plat/common/plat_gic.c
new file mode 100644 (file)
index 0000000..f736e55
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arm_gic.h>
+
+/*
+ * The following platform GIC functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak plat_ic_get_pending_interrupt_type
+#pragma weak plat_ic_acknowledge_interrupt
+#pragma weak plat_ic_get_interrupt_type
+#pragma weak plat_ic_end_of_interrupt
+#pragma weak plat_interrupt_type_to_line
+
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+       return arm_gic_get_pending_interrupt_id();
+}
+
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+       return arm_gic_get_pending_interrupt_type();
+}
+
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+       return arm_gic_acknowledge_interrupt();
+}
+
+uint32_t plat_ic_get_interrupt_type(uint32_t id)
+{
+       return arm_gic_get_interrupt_type(id);
+}
+
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+       arm_gic_end_of_interrupt(id);
+}
+
+uint32_t plat_interrupt_type_to_line(uint32_t type,
+                               uint32_t security_state)
+{
+       return arm_gic_interrupt_type_to_line(type, security_state);
+}
diff --git a/plat/fvp/aarch64/fvp_common.c b/plat/fvp/aarch64/fvp_common.c
new file mode 100644 (file)
index 0000000..d89e1e6
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <bl_common.h>
+#include <cci400.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_config.h>
+#include <xlat_tables.h>
+#include "../fvp_def.h"
+
+/*******************************************************************************
+ * plat_config holds the characteristics of the differences between the three
+ * FVP platforms (Base, A53_A57 & Foundation). It will be populated during cold
+ * boot at each boot stage by the primary before enabling the MMU (to allow cci
+ * configuration) & used thereafter. Each BL will have its own copy to allow
+ * independent operation.
+ ******************************************************************************/
+plat_config_t plat_config;
+
+#define MAP_SHARED_RAM MAP_REGION_FLAT(FVP_SHARED_MEM_BASE,            \
+                                       FVP_SHARED_MEM_SIZE,            \
+                                       MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_FLASH0     MAP_REGION_FLAT(FLASH0_BASE,                    \
+                                       FLASH0_SIZE,                    \
+                                       MT_MEMORY | MT_RO | MT_SECURE)
+
+#define MAP_DEVICE0    MAP_REGION_FLAT(DEVICE0_BASE,                   \
+                                       DEVICE0_SIZE,                   \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DEVICE1    MAP_REGION_FLAT(DEVICE1_BASE,                   \
+                                       DEVICE1_SIZE,                   \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DRAM1_NS   MAP_REGION_FLAT(DRAM1_NS_BASE,                  \
+                                       DRAM1_NS_SIZE,                  \
+                                       MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_TSP_SEC_MEM        MAP_REGION_FLAT(TSP_SEC_MEM_BASE,               \
+                                       TSP_SEC_MEM_SIZE,               \
+                                       MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ * This doesn't include TZRAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+#if IMAGE_BL1
+const mmap_region_t fvp_mmap[] = {
+       MAP_SHARED_RAM,
+       MAP_FLASH0,
+       MAP_DEVICE0,
+       MAP_DEVICE1,
+       {0}
+};
+#endif
+#if IMAGE_BL2
+const mmap_region_t fvp_mmap[] = {
+       MAP_SHARED_RAM,
+       MAP_FLASH0,
+       MAP_DEVICE0,
+       MAP_DEVICE1,
+       MAP_DRAM1_NS,
+       MAP_TSP_SEC_MEM,
+       {0}
+};
+#endif
+#if IMAGE_BL31
+const mmap_region_t fvp_mmap[] = {
+       MAP_SHARED_RAM,
+       MAP_DEVICE0,
+       MAP_DEVICE1,
+       MAP_TSP_SEC_MEM,
+       {0}
+};
+#endif
+#if IMAGE_BL32
+const mmap_region_t fvp_mmap[] = {
+       MAP_DEVICE0,
+       MAP_DEVICE1,
+       {0}
+};
+#endif
+
+/* Array of secure interrupts to be configured by the gic driver */
+const unsigned int irq_sec_array[] = {
+       IRQ_TZ_WDOG,
+       IRQ_SEC_PHY_TIMER,
+       IRQ_SEC_SGI_0,
+       IRQ_SEC_SGI_1,
+       IRQ_SEC_SGI_2,
+       IRQ_SEC_SGI_3,
+       IRQ_SEC_SGI_4,
+       IRQ_SEC_SGI_5,
+       IRQ_SEC_SGI_6,
+       IRQ_SEC_SGI_7
+};
+
+const unsigned int num_sec_irqs = sizeof(irq_sec_array) /
+       sizeof(irq_sec_array[0]);
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#if USE_COHERENT_MEM
+#define DEFINE_CONFIGURE_MMU_EL(_el)                           \
+       void fvp_configure_mmu_el##_el(unsigned long total_base,        \
+                                  unsigned long total_size,            \
+                                  unsigned long ro_start,              \
+                                  unsigned long ro_limit,              \
+                                  unsigned long coh_start,             \
+                                  unsigned long coh_limit)             \
+       {                                                               \
+               mmap_add_region(total_base, total_base,                 \
+                               total_size,                             \
+                               MT_MEMORY | MT_RW | MT_SECURE);         \
+               mmap_add_region(ro_start, ro_start,                     \
+                               ro_limit - ro_start,                    \
+                               MT_MEMORY | MT_RO | MT_SECURE);         \
+               mmap_add_region(coh_start, coh_start,                   \
+                               coh_limit - coh_start,                  \
+                               MT_DEVICE | MT_RW | MT_SECURE);         \
+               mmap_add(fvp_mmap);                                     \
+               init_xlat_tables();                                     \
+                                                                       \
+               enable_mmu_el##_el(0);                                  \
+       }
+#else
+#define DEFINE_CONFIGURE_MMU_EL(_el)                           \
+       void fvp_configure_mmu_el##_el(unsigned long total_base,        \
+                                  unsigned long total_size,            \
+                                  unsigned long ro_start,              \
+                                  unsigned long ro_limit)              \
+       {                                                               \
+               mmap_add_region(total_base, total_base,                 \
+                               total_size,                             \
+                               MT_MEMORY | MT_RW | MT_SECURE);         \
+               mmap_add_region(ro_start, ro_start,                     \
+                               ro_limit - ro_start,                    \
+                               MT_MEMORY | MT_RO | MT_SECURE);         \
+               mmap_add(fvp_mmap);                                     \
+               init_xlat_tables();                                     \
+                                                                       \
+               enable_mmu_el##_el(0);                                  \
+       }
+#endif
+
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(1)
+DEFINE_CONFIGURE_MMU_EL(3)
+
+/*******************************************************************************
+ * A single boot loader stack is expected to work on both the Foundation FVP
+ * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
+ * SYS_ID register provides a mechanism for detecting the differences between
+ * these platforms. This information is stored in a per-BL array to allow the
+ * code to take the correct path.Per BL platform configuration.
+ ******************************************************************************/
+int fvp_config_setup(void)
+{
+       unsigned int rev, hbi, bld, arch, sys_id;
+
+       sys_id = mmio_read_32(VE_SYSREGS_BASE + V2M_SYS_ID);
+       rev = (sys_id >> SYS_ID_REV_SHIFT) & SYS_ID_REV_MASK;
+       hbi = (sys_id >> SYS_ID_HBI_SHIFT) & SYS_ID_HBI_MASK;
+       bld = (sys_id >> SYS_ID_BLD_SHIFT) & SYS_ID_BLD_MASK;
+       arch = (sys_id >> SYS_ID_ARCH_SHIFT) & SYS_ID_ARCH_MASK;
+
+       if (arch != ARCH_MODEL) {
+               ERROR("This firmware is for FVP models\n");
+               panic();
+       }
+
+       /*
+        * The build field in the SYS_ID tells which variant of the GIC
+        * memory is implemented by the model.
+        */
+       switch (bld) {
+       case BLD_GIC_VE_MMAP:
+               plat_config.gicd_base = VE_GICD_BASE;
+               plat_config.gicc_base = VE_GICC_BASE;
+               plat_config.gich_base = VE_GICH_BASE;
+               plat_config.gicv_base = VE_GICV_BASE;
+               break;
+       case BLD_GIC_A53A57_MMAP:
+               plat_config.gicd_base = BASE_GICD_BASE;
+               plat_config.gicc_base = BASE_GICC_BASE;
+               plat_config.gich_base = BASE_GICH_BASE;
+               plat_config.gicv_base = BASE_GICV_BASE;
+               break;
+       default:
+               ERROR("Unsupported board build %x\n", bld);
+               panic();
+       }
+
+       /*
+        * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010
+        * for the Foundation FVP.
+        */
+       switch (hbi) {
+       case HBI_FOUNDATION:
+               plat_config.max_aff0 = 4;
+               plat_config.max_aff1 = 1;
+               plat_config.flags = 0;
+
+               /*
+                * Check for supported revisions of Foundation FVP
+                * Allow future revisions to run but emit warning diagnostic
+                */
+               switch (rev) {
+               case REV_FOUNDATION_V2_0:
+               case REV_FOUNDATION_V2_1:
+                       break;
+               default:
+                       WARN("Unrecognized Foundation FVP revision %x\n", rev);
+                       break;
+               }
+               break;
+       case HBI_FVP_BASE:
+               plat_config.max_aff0 = 4;
+               plat_config.max_aff1 = 2;
+               plat_config.flags |= CONFIG_BASE_MMAP | CONFIG_HAS_CCI |
+                       CONFIG_HAS_TZC;
+
+               /*
+                * Check for supported revisions
+                * Allow future revisions to run but emit warning diagnostic
+                */
+               switch (rev) {
+               case REV_FVP_BASE_V0:
+                       break;
+               default:
+                       WARN("Unrecognized Base FVP revision %x\n", rev);
+                       break;
+               }
+               break;
+       default:
+               ERROR("Unsupported board HBI number 0x%x\n", hbi);
+               panic();
+       }
+
+       return 0;
+}
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+       return NS_IMAGE_OFFSET;
+}
+
+uint64_t plat_get_syscnt_freq(void)
+{
+       uint64_t counter_base_frequency;
+
+       /* Read the frequency from Frequency modes table */
+       counter_base_frequency = mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF);
+
+       /* The first entry of the frequency modes table must not be 0 */
+       if (counter_base_frequency == 0)
+               panic();
+
+       return counter_base_frequency;
+}
+
+void fvp_cci_init(void)
+{
+       /*
+        * Initialize CCI-400 driver
+        */
+       if (plat_config.flags & CONFIG_HAS_CCI)
+               cci_init(CCI400_BASE,
+                       CCI400_SL_IFACE3_CLUSTER_IX,
+                       CCI400_SL_IFACE4_CLUSTER_IX);
+}
+
+void fvp_cci_enable(void)
+{
+       /*
+        * Enable CCI-400 coherency for this cluster. No need
+        * for locks as no other cpu is active at the
+        * moment
+        */
+       if (plat_config.flags & CONFIG_HAS_CCI)
+               cci_enable_cluster_coherency(read_mpidr());
+}
+
+void fvp_gic_init(void)
+{
+       arm_gic_init(plat_config.gicc_base,
+               plat_config.gicd_base,
+               BASE_GICR_BASE,
+               irq_sec_array,
+               num_sec_irqs);
+}
+
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t fvp_get_spsr_for_bl32_entry(void)
+{
+       /*
+        * The Secure Payload Dispatcher service is responsible for
+        * setting the SPSR prior to entry into the BL32 image.
+        */
+       return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+uint32_t fvp_get_spsr_for_bl33_entry(void)
+{
+       unsigned long el_status;
+       unsigned int mode;
+       uint32_t spsr;
+
+       /* Figure out what mode we enter the non-secure world in */
+       el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+       el_status &= ID_AA64PFR0_ELX_MASK;
+
+       if (el_status)
+               mode = MODE_EL2;
+       else
+               mode = MODE_EL1;
+
+       /*
+        * TODO: Consider the possibility of specifying the SPSR in
+        * the FIP ToC and allowing the platform to have a say as
+        * well.
+        */
+       spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+       return spsr;
+}
diff --git a/plat/fvp/aarch64/fvp_helpers.S b/plat/fvp/aarch64/fvp_helpers.S
new file mode 100644 (file)
index 0000000..e678b43
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <gic_v2.h>
+#include <platform_def.h>
+#include <pl011.h>
+#include "../drivers/pwrc/fvp_pwrc.h"
+
+       .globl  platform_get_entrypoint
+       .globl  plat_secondary_cold_boot_setup
+       .globl  platform_mem_init
+       .globl  plat_report_exception
+       .globl  platform_is_primary_cpu
+       .globl  plat_crash_console_init
+       .globl  plat_crash_console_putc
+
+       .macro  fvp_choose_gicmmap  param1, param2, x_tmp, w_tmp, res
+       ldr     \x_tmp, =VE_SYSREGS_BASE + V2M_SYS_ID
+       ldr     \w_tmp, [\x_tmp]
+       ubfx    \w_tmp, \w_tmp, #SYS_ID_BLD_SHIFT, #SYS_ID_BLD_LENGTH
+       cmp     \w_tmp, #BLD_GIC_VE_MMAP
+       csel    \res, \param1, \param2, eq
+       .endm
+
+       /* -----------------------------------------------------
+        * void plat_secondary_cold_boot_setup (void);
+        *
+        * This function performs any platform specific actions
+        * needed for a secondary cpu after a cold reset e.g
+        * mark the cpu's presence, mechanism to place it in a
+        * holding pen etc.
+        * TODO: Should we read the PSYS register to make sure
+        * that the request has gone through.
+        * -----------------------------------------------------
+        */
+func plat_secondary_cold_boot_setup
+       /* ---------------------------------------------
+        * Power down this cpu.
+        * TODO: Do we need to worry about powering the
+        * cluster down as well here. That will need
+        * locks which we won't have unless an elf-
+        * loader zeroes out the zi section.
+        * ---------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       ldr     x1, =PWRC_BASE
+       str     w0, [x1, #PPOFFR_OFF]
+
+       /* ---------------------------------------------
+        * Deactivate the gic cpu interface as well
+        * ---------------------------------------------
+        */
+       ldr     x0, =VE_GICC_BASE
+       ldr     x1, =BASE_GICC_BASE
+       fvp_choose_gicmmap      x0, x1, x2, w2, x1
+       mov     w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1)
+       orr     w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0)
+       str     w0, [x1, #GICC_CTLR]
+
+       /* ---------------------------------------------
+        * There is no sane reason to come out of this
+        * wfi so panic if we do. This cpu will be pow-
+        * ered on and reset by the cpu_on pm api
+        * ---------------------------------------------
+        */
+       dsb     sy
+       wfi
+cb_panic:
+       b       cb_panic
+
+
+       /* -----------------------------------------------------
+        * void platform_get_entrypoint (unsigned int mpid);
+        *
+        * Main job of this routine is to distinguish between
+        * a cold and warm boot.
+        * On a cold boot the secondaries first wait for the
+        * platform to be initialized after which they are
+        * hotplugged in. The primary proceeds to perform the
+        * platform initialization.
+        * On a warm boot, each cpu jumps to the address in its
+        * mailbox.
+        *
+        * TODO: Not a good idea to save lr in a temp reg
+        * TODO: PSYSR is a common register and should be
+        *      accessed using locks. Since its not possible
+        *      to use locks immediately after a cold reset
+        *      we are relying on the fact that after a cold
+        *      reset all cpus will read the same WK field
+        * -----------------------------------------------------
+        */
+func platform_get_entrypoint
+       mov     x9, x30 // lr
+       mov     x2, x0
+       ldr     x1, =PWRC_BASE
+       str     w2, [x1, #PSYSR_OFF]
+       ldr     w2, [x1, #PSYSR_OFF]
+       ubfx    w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_MASK
+       cmp     w2, #WKUP_PPONR
+       beq     warm_reset
+       cmp     w2, #WKUP_GICREQ
+       beq     warm_reset
+       mov     x0, #0
+       b       exit
+warm_reset:
+       /* ---------------------------------------------
+        * A per-cpu mailbox is maintained in the tru-
+        * sted DRAM. Its flushed out of the caches
+        * after every update using normal memory so
+        * its safe to read it here with SO attributes
+        * ---------------------------------------------
+        */
+       ldr     x10, =MBOX_BASE
+       bl      platform_get_core_pos
+       lsl     x0, x0, #CACHE_WRITEBACK_SHIFT
+       ldr     x0, [x10, x0]
+       cbz     x0, _panic
+exit:
+       ret     x9
+_panic:        b       _panic
+
+
+       /* -----------------------------------------------------
+        * void platform_mem_init (void);
+        *
+        * Zero out the mailbox registers in the shared memory.
+        * The mmu is turned off right now and only the primary can
+        * ever execute this code. Secondaries will read the
+        * mailboxes using SO accesses. In short, BL31 will
+        * update the mailboxes after mapping the tzdram as
+        * normal memory. It will flush its copy after update.
+        * BL1 will always read the mailboxes with the MMU off
+        * -----------------------------------------------------
+        */
+func platform_mem_init
+       ldr     x0, =MBOX_BASE
+       mov     w1, #PLATFORM_CORE_COUNT
+loop:
+       str     xzr, [x0], #CACHE_WRITEBACK_GRANULE
+       subs    w1, w1, #1
+       b.gt    loop
+       ret
+
+       /* ---------------------------------------------
+        * void plat_report_exception(unsigned int type)
+        * Function to report an unhandled exception
+        * with platform-specific means.
+        * On FVP platform, it updates the LEDs
+        * to indicate where we are
+        * ---------------------------------------------
+        */
+func plat_report_exception
+       mrs     x1, CurrentEl
+       lsr     x1, x1, #MODE_EL_SHIFT
+       lsl     x1, x1, #SYS_LED_EL_SHIFT
+       lsl     x0, x0, #SYS_LED_EC_SHIFT
+       mov     x2, #(SECURE << SYS_LED_SS_SHIFT)
+       orr     x0, x0, x2
+       orr     x0, x0, x1
+       mov     x1, #VE_SYSREGS_BASE
+       add     x1, x1, #V2M_SYS_LED
+       str     w0, [x1]
+       ret
+
+func platform_is_primary_cpu
+       and     x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+       cmp     x0, #FVP_PRIMARY_CPU
+       cset    x0, eq
+       ret
+
+       /* Define a crash console for the plaform */
+#define FVP_CRASH_CONSOLE_BASE         PL011_UART1_BASE
+
+       /* ---------------------------------------------
+        * int plat_crash_console_init(void)
+        * Function to initialize the crash console
+        * without a C Runtime to print crash report.
+        * Clobber list : x0, x1, x2
+        * ---------------------------------------------
+        */
+func plat_crash_console_init
+       mov_imm x0, FVP_CRASH_CONSOLE_BASE
+       mov_imm x1, PL011_UART1_CLK_IN_HZ
+       mov_imm x2, PL011_BAUDRATE
+       b       console_core_init
+
+       /* ---------------------------------------------
+        * int plat_crash_console_putc(int c)
+        * Function to print a character on the crash
+        * console without a C Runtime.
+        * Clobber list : x1, x2
+        * ---------------------------------------------
+        */
+func plat_crash_console_putc
+       mov_imm x1, FVP_CRASH_CONSOLE_BASE
+       b       console_core_putc
diff --git a/plat/fvp/bl1_fvp_setup.c b/plat/fvp/bl1_fvp_setup.c
new file mode 100644 (file)
index 0000000..4b421d7
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <console.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include "../../bl1/bl1_private.h"
+#include "fvp_def.h"
+#include "fvp_private.h"
+
+#if USE_COHERENT_MEM
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/* Data structure which holds the extents of the trusted SRAM for BL1*/
+static meminfo_t bl1_tzram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+       return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+       const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
+
+       /* Initialize the console to provide early debug support */
+       console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /* Allow BL1 to see the whole Trusted RAM */
+       bl1_tzram_layout.total_base = FVP_TRUSTED_SRAM_BASE;
+       bl1_tzram_layout.total_size = FVP_TRUSTED_SRAM_SIZE;
+
+       /* Calculate how much RAM BL1 is using and how much remains free */
+       bl1_tzram_layout.free_base = FVP_TRUSTED_SRAM_BASE;
+       bl1_tzram_layout.free_size = FVP_TRUSTED_SRAM_SIZE;
+       reserve_mem(&bl1_tzram_layout.free_base,
+                   &bl1_tzram_layout.free_size,
+                   BL1_RAM_BASE,
+                   bl1_size);
+
+       /* Initialize the platform config for future decision making */
+       fvp_config_setup();
+}
+
+/*******************************************************************************
+ * Function which will evaluate how much of the trusted ram has been gobbled
+ * up by BL1 and return the base and size of whats available for loading BL2.
+ * Its called after coherency and the MMU have been turned on.
+ ******************************************************************************/
+void bl1_platform_setup(void)
+{
+       /* Initialise the IO layer and register platform IO devices */
+       fvp_io_setup();
+}
+
+
+/*******************************************************************************
+ * Perform the very early platform specific architecture setup here. At the
+ * moment this only does basic initialization. Later architectural setup
+ * (bl1_arch_setup()) does not do anything platform specific.
+ ******************************************************************************/
+void bl1_plat_arch_setup(void)
+{
+       fvp_cci_init();
+       fvp_cci_enable();
+
+       fvp_configure_mmu_el3(bl1_tzram_layout.total_base,
+                             bl1_tzram_layout.total_size,
+                             BL1_RO_BASE,
+                             BL1_RO_LIMIT
+#if USE_COHERENT_MEM
+                             , BL1_COHERENT_RAM_BASE,
+                             BL1_COHERENT_RAM_LIMIT
+#endif
+                            );
+}
+
+
+/*******************************************************************************
+ * Before calling this function BL2 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL2 and set SPSR and security state.
+ * On FVP we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image,
+                               entry_point_info_t *bl2_ep)
+{
+       SET_SECURITY_STATE(bl2_ep->h.attr, SECURE);
+       bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+}
diff --git a/plat/fvp/bl2_fvp_setup.c b/plat/fvp/bl2_fvp_setup.c
new file mode 100644 (file)
index 0000000..364833f
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include "fvp_def.h"
+#include "fvp_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+#if USE_COHERENT_MEM
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+#endif
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL2_RO_BASE (unsigned long)(&__RO_START__)
+#define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
+
+#if USE_COHERENT_MEM
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout
+__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE)));
+
+/* Assert that BL3-1 parameters fit in shared memory */
+CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t)) <
+       (FVP_SHARED_MEM_BASE + FVP_SHARED_MEM_SIZE),
+       assert_bl31_params_do_not_fit_in_shared_memory);
+
+/*******************************************************************************
+ * Reference to structures which holds the arguments which need to be passed
+ * to BL31
+ ******************************************************************************/
+static bl31_params_t *bl2_to_bl31_params;
+static entry_point_info_t *bl31_ep_info;
+
+meminfo_t *bl2_plat_sec_mem_layout(void)
+{
+       return &bl2_tzram_layout;
+}
+
+/*******************************************************************************
+ * This function assigns a pointer to the memory that the platform has kept
+ * aside to pass platform specific and trusted firmware related information
+ * to BL31. This memory is allocated by allocating memory to
+ * bl2_to_bl31_params_mem_t structure which is a superset of all the
+ * structure whose information is passed to BL31
+ * NOTE: This function should be called only once and should be done
+ * before generating params to BL31
+ ******************************************************************************/
+bl31_params_t *bl2_plat_get_bl31_params(void)
+{
+       bl2_to_bl31_params_mem_t *bl31_params_mem;
+
+       /*
+        * Allocate the memory for all the arguments that needs to
+        * be passed to BL31
+        */
+       bl31_params_mem = (bl2_to_bl31_params_mem_t *)PARAMS_BASE;
+       memset((void *)PARAMS_BASE, 0, sizeof(bl2_to_bl31_params_mem_t));
+
+       /* Assign memory for TF related information */
+       bl2_to_bl31_params = &bl31_params_mem->bl31_params;
+       SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0);
+
+       /* Fill BL31 related information */
+       bl31_ep_info = &bl31_params_mem->bl31_ep_info;
+       bl2_to_bl31_params->bl31_image_info = &bl31_params_mem->bl31_image_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY,
+                                               VERSION_1, 0);
+
+       /* Fill BL32 related information if it exists */
+       if (BL32_BASE) {
+               bl2_to_bl31_params->bl32_ep_info =
+                                       &bl31_params_mem->bl32_ep_info;
+               SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info,
+                                       PARAM_EP, VERSION_1, 0);
+               bl2_to_bl31_params->bl32_image_info =
+                                       &bl31_params_mem->bl32_image_info;
+               SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info,
+                                       PARAM_IMAGE_BINARY,
+                                       VERSION_1, 0);
+       }
+
+       /* Fill BL33 related information */
+       bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem->bl33_ep_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
+                                       PARAM_EP, VERSION_1, 0);
+       bl2_to_bl31_params->bl33_image_info = &bl31_params_mem->bl33_image_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY,
+                                       VERSION_1, 0);
+
+       return bl2_to_bl31_params;
+}
+
+
+/*******************************************************************************
+ * This function returns a pointer to the shared memory that the platform
+ * has kept to point to entry point information of BL31 to BL2
+ ******************************************************************************/
+struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
+{
+#if DEBUG
+       bl31_ep_info->args.arg1 = FVP_BL31_PLAT_PARAM_VAL;
+#endif
+       return bl31_ep_info;
+}
+
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted SRAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted SRAM.
+ * Copy it to a safe loaction before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+void bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+       /* Initialize the console to provide early debug support */
+       console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /* Setup the BL2 memory layout */
+       bl2_tzram_layout = *mem_layout;
+
+       /* Initialize the platform config for future decision making */
+       fvp_config_setup();
+
+       /* Initialise the IO layer and register platform IO devices */
+       fvp_io_setup();
+}
+
+/*******************************************************************************
+ * Perform platform specific setup. For now just initialize the memory location
+ * to use for passing arguments to BL31.
+ ******************************************************************************/
+void bl2_platform_setup(void)
+{
+       /*
+        * Do initial security configuration to allow DRAM/device access. On
+        * Base FVP only DRAM security is programmable (via TrustZone), but
+        * other platforms might have more programmable security devices
+        * present.
+        */
+       fvp_security_setup();
+}
+
+/* Flush the TF params and the TF plat params */
+void bl2_plat_flush_bl31_params(void)
+{
+       flush_dcache_range((unsigned long)PARAMS_BASE, \
+                               sizeof(bl2_to_bl31_params_mem_t));
+}
+
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl2_plat_arch_setup(void)
+{
+       fvp_configure_mmu_el1(bl2_tzram_layout.total_base,
+                             bl2_tzram_layout.total_size,
+                             BL2_RO_BASE,
+                             BL2_RO_LIMIT
+#if USE_COHERENT_MEM
+                             , BL2_COHERENT_RAM_BASE,
+                             BL2_COHERENT_RAM_LIMIT
+#endif
+                             );
+}
+
+/*******************************************************************************
+ * Before calling this function BL31 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL31 and set SPSR and security state.
+ * On FVP we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl31_ep_info(image_info_t *bl31_image_info,
+                                       entry_point_info_t *bl31_ep_info)
+{
+       SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
+       bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+                                       DISABLE_ALL_EXCEPTIONS);
+}
+
+
+/*******************************************************************************
+ * Before calling this function BL32 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL32 and set SPSR and security state.
+ * On FVP we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
+                                       entry_point_info_t *bl32_ep_info)
+{
+       SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+       bl32_ep_info->spsr = fvp_get_spsr_for_bl32_entry();
+}
+
+/*******************************************************************************
+ * Before calling this function BL33 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL33 and set SPSR and security state.
+ * On FVP we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl33_ep_info(image_info_t *image,
+                                       entry_point_info_t *bl33_ep_info)
+{
+       SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
+       bl33_ep_info->spsr = fvp_get_spsr_for_bl33_entry();
+}
+
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL32
+ ******************************************************************************/
+void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
+{
+       /*
+        * Populate the extents of memory available for loading BL32.
+        */
+       bl32_meminfo->total_base = BL32_BASE;
+       bl32_meminfo->free_base = BL32_BASE;
+       bl32_meminfo->total_size =
+                       (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+       bl32_meminfo->free_size =
+                       (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL33
+ ******************************************************************************/
+void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
+{
+       bl33_meminfo->total_base = DRAM1_NS_BASE;
+       bl33_meminfo->total_size = DRAM1_NS_SIZE;
+       bl33_meminfo->free_base = DRAM1_NS_BASE;
+       bl33_meminfo->free_size = DRAM1_NS_SIZE;
+}
diff --git a/plat/fvp/bl31_fvp_setup.c b/plat/fvp/bl31_fvp_setup.c
new file mode 100644 (file)
index 0000000..977cbb4
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <console.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+#include "drivers/pwrc/fvp_pwrc.h"
+#include "fvp_def.h"
+#include "fvp_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+extern unsigned long __BL31_END__;
+
+#if USE_COHERENT_MEM
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+#endif
+
+/*
+ * The next 3 constants identify the extents of the code, RO data region and the
+ * limit of the BL3-1 image.  These addresses are used by the MMU setup code and
+ * therefore they must be page-aligned.  It is the responsibility of the linker
+ * script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL31_END (unsigned long)(&__BL31_END__)
+
+#if USE_COHERENT_MEM
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+#if RESET_TO_BL31
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+#else
+/*******************************************************************************
+ * Reference to structure which holds the arguments that have been passed to
+ * BL31 from BL2.
+ ******************************************************************************/
+static bl31_params_t *bl2_to_bl31_params;
+#endif
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for the
+ * security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+#if RESET_TO_BL31
+       assert(sec_state_is_valid(type));
+
+       if (type == NON_SECURE)
+               return &bl33_image_ep_info;
+       else
+               return &bl32_image_ep_info;
+#else
+       entry_point_info_t *next_image_info;
+
+       assert(sec_state_is_valid(type));
+
+       next_image_info = (type == NON_SECURE) ?
+               bl2_to_bl31_params->bl33_ep_info :
+               bl2_to_bl31_params->bl32_ep_info;
+
+       /* None of the images on this platform can have 0x0 as the entrypoint */
+       if (next_image_info->pc)
+               return next_image_info;
+       else
+               return NULL;
+#endif
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'image_info' structure of the next image for the
+ * security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+image_info_t *bl31_plat_get_next_image_image_info(uint32_t type)
+{
+#if RESET_TO_BL31
+       assert(sec_state_is_valid(type));
+
+       if (type == NON_SECURE)
+               return NULL;
+       else
+               return NULL;
+#else
+       image_info_t *next_image_info;
+
+       assert(sec_state_is_valid(type));
+
+       next_image_info = (type == NON_SECURE) ?
+               bl2_to_bl31_params->bl33_image_info :
+               bl2_to_bl31_params->bl32_image_info;
+
+       /* None of the images on this platform can have size 0x0 */
+       if (next_image_info->image_size)
+               return next_image_info;
+       else
+               return NULL;
+#endif
+}
+
+
+
+/*******************************************************************************
+ * Perform any BL31 specific platform actions. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables. On the FVP
+ * we know that BL2 has populated the parameters in secure DRAM. So we just use
+ * the reference passed in 'from_bl2' instead of copying. The 'data' parameter
+ * is not used since all the information is contained in 'from_bl2'. Also, BL2
+ * has flushed this information to memory, so we are guaranteed to pick up good
+ * data
+ ******************************************************************************/
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+                               void *plat_params_from_bl2)
+{
+       /* Initialize the console to provide early debug support */
+       console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /* Initialize the platform config for future decision making */
+       fvp_config_setup();
+
+#if RESET_TO_BL31
+       /* There are no parameters from BL2 if BL31 is a reset vector */
+       assert(from_bl2 == NULL);
+       assert(plat_params_from_bl2 == NULL);
+
+       /*
+        * Do initial security configuration to allow DRAM/device access. On
+        * Base FVP only DRAM security is programmable (via TrustZone), but
+        * other platforms might have more programmable security devices
+        * present.
+        */
+       fvp_security_setup();
+
+       /* Populate entry point information for BL3-2 and BL3-3 */
+       SET_PARAM_HEAD(&bl32_image_ep_info,
+                               PARAM_EP,
+                               VERSION_1,
+                               0);
+       SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+       bl32_image_ep_info.pc = BL32_BASE;
+       bl32_image_ep_info.spsr = fvp_get_spsr_for_bl32_entry();
+
+       SET_PARAM_HEAD(&bl33_image_ep_info,
+                               PARAM_EP,
+                               VERSION_1,
+                               0);
+       /*
+        * Tell BL31 where the non-trusted software image
+        * is located and the entry state information
+        */
+       bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+       bl33_image_ep_info.spsr = fvp_get_spsr_for_bl33_entry();
+       SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#else
+       /* Check params passed from BL2 should not be NULL,
+        * We are not checking plat_params_from_bl2 as NULL as we are not
+        * using it on FVP
+        */
+       assert(from_bl2 != NULL);
+       assert(from_bl2->h.type == PARAM_BL31);
+       assert(from_bl2->h.version >= VERSION_1);
+
+       bl2_to_bl31_params = from_bl2;
+       assert(((unsigned long)plat_params_from_bl2) == FVP_BL31_PLAT_PARAM_VAL);
+#endif
+}
+
+/*******************************************************************************
+ * Initialize the gic, configure the CLCD and zero out variables needed by the
+ * secondaries to boot up correctly.
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+       unsigned int reg_val;
+
+       /* Initialize the gic cpu and distributor interfaces */
+       fvp_gic_init();
+       arm_gic_setup();
+
+       /*
+        * TODO: Configure the CLCD before handing control to
+        * linux. Need to see if a separate driver is needed
+        * instead.
+        */
+       mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGDATA, 0);
+       mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL,
+                     (1ull << 31) | (1 << 30) | (7 << 20) | (0 << 16));
+
+       /* Enable and initialize the System level generic timer */
+       mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN);
+
+       /* Allow access to the System counter timer module */
+       reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
+       reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
+       reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
+       mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(0), reg_val);
+       mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val);
+
+       reg_val = (1 << CNTNSAR_NS_SHIFT(0)) | (1 << CNTNSAR_NS_SHIFT(1));
+       mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+
+       /* Intialize the power controller */
+       fvp_pwrc_setup();
+
+       /* Topologies are best known to the platform. */
+       fvp_setup_topology();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+       fvp_cci_init();
+#if RESET_TO_BL31
+       fvp_cci_enable();
+#endif
+       fvp_configure_mmu_el3(BL31_RO_BASE,
+                             (BL31_END - BL31_RO_BASE),
+                             BL31_RO_BASE,
+                             BL31_RO_LIMIT
+#if USE_COHERENT_MEM
+                             , BL31_COHERENT_RAM_BASE,
+                             BL31_COHERENT_RAM_LIMIT
+#endif
+                             );
+}
diff --git a/plat/fvp/drivers/pwrc/fvp_pwrc.c b/plat/fvp/drivers/pwrc/fvp_pwrc.c
new file mode 100644 (file)
index 0000000..0497c2b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bakery_lock.h>
+#include <mmio.h>
+#include "../../fvp_def.h"
+#include "../../fvp_private.h"
+#include "fvp_pwrc.h"
+
+/*
+ * TODO: Someday there will be a generic power controller api. At the moment
+ * each platform has its own pwrc so just exporting functions is fine.
+ */
+#if USE_COHERENT_MEM
+static bakery_lock_t pwrc_lock __attribute__ ((section("tzfw_coherent_mem")));
+#define LOCK_ARG       &pwrc_lock
+#else
+#define LOCK_ARG       FVP_PWRC_BAKERY_ID
+#endif
+
+unsigned int fvp_pwrc_get_cpu_wkr(unsigned long mpidr)
+{
+       return PSYSR_WK(fvp_pwrc_read_psysr(mpidr));
+}
+
+unsigned int fvp_pwrc_read_psysr(unsigned long mpidr)
+{
+       unsigned int rc;
+       fvp_lock_get(LOCK_ARG);
+       mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr);
+       rc = mmio_read_32(PWRC_BASE + PSYSR_OFF);
+       fvp_lock_release(LOCK_ARG);
+       return rc;
+}
+
+void fvp_pwrc_write_pponr(unsigned long mpidr)
+{
+       fvp_lock_get(LOCK_ARG);
+       mmio_write_32(PWRC_BASE + PPONR_OFF, (unsigned int) mpidr);
+       fvp_lock_release(LOCK_ARG);
+}
+
+void fvp_pwrc_write_ppoffr(unsigned long mpidr)
+{
+       fvp_lock_get(LOCK_ARG);
+       mmio_write_32(PWRC_BASE + PPOFFR_OFF, (unsigned int) mpidr);
+       fvp_lock_release(LOCK_ARG);
+}
+
+void fvp_pwrc_set_wen(unsigned long mpidr)
+{
+       fvp_lock_get(LOCK_ARG);
+       mmio_write_32(PWRC_BASE + PWKUPR_OFF,
+                     (unsigned int) (PWKUPR_WEN | mpidr));
+       fvp_lock_release(LOCK_ARG);
+}
+
+void fvp_pwrc_clr_wen(unsigned long mpidr)
+{
+       fvp_lock_get(LOCK_ARG);
+       mmio_write_32(PWRC_BASE + PWKUPR_OFF,
+                     (unsigned int) mpidr);
+       fvp_lock_release(LOCK_ARG);
+}
+
+void fvp_pwrc_write_pcoffr(unsigned long mpidr)
+{
+       fvp_lock_get(LOCK_ARG);
+       mmio_write_32(PWRC_BASE + PCOFFR_OFF, (unsigned int) mpidr);
+       fvp_lock_release(LOCK_ARG);
+}
+
+/* Nothing else to do here apart from initializing the lock */
+int fvp_pwrc_setup(void)
+{
+       fvp_lock_init(LOCK_ARG);
+
+       return 0;
+}
+
+
+
diff --git a/plat/fvp/drivers/pwrc/fvp_pwrc.h b/plat/fvp/drivers/pwrc/fvp_pwrc.h
new file mode 100644 (file)
index 0000000..ad1ea85
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FVP_PWRC_H__
+#define __FVP_PWRC_H__
+
+/* FVP Power controller register offset etc */
+#define PPOFFR_OFF             0x0
+#define PPONR_OFF              0x4
+#define PCOFFR_OFF             0x8
+#define PWKUPR_OFF             0xc
+#define PSYSR_OFF              0x10
+
+#define PWKUPR_WEN             (1ull << 31)
+
+#define PSYSR_AFF_L2           (1 << 31)
+#define PSYSR_AFF_L1           (1 << 30)
+#define PSYSR_AFF_L0           (1 << 29)
+#define PSYSR_WEN              (1 << 28)
+#define PSYSR_PC               (1 << 27)
+#define PSYSR_PP               (1 << 26)
+
+#define PSYSR_WK_SHIFT         24
+#define PSYSR_WK_MASK          0x3
+#define PSYSR_WK(x)            (x >> PSYSR_WK_SHIFT) & PSYSR_WK_MASK
+
+#define WKUP_COLD              0x0
+#define WKUP_RESET             0x1
+#define WKUP_PPONR             0x2
+#define WKUP_GICREQ            0x3
+
+#define PSYSR_INVALID          0xffffffff
+
+#ifndef __ASSEMBLY__
+
+/*******************************************************************************
+ * Function & variable prototypes
+ ******************************************************************************/
+int fvp_pwrc_setup(void);
+void fvp_pwrc_write_pcoffr(unsigned long);
+void fvp_pwrc_write_ppoffr(unsigned long);
+void fvp_pwrc_write_pponr(unsigned long);
+void fvp_pwrc_set_wen(unsigned long);
+void fvp_pwrc_clr_wen(unsigned long);
+unsigned int fvp_pwrc_read_psysr(unsigned long);
+unsigned int fvp_pwrc_get_cpu_wkr(unsigned long);
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* __FVP_PWRC_H__ */
diff --git a/plat/fvp/fvp_def.h b/plat/fvp/fvp_def.h
new file mode 100644 (file)
index 0000000..d1d9adb
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FVP_DEF_H__
+#define __FVP_DEF_H__
+
+/* Firmware Image Package */
+#define FIP_IMAGE_NAME                 "fip.bin"
+#define FVP_PRIMARY_CPU                        0x0
+
+/* Memory location options for TSP */
+#define FVP_TRUSTED_SRAM_ID            0
+#define FVP_TRUSTED_DRAM_ID            1
+#define FVP_DRAM_ID                    2
+
+/*
+ * Some of the definitions in this file use the 'ull' suffix in order to avoid
+ * subtle integer overflow errors due to implicit integer type promotion when
+ * working with 32-bit values.
+ *
+ * The TSP linker script includes some of these definitions to define the BL3-2
+ * memory map, but the GNU LD does not support the 'ull' suffix, causing the
+ * build process to fail. To solve this problem, the auxiliary macro MAKE_ULL(x)
+ * will add the 'ull' suffix only when the macro __LINKER__  is not defined
+ * (__LINKER__ is defined in the command line to preprocess the linker script).
+ * Constants in the linker script will not have the 'ull' suffix, but this is
+ * not a problem since the linker evaluates all constant expressions to 64 bit
+ * (assuming the target architecture is 64 bit).
+ */
+#ifndef __LINKER__
+  #define MAKE_ULL(x)                  x##ull
+#else
+  #define MAKE_ULL(x)                  x
+#endif
+
+/*******************************************************************************
+ * FVP memory map related constants
+ ******************************************************************************/
+
+#define FVP_TRUSTED_ROM_BASE   0x00000000
+#define FVP_TRUSTED_ROM_SIZE   0x04000000      /* 64 MB */
+
+/* The first 4KB of Trusted SRAM are used as shared memory */
+#define FVP_SHARED_MEM_BASE    0x04000000
+#define FVP_SHARED_MEM_SIZE    0x00001000      /* 4 KB */
+
+/* The remaining Trusted SRAM is used to load the BL images */
+#define FVP_TRUSTED_SRAM_BASE  0x04001000
+#define FVP_TRUSTED_SRAM_SIZE  0x0003F000      /* 252 KB */
+
+#define FVP_TRUSTED_DRAM_BASE  0x06000000
+#define FVP_TRUSTED_DRAM_SIZE  0x02000000      /* 32 MB */
+
+#define FLASH0_BASE            0x08000000
+#define FLASH0_SIZE            0x04000000
+
+#define FLASH1_BASE            0x0c000000
+#define FLASH1_SIZE            0x04000000
+
+#define PSRAM_BASE             0x14000000
+#define PSRAM_SIZE             0x04000000
+
+#define VRAM_BASE              0x18000000
+#define VRAM_SIZE              0x02000000
+
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE           0x1a000000
+#define DEVICE0_SIZE           0x12200000
+
+#define DEVICE1_BASE           0x2f000000
+#define DEVICE1_SIZE           0x200000
+
+#define NSRAM_BASE             0x2e000000
+#define NSRAM_SIZE             0x10000
+
+#define DRAM1_BASE             MAKE_ULL(0x80000000)
+#define DRAM1_SIZE             MAKE_ULL(0x80000000)
+#define DRAM1_END              (DRAM1_BASE + DRAM1_SIZE - 1)
+
+/* Define the top 16 MB of DRAM1 as secure */
+#define DRAM1_SEC_SIZE         MAKE_ULL(0x01000000)
+#define DRAM1_SEC_BASE         (DRAM1_BASE + DRAM1_SIZE - DRAM1_SEC_SIZE)
+#define DRAM1_SEC_END          (DRAM1_SEC_BASE + DRAM1_SEC_SIZE - 1)
+
+#define DRAM1_NS_BASE          DRAM1_BASE
+#define DRAM1_NS_SIZE          (DRAM1_SIZE - DRAM1_SEC_SIZE)
+#define DRAM1_NS_END           (DRAM1_NS_BASE + DRAM1_NS_SIZE - 1)
+
+#define DRAM_BASE              DRAM1_BASE
+#define DRAM_SIZE              DRAM1_SIZE
+
+#define DRAM2_BASE             MAKE_ULL(0x880000000)
+#define DRAM2_SIZE             MAKE_ULL(0x780000000)
+#define DRAM2_END              (DRAM2_BASE + DRAM2_SIZE - 1)
+
+#define PCIE_EXP_BASE          0x40000000
+#define TZRNG_BASE             0x7fe60000
+#define TZNVCTR_BASE           0x7fe70000
+#define TZROOTKEY_BASE         0x7fe80000
+
+/* Memory mapped Generic timer interfaces  */
+#define SYS_CNTCTL_BASE                0x2a430000
+#define SYS_CNTREAD_BASE       0x2a800000
+#define SYS_TIMCTL_BASE                0x2a810000
+
+/* V2M motherboard system registers & offsets */
+#define VE_SYSREGS_BASE                0x1c010000
+#define V2M_SYS_ID             0x0
+#define V2M_SYS_SWITCH         0x4
+#define V2M_SYS_LED            0x8
+#define V2M_SYS_CFGDATA                0xa0
+#define V2M_SYS_CFGCTRL                0xa4
+#define V2M_SYS_CFGSTATUS      0xa8
+
+#define CFGCTRL_START          (1 << 31)
+#define CFGCTRL_RW             (1 << 30)
+#define CFGCTRL_FUNC_SHIFT     20
+#define CFGCTRL_FUNC(fn)       (fn << CFGCTRL_FUNC_SHIFT)
+#define FUNC_CLK_GEN           0x01
+#define FUNC_TEMP              0x04
+#define FUNC_DB_RESET          0x05
+#define FUNC_SCC_CFG           0x06
+#define FUNC_SHUTDOWN          0x08
+#define FUNC_REBOOT            0x09
+
+/* Load address of BL33 in the FVP port */
+#define NS_IMAGE_OFFSET                (DRAM1_BASE + 0x8000000) /* DRAM + 128MB */
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define FVP_BL31_PLAT_PARAM_VAL        0x0f1e2d3c4b5a6978ULL
+
+/*
+ * V2M sysled bit definitions. The values written to this
+ * register are defined in arch.h & runtime_svc.h. Only
+ * used by the primary cpu to diagnose any cold boot issues.
+ *
+ * SYS_LED[0]   - Security state (S=0/NS=1)
+ * SYS_LED[2:1] - Exception Level (EL3-EL0)
+ * SYS_LED[7:3] - Exception Class (Sync/Async & origin)
+ *
+ */
+#define SYS_LED_SS_SHIFT               0x0
+#define SYS_LED_EL_SHIFT               0x1
+#define SYS_LED_EC_SHIFT               0x3
+
+#define SYS_LED_SS_MASK                0x1
+#define SYS_LED_EL_MASK                0x3
+#define SYS_LED_EC_MASK                0x1f
+
+/* V2M sysid register bits */
+#define SYS_ID_REV_SHIFT       28
+#define SYS_ID_HBI_SHIFT       16
+#define SYS_ID_BLD_SHIFT       12
+#define SYS_ID_ARCH_SHIFT      8
+#define SYS_ID_FPGA_SHIFT      0
+
+#define SYS_ID_REV_MASK        0xf
+#define SYS_ID_HBI_MASK        0xfff
+#define SYS_ID_BLD_MASK        0xf
+#define SYS_ID_ARCH_MASK       0xf
+#define SYS_ID_FPGA_MASK       0xff
+
+#define SYS_ID_BLD_LENGTH      4
+
+#define HBI_FVP_BASE           0x020
+#define REV_FVP_BASE_V0                0x0
+
+#define HBI_FOUNDATION         0x010
+#define REV_FOUNDATION_V2_0    0x0
+#define REV_FOUNDATION_V2_1    0x1
+
+#define BLD_GIC_VE_MMAP        0x0
+#define BLD_GIC_A53A57_MMAP    0x1
+
+#define ARCH_MODEL             0x1
+
+/* FVP Power controller base address*/
+#define PWRC_BASE              0x1c100000
+
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define CCI400_BASE                    0x2c090000
+#define CCI400_SL_IFACE3_CLUSTER_IX    0
+#define CCI400_SL_IFACE4_CLUSTER_IX    1
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+/* VE compatible GIC memory map */
+#define VE_GICD_BASE                   0x2c001000
+#define VE_GICC_BASE                   0x2c002000
+#define VE_GICH_BASE                   0x2c004000
+#define VE_GICV_BASE                   0x2c006000
+
+/* Base FVP compatible GIC memory map */
+#define BASE_GICD_BASE                 0x2f000000
+#define BASE_GICR_BASE                 0x2f100000
+#define BASE_GICC_BASE                 0x2c000000
+#define BASE_GICH_BASE                 0x2c010000
+#define BASE_GICV_BASE                 0x2c02f000
+
+#define IRQ_TZ_WDOG                    56
+#define IRQ_SEC_PHY_TIMER              29
+#define IRQ_SEC_SGI_0                  8
+#define IRQ_SEC_SGI_1                  9
+#define IRQ_SEC_SGI_2                  10
+#define IRQ_SEC_SGI_3                  11
+#define IRQ_SEC_SGI_4                  12
+#define IRQ_SEC_SGI_5                  13
+#define IRQ_SEC_SGI_6                  14
+#define IRQ_SEC_SGI_7                  15
+
+/*******************************************************************************
+ * PL011 related constants
+ ******************************************************************************/
+#define PL011_UART0_BASE               0x1c090000
+#define PL011_UART1_BASE               0x1c0a0000
+#define PL011_UART2_BASE               0x1c0b0000
+#define PL011_UART3_BASE               0x1c0c0000
+
+#define PL011_BAUDRATE  115200
+
+#define PL011_UART0_CLK_IN_HZ 24000000
+#define PL011_UART1_CLK_IN_HZ 24000000
+#define PL011_UART2_CLK_IN_HZ 24000000
+#define PL011_UART3_CLK_IN_HZ 24000000
+
+/*******************************************************************************
+ * TrustZone address space controller related constants
+ ******************************************************************************/
+#define TZC400_BASE                    0x2a4a0000
+
+/*
+ * The NSAIDs for this platform as used to program the TZC400.
+ */
+
+/* NSAIDs used by devices in TZC filter 0 on FVP */
+#define FVP_NSAID_DEFAULT              0
+#define FVP_NSAID_PCI                  1
+#define FVP_NSAID_VIRTIO               8  /* from FVP v5.6 onwards */
+#define FVP_NSAID_AP                   9  /* Application Processors */
+#define FVP_NSAID_VIRTIO_OLD           15 /* until FVP v5.5 */
+
+/* NSAIDs used by devices in TZC filter 2 on FVP */
+#define FVP_NSAID_HDLCD0               2
+#define FVP_NSAID_CLCD                 7
+
+/*******************************************************************************
+ *  Shared Data
+ ******************************************************************************/
+
+/* Entrypoint mailboxes */
+#define MBOX_BASE              FVP_SHARED_MEM_BASE
+#define MBOX_SIZE              0x200
+
+/* Base address where parameters to BL31 are stored */
+#define PARAMS_BASE            (MBOX_BASE + MBOX_SIZE)
+
+#endif /* __FVP_DEF_H__ */
diff --git a/plat/fvp/fvp_io_storage.c b/plat/fvp/fvp_io_storage.c
new file mode 100644 (file)
index 0000000..ec1fe58
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <io_semihosting.h>
+#include <platform_def.h>
+#include <semihosting.h>       /* For FOPEN_MODE_... */
+#include <string.h>
+
+/* IO devices */
+static const io_dev_connector_t *sh_dev_con;
+static uintptr_t sh_dev_spec;
+static uintptr_t sh_init_params;
+static uintptr_t sh_dev_handle;
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_spec;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_spec;
+static uintptr_t memmap_init_params;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+       .offset = FLASH0_BASE,
+       .length = FLASH0_SIZE
+};
+
+static const io_file_spec_t bl2_file_spec = {
+       .path = BL2_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_file_spec = {
+       .path = BL31_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_file_spec = {
+       .path = BL32_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_file_spec = {
+       .path = BL33_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_file_spec_t bl2_cert_file_spec = {
+       .path = BL2_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t trusted_key_cert_file_spec = {
+       .path = TRUSTED_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_key_cert_file_spec = {
+       .path = BL30_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_key_cert_file_spec = {
+       .path = BL31_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_key_cert_file_spec = {
+       .path = BL32_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_key_cert_file_spec = {
+       .path = BL33_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_cert_file_spec = {
+       .path = BL30_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_cert_file_spec = {
+       .path = BL31_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_cert_file_spec = {
+       .path = BL32_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_cert_file_spec = {
+       .path = BL33_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+       char *image_name;
+       uintptr_t *dev_handle;
+       uintptr_t image_spec;
+       int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+       {
+               FIP_IMAGE_NAME,
+               &memmap_dev_handle,
+               (uintptr_t)&fip_block_spec,
+               open_memmap
+       }, {
+               BL2_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl2_file_spec,
+               open_fip
+       }, {
+               BL31_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl31_file_spec,
+               open_fip
+       }, {
+               BL32_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl32_file_spec,
+               open_fip
+       }, {
+               BL33_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl33_file_spec,
+               open_fip
+       }, {
+#if TRUSTED_BOARD_BOOT
+               BL2_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl2_cert_file_spec,
+               open_fip
+       }, {
+               TRUSTED_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&trusted_key_cert_file_spec,
+               open_fip
+       }, {
+               BL30_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl30_key_cert_file_spec,
+               open_fip
+       }, {
+               BL31_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl31_key_cert_file_spec,
+               open_fip
+       }, {
+               BL32_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl32_key_cert_file_spec,
+               open_fip
+       }, {
+               BL33_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl33_key_cert_file_spec,
+               open_fip
+       }, {
+               BL30_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl30_cert_file_spec,
+               open_fip
+       }, {
+               BL31_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl31_cert_file_spec,
+               open_fip
+       }, {
+               BL32_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl32_cert_file_spec,
+               open_fip
+       }, {
+               BL33_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl33_cert_file_spec,
+               open_fip
+       }, {
+#endif /* TRUSTED_BOARD_BOOT */
+               0, 0, 0
+       }
+};
+
+
+static int open_fip(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+
+       /* See if a Firmware Image Package is available */
+       result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_NAME);
+       if (result == IO_SUCCESS) {
+               VERBOSE("Using FIP\n");
+               /*TODO: Check image defined in spec is present in FIP. */
+       }
+       return result;
+}
+
+
+static int open_memmap(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+       uintptr_t local_image_handle;
+
+       result = io_dev_init(memmap_dev_handle, memmap_init_params);
+       if (result == IO_SUCCESS) {
+               result = io_open(memmap_dev_handle, spec, &local_image_handle);
+               if (result == IO_SUCCESS) {
+                       VERBOSE("Using Memmap IO\n");
+                       io_close(local_image_handle);
+               }
+       }
+       return result;
+}
+
+
+static int open_semihosting(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+       uintptr_t local_image_handle;
+
+       /* See if the file exists on semi-hosting.*/
+       result = io_dev_init(sh_dev_handle, sh_init_params);
+       if (result == IO_SUCCESS) {
+               result = io_open(sh_dev_handle, spec, &local_image_handle);
+               if (result == IO_SUCCESS) {
+                       VERBOSE("Using Semi-hosting IO\n");
+                       io_close(local_image_handle);
+               }
+       }
+       return result;
+}
+
+void fvp_io_setup (void)
+{
+       int io_result = IO_FAIL;
+
+       /* Register the IO devices on this platform */
+       io_result = register_io_dev_sh(&sh_dev_con);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = register_io_dev_fip(&fip_dev_con);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = register_io_dev_memmap(&memmap_dev_con);
+       assert(io_result == IO_SUCCESS);
+
+       /* Open connections to devices and cache the handles */
+       io_result = io_dev_open(sh_dev_con, sh_dev_spec, &sh_dev_handle);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = io_dev_open(memmap_dev_con, memmap_dev_spec,
+                               &memmap_dev_handle);
+       assert(io_result == IO_SUCCESS);
+
+       /* Ignore improbable errors in release builds */
+       (void)io_result;
+}
+
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy */
+int plat_get_image_source(const char *image_name, uintptr_t *dev_handle,
+                         uintptr_t *image_spec)
+{
+       int result = IO_FAIL;
+       const struct plat_io_policy *policy;
+
+       if ((image_name != NULL) && (dev_handle != NULL) &&
+           (image_spec != NULL)) {
+               policy = policies;
+               while (policy->image_name != NULL) {
+                       if (strcmp(policy->image_name, image_name) == 0) {
+                               result = policy->check(policy->image_spec);
+                               if (result == IO_SUCCESS) {
+                                       *image_spec = policy->image_spec;
+                                       *dev_handle = *(policy->dev_handle);
+                                       break;
+                               } else {
+                                       result = open_semihosting(
+                                                       policy->image_spec);
+                                       if (result == IO_SUCCESS) {
+                                               *dev_handle = sh_dev_handle;
+                                               *image_spec =
+                                                       policy->image_spec;
+                                       }
+                               }
+                       }
+                       policy++;
+               }
+       } else {
+               result = IO_FAIL;
+       }
+       return result;
+}
diff --git a/plat/fvp/fvp_pm.c b/plat/fvp/fvp_pm.c
new file mode 100644 (file)
index 0000000..9044e69
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bakery_lock.h>
+#include <cci400.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <plat_config.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <errno.h>
+#include "drivers/pwrc/fvp_pwrc.h"
+#include "fvp_def.h"
+#include "fvp_private.h"
+
+/*******************************************************************************
+ * Private FVP function to program the mailbox for a cpu before it is released
+ * from reset.
+ ******************************************************************************/
+static void fvp_program_mailbox(uint64_t mpidr, uint64_t address)
+{
+       uint64_t linear_id;
+       mailbox_t *fvp_mboxes;
+
+       linear_id = platform_get_core_pos(mpidr);
+       fvp_mboxes = (mailbox_t *)MBOX_BASE;
+       fvp_mboxes[linear_id].value = address;
+       flush_dcache_range((unsigned long) &fvp_mboxes[linear_id],
+                          sizeof(unsigned long));
+}
+
+/*******************************************************************************
+ * Function which implements the common FVP specific operations to power down a
+ * cpu in response to a CPU_OFF or CPU_SUSPEND request.
+ ******************************************************************************/
+static void fvp_cpu_pwrdwn_common()
+{
+       /* Prevent interrupts from spuriously waking up this cpu */
+       arm_gic_cpuif_deactivate();
+
+       /* Program the power controller to power off this cpu. */
+       fvp_pwrc_write_ppoffr(read_mpidr_el1());
+}
+
+/*******************************************************************************
+ * Function which implements the common FVP specific operations to power down a
+ * cluster in response to a CPU_OFF or CPU_SUSPEND request.
+ ******************************************************************************/
+static void fvp_cluster_pwrdwn_common()
+{
+       uint64_t mpidr = read_mpidr_el1();
+
+       /* Disable coherency if this cluster is to be turned off */
+       if (get_plat_config()->flags & CONFIG_HAS_CCI)
+               cci_disable_cluster_coherency(mpidr);
+
+       /* Program the power controller to turn the cluster off */
+       fvp_pwrc_write_pcoffr(mpidr);
+}
+
+/*******************************************************************************
+ * Private FVP function which is used to determine if any platform actions
+ * should be performed for the specified affinity instance given its
+ * state. Nothing needs to be done if the 'state' is not off or if this is not
+ * the highest affinity level which will enter the 'state'.
+ ******************************************************************************/
+static int32_t fvp_do_plat_actions(unsigned int afflvl, unsigned int state)
+{
+       unsigned int max_phys_off_afflvl;
+
+       assert(afflvl <= MPIDR_AFFLVL1);
+
+       if (state != PSCI_STATE_OFF)
+               return -EAGAIN;
+
+       /*
+        * Find the highest affinity level which will be suspended and postpone
+        * all the platform specific actions until that level is hit.
+        */
+       max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
+       assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
+       if (afflvl != max_phys_off_afflvl)
+               return -EAGAIN;
+
+       return 0;
+}
+
+/*******************************************************************************
+ * FVP handler called when an affinity instance is about to enter standby.
+ ******************************************************************************/
+void fvp_affinst_standby(unsigned int power_state)
+{
+       /*
+        * Enter standby state
+        * dsb is good practice before using wfi to enter low power states
+        */
+       dsb();
+       wfi();
+}
+
+/*******************************************************************************
+ * FVP handler called when an affinity instance is about to be turned on. The
+ * level and mpidr determine the affinity instance.
+ ******************************************************************************/
+int fvp_affinst_on(unsigned long mpidr,
+                  unsigned long sec_entrypoint,
+                  unsigned int afflvl,
+                  unsigned int state)
+{
+       int rc = PSCI_E_SUCCESS;
+       unsigned int psysr;
+
+       /*
+        * It's possible to turn on only affinity level 0 i.e. a cpu
+        * on the FVP. Ignore any other affinity level.
+        */
+       if (afflvl != MPIDR_AFFLVL0)
+               return rc;
+
+       /*
+        * Ensure that we do not cancel an inflight power off request
+        * for the target cpu. That would leave it in a zombie wfi.
+        * Wait for it to power off, program the jump address for the
+        * target cpu and then program the power controller to turn
+        * that cpu on
+        */
+       do {
+               psysr = fvp_pwrc_read_psysr(mpidr);
+       } while (psysr & PSYSR_AFF_L0);
+
+       fvp_program_mailbox(mpidr, sec_entrypoint);
+       fvp_pwrc_write_pponr(mpidr);
+
+       return rc;
+}
+
+/*******************************************************************************
+ * FVP handler called when an affinity instance is about to be turned off. The
+ * level and mpidr determine the affinity instance. The 'state' arg. allows the
+ * platform to decide whether the cluster is being turned off and take apt
+ * actions.
+ *
+ * CAUTION: There is no guarantee that caches will remain turned on across calls
+ * to this function as each affinity level is dealt with. So do not write & read
+ * global variables across calls. It will be wise to do flush a write to the
+ * global to prevent unpredictable results.
+ ******************************************************************************/
+void fvp_affinst_off(unsigned int afflvl,
+                   unsigned int state)
+{
+       /* Determine if any platform actions need to be executed */
+       if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       /*
+        * If execution reaches this stage then this affinity level will be
+        * suspended. Perform at least the cpu specific actions followed the
+        * cluster specific operations if applicable.
+        */
+       fvp_cpu_pwrdwn_common();
+
+       if (afflvl != MPIDR_AFFLVL0)
+               fvp_cluster_pwrdwn_common();
+
+}
+
+/*******************************************************************************
+ * FVP handler called when an affinity instance is about to be suspended. The
+ * level and mpidr determine the affinity instance. The 'state' arg. allows the
+ * platform to decide whether the cluster is being turned off and take apt
+ * actions.
+ *
+ * CAUTION: There is no guarantee that caches will remain turned on across calls
+ * to this function as each affinity level is dealt with. So do not write & read
+ * global variables across calls. It will be wise to do flush a write to the
+ * global to prevent unpredictable results.
+ ******************************************************************************/
+void fvp_affinst_suspend(unsigned long sec_entrypoint,
+                       unsigned int afflvl,
+                       unsigned int state)
+{
+       unsigned long mpidr;
+
+       /* Determine if any platform actions need to be executed. */
+       if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       /* Get the mpidr for this cpu */
+       mpidr = read_mpidr_el1();
+
+       /* Program the jump address for the this cpu */
+       fvp_program_mailbox(mpidr, sec_entrypoint);
+
+       /* Program the power controller to enable wakeup interrupts. */
+       fvp_pwrc_set_wen(mpidr);
+
+       /* Perform the common cpu specific operations */
+       fvp_cpu_pwrdwn_common();
+
+       /* Perform the common cluster specific operations */
+       if (afflvl != MPIDR_AFFLVL0)
+               fvp_cluster_pwrdwn_common();
+}
+
+/*******************************************************************************
+ * FVP handler called when an affinity instance has just been powered on after
+ * being turned off earlier. The level and mpidr determine the affinity
+ * instance. The 'state' arg. allows the platform to decide whether the cluster
+ * was turned off prior to wakeup and do what's necessary to setup it up
+ * correctly.
+ ******************************************************************************/
+void fvp_affinst_on_finish(unsigned int afflvl,
+                         unsigned int state)
+{
+       unsigned long mpidr;
+
+       /* Determine if any platform actions need to be executed. */
+       if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       /* Get the mpidr for this cpu */
+       mpidr = read_mpidr_el1();
+
+       /* Perform the common cluster specific operations */
+       if (afflvl != MPIDR_AFFLVL0) {
+               /*
+                * This CPU might have woken up whilst the cluster was
+                * attempting to power down. In this case the FVP power
+                * controller will have a pending cluster power off request
+                * which needs to be cleared by writing to the PPONR register.
+                * This prevents the power controller from interpreting a
+                * subsequent entry of this cpu into a simple wfi as a power
+                * down request.
+                */
+               fvp_pwrc_write_pponr(mpidr);
+
+               /* Enable coherency if this cluster was off */
+               fvp_cci_enable();
+       }
+
+       /*
+        * Clear PWKUPR.WEN bit to ensure interrupts do not interfere
+        * with a cpu power down unless the bit is set again
+        */
+       fvp_pwrc_clr_wen(mpidr);
+
+       /* Zero the jump address in the mailbox for this cpu */
+       fvp_program_mailbox(mpidr, 0);
+
+       /* Enable the gic cpu interface */
+       arm_gic_cpuif_setup();
+
+       /* TODO: This setup is needed only after a cold boot */
+       arm_gic_pcpu_distif_setup();
+}
+
+/*******************************************************************************
+ * FVP handler called when an affinity instance has just been powered on after
+ * having been suspended earlier. The level and mpidr determine the affinity
+ * instance.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+void fvp_affinst_suspend_finish(unsigned int afflvl,
+                              unsigned int state)
+{
+       fvp_affinst_on_finish(afflvl, state);
+}
+
+/*******************************************************************************
+ * FVP handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 fvp_system_off(void)
+{
+       /* Write the System Configuration Control Register */
+       mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL,
+               CFGCTRL_START | CFGCTRL_RW | CFGCTRL_FUNC(FUNC_SHUTDOWN));
+       wfi();
+       ERROR("FVP System Off: operation not handled.\n");
+       panic();
+}
+
+static void __dead2 fvp_system_reset(void)
+{
+       /* Write the System Configuration Control Register */
+       mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL,
+               CFGCTRL_START | CFGCTRL_RW | CFGCTRL_FUNC(FUNC_REBOOT));
+       wfi();
+       ERROR("FVP System Reset: operation not handled.\n");
+       panic();
+}
+
+/*******************************************************************************
+ * FVP handler called to check the validity of the power state parameter.
+ ******************************************************************************/
+int fvp_validate_power_state(unsigned int power_state)
+{
+       /* Sanity check the requested state */
+       if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) {
+               /*
+                * It's possible to enter standby only on affinity level 0
+                * i.e. a cpu on the fvp. Ignore any other affinity level.
+                */
+               if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0)
+                       return PSCI_E_INVALID_PARAMS;
+       }
+
+       /*
+        * We expect the 'state id' to be zero.
+        */
+       if (psci_get_pstate_id(power_state))
+               return PSCI_E_INVALID_PARAMS;
+
+       return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static const plat_pm_ops_t fvp_plat_pm_ops = {
+       .affinst_standby = fvp_affinst_standby,
+       .affinst_on = fvp_affinst_on,
+       .affinst_off = fvp_affinst_off,
+       .affinst_suspend = fvp_affinst_suspend,
+       .affinst_on_finish = fvp_affinst_on_finish,
+       .affinst_suspend_finish = fvp_affinst_suspend_finish,
+       .system_off = fvp_system_off,
+       .system_reset = fvp_system_reset,
+       .validate_power_state = fvp_validate_power_state
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops & initialize the fvp power controller
+ ******************************************************************************/
+int platform_setup_pm(const plat_pm_ops_t **plat_ops)
+{
+       *plat_ops = &fvp_plat_pm_ops;
+       return 0;
+}
diff --git a/plat/fvp/fvp_private.h b/plat/fvp/fvp_private.h
new file mode 100644 (file)
index 0000000..3949754
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FVP_PRIVATE_H__
+#define __FVP_PRIVATE_H__
+
+#include <bakery_lock.h>
+#include <bl_common.h>
+#include <cpu_data.h>
+#include <platform_def.h>
+
+
+typedef volatile struct mailbox {
+       unsigned long value
+       __attribute__((__aligned__(CACHE_WRITEBACK_GRANULE)));
+} mailbox_t;
+
+/*******************************************************************************
+ * This structure represents the superset of information that is passed to
+ * BL31 e.g. while passing control to it from BL2 which is bl31_params
+ * and bl31_plat_params and its elements
+ ******************************************************************************/
+typedef struct bl2_to_bl31_params_mem {
+       bl31_params_t bl31_params;
+       image_info_t bl31_image_info;
+       image_info_t bl32_image_info;
+       image_info_t bl33_image_info;
+       entry_point_info_t bl33_ep_info;
+       entry_point_info_t bl32_ep_info;
+       entry_point_info_t bl31_ep_info;
+} bl2_to_bl31_params_mem_t;
+
+#if USE_COHERENT_MEM
+/*
+ * These are wrapper macros to the Coherent Memory Bakery Lock API.
+ */
+#define fvp_lock_init(_lock_arg)       bakery_lock_init(_lock_arg)
+#define fvp_lock_get(_lock_arg)                bakery_lock_get(_lock_arg)
+#define fvp_lock_release(_lock_arg)    bakery_lock_release(_lock_arg)
+
+#else
+
+/*******************************************************************************
+ * Constants to specify how many bakery locks this platform implements. These
+ * are used if the platform chooses not to use coherent memory for bakery lock
+ * data structures.
+ ******************************************************************************/
+#define FVP_MAX_BAKERIES       1
+#define FVP_PWRC_BAKERY_ID     0
+
+/*******************************************************************************
+ * Definition of structure which holds platform specific per-cpu data. Currently
+ * it holds only the bakery lock information for each cpu. Constants to
+ * specify how many bakeries this platform implements and bakery ids are
+ * specified in fvp_def.h
+ ******************************************************************************/
+typedef struct fvp_cpu_data {
+       bakery_info_t pcpu_bakery_info[FVP_MAX_BAKERIES];
+} fvp_cpu_data_t;
+
+/* Macro to define the offset of bakery_info_t in fvp_cpu_data_t */
+#define FVP_CPU_DATA_LOCK_OFFSET       __builtin_offsetof\
+                                           (fvp_cpu_data_t, pcpu_bakery_info)
+
+
+/*******************************************************************************
+ * Helper macros for bakery lock api when using the above fvp_cpu_data_t for
+ * bakery lock data structures. It assumes that the bakery_info is at the
+ * beginning of the platform specific per-cpu data.
+ ******************************************************************************/
+#define fvp_lock_init(_lock_arg)       /* No init required */
+#define fvp_lock_get(_lock_arg)                bakery_lock_get(_lock_arg,          \
+                                               CPU_DATA_PLAT_PCPU_OFFSET + \
+                                               FVP_CPU_DATA_LOCK_OFFSET)
+#define fvp_lock_release(_lock_arg)    bakery_lock_release(_lock_arg,      \
+                                               CPU_DATA_PLAT_PCPU_OFFSET + \
+                                               FVP_CPU_DATA_LOCK_OFFSET)
+
+/*
+ * Ensure that the size of the FVP specific per-cpu data structure and the size
+ * of the memory allocated in generic per-cpu data for the platform are the same.
+ */
+CASSERT(PLAT_PCPU_DATA_SIZE == sizeof(fvp_cpu_data_t), \
+       fvp_pcpu_data_size_mismatch);
+
+#endif /* __USE_COHERENT_MEM__ */
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void fvp_configure_mmu_el1(unsigned long total_base,
+                          unsigned long total_size,
+                          unsigned long,
+                          unsigned long
+#if USE_COHERENT_MEM
+                          , unsigned long,
+                          unsigned long
+#endif
+                          );
+void fvp_configure_mmu_el3(unsigned long total_base,
+                          unsigned long total_size,
+                          unsigned long,
+                          unsigned long
+#if USE_COHERENT_MEM
+                          , unsigned long,
+                          unsigned long
+#endif
+                          );
+
+int fvp_config_setup(void);
+
+void fvp_cci_init(void);
+void fvp_cci_enable(void);
+
+void fvp_gic_init(void);
+
+/* Declarations for fvp_topology.c */
+int fvp_setup_topology(void);
+
+/* Declarations for fvp_io_storage.c */
+void fvp_io_setup(void);
+
+/* Declarations for fvp_security.c */
+void fvp_security_setup(void);
+
+/* Gets the SPR for BL32 entry */
+uint32_t fvp_get_spsr_for_bl32_entry(void);
+
+/* Gets the SPSR for BL33 entry */
+uint32_t fvp_get_spsr_for_bl33_entry(void);
+
+
+#endif /* __FVP_PRIVATE_H__ */
diff --git a/plat/fvp/fvp_security.c b/plat/fvp/fvp_security.c
new file mode 100644 (file)
index 0000000..62bde08
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <plat_config.h>
+#include <tzc400.h>
+#include "fvp_def.h"
+#include "fvp_private.h"
+
+/* Used to improve readability for configuring regions. */
+#define FILTER_SHIFT(filter)   (1 << filter)
+
+/*
+ * For the moment we assume that all security programming is done by the
+ * primary core.
+ * TODO:
+ * Might want to enable interrupt on violations when supported?
+ */
+void fvp_security_setup(void)
+{
+       /*
+        * The Base FVP has a TrustZone address space controller, the Foundation
+        * FVP does not. Trying to program the device on the foundation FVP will
+        * cause an abort.
+        *
+        * If the platform had additional peripheral specific security
+        * configurations, those would be configured here.
+        */
+
+       if (!(get_plat_config()->flags & CONFIG_HAS_TZC))
+               return;
+
+       /*
+        * The TrustZone controller controls access to main DRAM. Give
+        * full NS access for the moment to use with OS.
+        */
+       INFO("Configuring TrustZone Controller\n");
+
+       /*
+        * The driver does some error checking and will assert.
+        * - Provide base address of device on platform.
+        * - Provide width of ACE-Lite IDs on platform.
+        */
+       tzc_init(TZC400_BASE);
+
+       /*
+        * Currently only filters 0 and 2 are connected on Base FVP.
+        * Filter 0 : CPU clusters (no access to DRAM by default)
+        * Filter 1 : not connected
+        * Filter 2 : LCDs (access to VRAM allowed by default)
+        * Filter 3 : not connected
+        * Programming unconnected filters will have no effect at the
+        * moment. These filter could, however, be connected in future.
+        * So care should be taken not to configure the unused filters.
+        */
+
+       /* Disable all filters before programming. */
+       tzc_disable_filters();
+
+       /*
+        * Allow only non-secure access to all DRAM to supported devices.
+        * Give access to the CPUs and Virtio. Some devices
+        * would normally use the default ID so allow that too. We use
+        * two regions to cover the blocks of physical memory in the FVPs
+        * plus one region to reserve some memory as secure.
+        *
+        * Software executing in the secure state, such as a secure
+        * boot-loader, can access the DRAM by using the NS attributes in
+        * the MMU translation tables and descriptors.
+        */
+
+       /* Region 1 set to cover the Non-Secure DRAM */
+       tzc_configure_region(FILTER_SHIFT(0), 1,
+                       DRAM1_NS_BASE, DRAM1_NS_END,
+                       TZC_REGION_S_NONE,
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) |
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_PCI) |
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) |
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO) |
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD));
+
+       /* Region 2 set to cover the Secure DRAM */
+       tzc_configure_region(FILTER_SHIFT(0), 2,
+                       DRAM1_SEC_BASE, DRAM1_SEC_END,
+                       TZC_REGION_S_RDWR,
+                       0x0);
+
+       /* Region 3 set to cover the second block of DRAM */
+       tzc_configure_region(FILTER_SHIFT(0), 3,
+                       DRAM2_BASE, DRAM2_END, TZC_REGION_S_NONE,
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) |
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_PCI) |
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) |
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO) |
+                       TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD));
+
+       /*
+        * TODO: Interrupts are not currently supported. The only
+        * options we have are for access errors to occur quietly or to
+        * cause an exception. We choose to cause an exception.
+        */
+       tzc_set_action(TZC_ACTION_ERR);
+
+       /* Enable filters. */
+       tzc_enable_filters();
+}
diff --git a/plat/fvp/fvp_topology.c b/plat/fvp/fvp_topology.c
new file mode 100644 (file)
index 0000000..49f7daf
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <platform_def.h>
+/* TODO: Reusing psci error codes & state information. Get our own! */
+#include <psci.h>
+#include "drivers/pwrc/fvp_pwrc.h"
+
+/* We treat '255' as an invalid affinity instance */
+#define AFFINST_INVAL  0xff
+
+/*******************************************************************************
+ * We support 3 flavours of the FVP: Foundation, Base AEM & Base Cortex. Each
+ * flavour has a different topology. The common bit is that there can be a max.
+ * of 2 clusters (affinity 1) and 4 cpus (affinity 0) per cluster. So we define
+ * a tree like data structure which caters to these maximum bounds. It simply
+ * marks the absent affinity level instances as PSCI_AFF_ABSENT e.g. there is no
+ * cluster 1 on the Foundation FVP. The 'data' field is currently unused.
+ ******************************************************************************/
+typedef struct affinity_info {
+       unsigned char sibling;
+       unsigned char child;
+       unsigned char state;
+       unsigned int data;
+} affinity_info_t;
+
+/*******************************************************************************
+ * The following two data structures store the topology tree for the fvp. There
+ * is a separate array for each affinity level i.e. cpus and clusters. The child
+ * and sibling references allow traversal inside and in between the two arrays.
+ ******************************************************************************/
+static affinity_info_t fvp_aff1_topology_map[PLATFORM_CLUSTER_COUNT];
+static affinity_info_t fvp_aff0_topology_map[PLATFORM_CORE_COUNT];
+
+/* Simple global variable to safeguard us from stupidity */
+static unsigned int topology_setup_done;
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform to allow the former to detect the platform
+ * topology. psci queries the platform to determine how many affinity instances
+ * are present at a particular level for a given mpidr e.g. consider a dual
+ * cluster platform where each cluster has 4 cpus. A call to this function with
+ * (0, 0x100) will return the number of cpus implemented under cluster 1 i.e. 4.
+ * Similarly a call with (1, 0x100) will return 2 i.e. the number of clusters.
+ * This is 'cause we are effectively asking how many affinity level 1 instances
+ * are implemented under affinity level 2 instance 0.
+ ******************************************************************************/
+unsigned int plat_get_aff_count(unsigned int aff_lvl,
+                               unsigned long mpidr)
+{
+       unsigned int aff_count = 1, ctr;
+       unsigned char parent_aff_id;
+
+       assert(topology_setup_done == 1);
+
+       switch (aff_lvl) {
+       case 3:
+       case 2:
+               /*
+                * Assert if the parent affinity instance is not 0.
+                * This also takes care of level 3 in an obfuscated way
+                */
+               parent_aff_id = (mpidr >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK;
+               assert(parent_aff_id == 0);
+
+               /*
+                * Report that we implement a single instance of
+                * affinity levels 2 & 3 which are AFF_ABSENT
+                */
+               break;
+       case 1:
+               /* Assert if the parent affinity instance is not 0. */
+               parent_aff_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK;
+               assert(parent_aff_id == 0);
+
+               /* Fetch the starting index in the aff1 array */
+               for (ctr = 0;
+                    fvp_aff1_topology_map[ctr].sibling != AFFINST_INVAL;
+                    ctr = fvp_aff1_topology_map[ctr].sibling) {
+                       aff_count++;
+               }
+
+               break;
+       case 0:
+               /* Assert if the cluster id is anything apart from 0 or 1 */
+               parent_aff_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+               assert(parent_aff_id < PLATFORM_CLUSTER_COUNT);
+
+               /* Fetch the starting index in the aff0 array */
+               for (ctr = fvp_aff1_topology_map[parent_aff_id].child;
+                    fvp_aff0_topology_map[ctr].sibling != AFFINST_INVAL;
+                    ctr = fvp_aff0_topology_map[ctr].sibling) {
+                       aff_count++;
+               }
+
+               break;
+       default:
+               assert(0);
+       }
+
+       return aff_count;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform to allow the former to detect the state of a
+ * affinity instance in the platform topology. psci queries the platform to
+ * determine whether an affinity instance is present or absent. This caters for
+ * topologies where an intermediate affinity level instance is missing e.g.
+ * consider a platform which implements a single cluster with 4 cpus and there
+ * is another cpu sitting directly on the interconnect along with the cluster.
+ * The mpidrs of the cluster would range from 0x0-0x3. The mpidr of the single
+ * cpu would be 0x100 to highlight that it does not belong to cluster 0. Cluster
+ * 1 is however missing but needs to be accounted to reach this single cpu in
+ * the topology tree. Hence it will be marked as PSCI_AFF_ABSENT. This is not
+ * applicable to the FVP but depicted as an example.
+ ******************************************************************************/
+unsigned int plat_get_aff_state(unsigned int aff_lvl,
+                               unsigned long mpidr)
+{
+       unsigned int aff_state = PSCI_AFF_ABSENT, idx;
+       idx = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+
+       assert(topology_setup_done == 1);
+
+       switch (aff_lvl) {
+       case 3:
+       case 2:
+               /* Report affinity levels 2 & 3 as absent */
+               break;
+       case 1:
+               aff_state = fvp_aff1_topology_map[idx].state;
+               break;
+       case 0:
+               /*
+                * First get start index of the aff0 in its array & then add
+                * to it the affinity id that we want the state of
+                */
+               idx = fvp_aff1_topology_map[idx].child;
+               idx += (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+               aff_state = fvp_aff0_topology_map[idx].state;
+               break;
+       default:
+               assert(0);
+       }
+
+       return aff_state;
+}
+
+/*******************************************************************************
+ * Handy optimization to prevent the psci implementation from traversing through
+ * affinity levels which are not present while detecting the platform topology.
+ ******************************************************************************/
+int plat_get_max_afflvl(void)
+{
+       return MPIDR_AFFLVL1;
+}
+
+/*******************************************************************************
+ * This function populates the FVP specific topology information depending upon
+ * the FVP flavour its running on. We construct all the mpidrs we can handle
+ * and rely on the PWRC.PSYSR to flag absent cpus when their status is queried.
+ ******************************************************************************/
+int fvp_setup_topology(void)
+{
+       unsigned char aff0, aff1, aff_state, aff0_offset = 0;
+       unsigned long mpidr;
+
+       topology_setup_done = 0;
+
+       for (aff1 = 0; aff1 < PLATFORM_CLUSTER_COUNT; aff1++) {
+
+               fvp_aff1_topology_map[aff1].child = aff0_offset;
+               fvp_aff1_topology_map[aff1].sibling = aff1 + 1;
+
+               for (aff0 = 0; aff0 < PLATFORM_MAX_CPUS_PER_CLUSTER; aff0++) {
+
+                       mpidr = aff1 << MPIDR_AFF1_SHIFT;
+                       mpidr |= aff0 << MPIDR_AFF0_SHIFT;
+
+                       if (fvp_pwrc_read_psysr(mpidr) != PSYSR_INVALID) {
+                               /*
+                                * Presence of even a single aff0 indicates
+                                * presence of parent aff1 on the FVP.
+                                */
+                               aff_state = PSCI_AFF_PRESENT;
+                               fvp_aff1_topology_map[aff1].state =
+                                       PSCI_AFF_PRESENT;
+                       } else {
+                               aff_state = PSCI_AFF_ABSENT;
+                       }
+
+                       fvp_aff0_topology_map[aff0_offset].child = AFFINST_INVAL;
+                       fvp_aff0_topology_map[aff0_offset].state = aff_state;
+                       fvp_aff0_topology_map[aff0_offset].sibling =
+                               aff0_offset + 1;
+
+                       /* Increment the absolute number of aff0s traversed */
+                       aff0_offset++;
+               }
+
+               /* Tie-off the last aff0 sibling to -1 to avoid overflow */
+               fvp_aff0_topology_map[aff0_offset - 1].sibling = AFFINST_INVAL;
+       }
+
+       /* Tie-off the last aff1 sibling to AFFINST_INVAL to avoid overflow */
+       fvp_aff1_topology_map[aff1 - 1].sibling = AFFINST_INVAL;
+
+       topology_setup_done = 1;
+       return 0;
+}
diff --git a/plat/fvp/fvp_trusted_boot.c b/plat/fvp/fvp_trusted_boot.c
new file mode 100644 (file)
index 0000000..e7dcc01
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include "fvp_def.h"
+#include "fvp_private.h"
+
+/*
+ * Check the validity of the key
+ *
+ * 0 = success, Otherwise = error
+ */
+int plat_match_rotpk(const unsigned char *key_buf, unsigned int key_len)
+{
+       /* TODO: check against the ROT key stored in the platform */
+       return 0;
+}
diff --git a/plat/fvp/include/plat_macros.S b/plat/fvp/include/plat_macros.S
new file mode 100644 (file)
index 0000000..f050261
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <cci400.h>
+#include <gic_v2.h>
+#include <plat_config.h>
+#include "../fvp_def.h"
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+       .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+       .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+       .asciz "\n"
+spacer:
+       .asciz ":\t\t0x"
+
+       /* ---------------------------------------------
+        * The below macro prints out relevant GIC
+        * registers whenever an unhandled exception is
+        * taken in BL3-1.
+        * Clobbers: x0 - x10, x16, x17, sp
+        * ---------------------------------------------
+        */
+       .macro plat_print_gic_regs
+       mov_imm x0, (VE_SYSREGS_BASE + V2M_SYS_ID)
+       ldr     w16, [x0]
+       /* Extract BLD (12th - 15th bits) from the SYS_ID */
+       ubfx    x16, x16, #SYS_ID_BLD_SHIFT, #4
+       /* Check if VE mmap */
+       cmp     w16, #BLD_GIC_VE_MMAP
+       b.eq    use_ve_mmap
+       /* Check if Cortex-A53/A57 mmap */
+       cmp     w16, #BLD_GIC_A53A57_MMAP
+       b.ne    exit_print_gic_regs
+       mov_imm x17, BASE_GICC_BASE
+       mov_imm x16, BASE_GICD_BASE
+       b       print_gicc_regs
+use_ve_mmap:
+       mov_imm x17, VE_GICC_BASE
+       mov_imm x16, VE_GICD_BASE
+print_gicc_regs:
+       /* gicc base address is now in x17 */
+       adr     x6, gicc_regs   /* Load the gicc reg list to x6 */
+       /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+       ldr     w8, [x17, #GICC_HPPIR]
+       ldr     w9, [x17, #GICC_AHPPIR]
+       ldr     w10, [x17, #GICC_CTLR]
+       /* Store to the crash buf and print to console */
+       bl      str_in_crash_buf_print
+
+       /* Print the GICD_ISPENDR regs */
+       add     x7, x16, #GICD_ISPENDR
+       adr     x4, gicd_pend_reg
+       bl      asm_print_str
+gicd_ispendr_loop:
+       sub     x4, x7, x16
+       cmp     x4, #0x280
+       b.eq    exit_print_gic_regs
+       bl      asm_print_hex
+       adr     x4, spacer
+       bl      asm_print_str
+       ldr     x4, [x7], #8
+       bl      asm_print_hex
+       adr     x4, newline
+       bl      asm_print_str
+       b       gicd_ispendr_loop
+exit_print_gic_regs:
+       .endm
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+       .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+       /* ------------------------------------------------
+        * The below macro prints out relevant interconnect
+        * registers whenever an unhandled exception is
+        * taken in BL3-1.
+        * Clobbers: x0 - x9, sp
+        * ------------------------------------------------
+        */
+       .macro plat_print_interconnect_regs
+       adr     x6, cci_iface_regs
+       /* Store in x7 the base address of the first interface */
+       mov_imm x7, (CCI400_BASE + SLAVE_IFACE3_OFFSET)
+       ldr     w8, [x7, #SNOOP_CTRL_REG]
+       /* Store in x7 the base address of the second interface */
+       mov_imm x7, (CCI400_BASE + SLAVE_IFACE4_OFFSET)
+       ldr     w9, [x7, #SNOOP_CTRL_REG]
+       /* Store to the crash buf and print to console */
+       bl      str_in_crash_buf_print
+       .endm
diff --git a/plat/fvp/include/platform_def.h b/plat/fvp/include/platform_def.h
new file mode 100644 (file)
index 0000000..182c150
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include "../fvp_def.h"
+
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT          "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH            aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#if TRUSTED_BOARD_BOOT
+#define PLATFORM_STACK_SIZE 0x1000
+#else
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+#elif IMAGE_BL2
+#if TRUSTED_BOARD_BOOT
+#define PLATFORM_STACK_SIZE 0x1000
+#else
+#define PLATFORM_STACK_SIZE 0x400
+#endif
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR           "Booting Trusted Firmware\n"
+
+/* Trusted Boot Firmware BL2 */
+#define BL2_IMAGE_NAME                 "bl2.bin"
+
+/* EL3 Runtime Firmware BL31 */
+#define BL31_IMAGE_NAME                        "bl31.bin"
+
+/* Secure Payload BL32 (Trusted OS) */
+#define BL32_IMAGE_NAME                        "bl32.bin"
+
+/* Non-Trusted Firmware BL33 */
+#define BL33_IMAGE_NAME                        "bl33.bin" /* e.g. UEFI */
+
+#if TRUSTED_BOARD_BOOT
+/* Certificates */
+# define BL2_CERT_NAME                 "bl2.crt"
+# define TRUSTED_KEY_CERT_NAME         "trusted_key.crt"
+
+# define BL30_KEY_CERT_NAME            "bl30_key.crt"
+# define BL31_KEY_CERT_NAME            "bl31_key.crt"
+# define BL32_KEY_CERT_NAME            "bl32_key.crt"
+# define BL33_KEY_CERT_NAME            "bl33_key.crt"
+
+# define BL30_CERT_NAME                        "bl30.crt"
+# define BL31_CERT_NAME                        "bl31.crt"
+# define BL32_CERT_NAME                        "bl32.crt"
+# define BL33_CERT_NAME                        "bl33.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+#define PLATFORM_CACHE_LINE_SIZE       64
+#define PLATFORM_CLUSTER_COUNT         2ull
+#define PLATFORM_CLUSTER0_CORE_COUNT   4
+#define PLATFORM_CLUSTER1_CORE_COUNT   4
+#define PLATFORM_CORE_COUNT            (PLATFORM_CLUSTER1_CORE_COUNT + \
+                                               PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER  4
+#define PLATFORM_NUM_AFFS              (PLATFORM_CLUSTER_COUNT + \
+                                        PLATFORM_CORE_COUNT)
+#define MAX_IO_DEVICES                 3
+#define MAX_IO_HANDLES                 4
+
+/*******************************************************************************
+ * BL1 specific defines.
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ ******************************************************************************/
+#define BL1_RO_BASE                    FVP_TRUSTED_ROM_BASE
+#define BL1_RO_LIMIT                   (FVP_TRUSTED_ROM_BASE \
+                                       + FVP_TRUSTED_ROM_SIZE)
+/*
+ * Put BL1 RW at the top of the Trusted SRAM. BL1_RW_BASE is calculated using
+ * the current BL1 RW debug size plus a little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+#define BL1_RW_BASE                    (FVP_TRUSTED_SRAM_BASE \
+                                       + FVP_TRUSTED_SRAM_SIZE - 0x8000)
+#else
+#define BL1_RW_BASE                    (FVP_TRUSTED_SRAM_BASE \
+                                       + FVP_TRUSTED_SRAM_SIZE - 0x6000)
+#endif
+#define BL1_RW_LIMIT                   (FVP_TRUSTED_SRAM_BASE \
+                                       + FVP_TRUSTED_SRAM_SIZE)
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+#define BL2_BASE                       (BL31_BASE - 0x1C000)
+#else
+#define BL2_BASE                       (BL31_BASE - 0xC000)
+#endif
+#define BL2_LIMIT                      BL31_BASE
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL3-1 debug size plus a little space for growth.
+ */
+#define BL31_BASE                      (FVP_TRUSTED_SRAM_BASE \
+                                       + FVP_TRUSTED_SRAM_SIZE - 0x1D000)
+#define BL31_PROGBITS_LIMIT            BL1_RW_BASE
+#define BL31_LIMIT                     (FVP_TRUSTED_SRAM_BASE \
+                                       + FVP_TRUSTED_SRAM_SIZE)
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+/*
+ * The TSP can execute either from Trusted SRAM or Trusted DRAM.
+ */
+#define BL32_SRAM_BASE                 FVP_TRUSTED_SRAM_BASE
+#define BL32_SRAM_LIMIT                        BL31_BASE
+#define BL32_DRAM_BASE                 FVP_TRUSTED_DRAM_BASE
+#define BL32_DRAM_LIMIT                        (FVP_TRUSTED_DRAM_BASE + (1 << 21))
+
+#if FVP_TSP_RAM_LOCATION_ID == FVP_IN_TRUSTED_SRAM
+# define TSP_SEC_MEM_BASE              FVP_TRUSTED_SRAM_BASE
+# define TSP_SEC_MEM_SIZE              FVP_TRUSTED_SRAM_SIZE
+# define TSP_PROGBITS_LIMIT            BL2_BASE
+# define BL32_BASE                     BL32_SRAM_BASE
+# define BL32_LIMIT                    BL32_SRAM_LIMIT
+#elif FVP_TSP_RAM_LOCATION_ID == FVP_IN_TRUSTED_DRAM
+# define TSP_SEC_MEM_BASE              FVP_TRUSTED_DRAM_BASE
+# define TSP_SEC_MEM_SIZE              FVP_TRUSTED_DRAM_SIZE
+# define BL32_BASE                     BL32_DRAM_BASE
+# define BL32_LIMIT                    BL32_DRAM_LIMIT
+#else
+# error "Unsupported FVP_TSP_RAM_LOCATION_ID value"
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the TSP.
+ */
+#define TSP_IRQ_SEC_PHY_TIMER          IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE                        (1ull << 32)
+
+#if IMAGE_BL1
+# define MAX_XLAT_TABLES               2
+#elif IMAGE_BL2
+# define MAX_XLAT_TABLES               3
+#elif IMAGE_BL31
+# define MAX_XLAT_TABLES               2
+#elif IMAGE_BL32
+# if FVP_TSP_RAM_LOCATION_ID == FVP_DRAM_ID
+#  define MAX_XLAT_TABLES              3
+# else
+#  define MAX_XLAT_TABLES              2
+# endif
+#endif
+
+#define MAX_MMAP_REGIONS               16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT   6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#if !USE_COHERENT_MEM
+/*******************************************************************************
+ * Size of the per-cpu data in bytes that should be reserved in the generic
+ * per-cpu data structure for the FVP port.
+ ******************************************************************************/
+#define PLAT_PCPU_DATA_SIZE    2
+#endif
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/fvp/include/platform_oid.h b/plat/fvp/include/platform_oid.h
new file mode 100644 (file)
index 0000000..38aca12
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PLATFORM_OID_H_
+#define PLATFORM_OID_H_
+
+/*
+ * This is the list of the different extensions containing relevant information
+ * to establish the chain of trust.
+ *
+ * The OIDs shown here are just an example. Real OIDs should be obtained from
+ * the ITU-T.
+ */
+
+/* Non-volatile counter extensions */
+#define TZ_FW_NVCOUNTER_OID            "1.2.3.1"
+#define NTZ_FW_NVCOUNTER_OID           "1.2.3.2"
+
+/* BL2 extensions */
+#define BL2_HASH_OID                   "1.2.3.3"
+
+/* Trusted Key extensions */
+#define TZ_WORLD_PK_OID                        "1.2.3.4"
+#define NTZ_WORLD_PK_OID               "1.2.3.5"
+
+/* BL3-1 extensions */
+#define BL31_CONTENT_CERT_PK_OID       "1.2.3.6"
+#define BL31_HASH_OID                  "1.2.3.7"
+
+/* BL3-0 extensions */
+#define BL30_CONTENT_CERT_PK_OID       "1.2.3.8"
+#define BL30_HASH_OID                  "1.2.3.9"
+
+/* BL3-2 extensions */
+#define BL32_CONTENT_CERT_PK_OID       "1.2.3.10"
+#define BL32_HASH_OID                  "1.2.3.11"
+
+/* BL3-3 extensions */
+#define BL33_CONTENT_CERT_PK_OID       "1.2.3.12"
+#define BL33_HASH_OID                  "1.2.3.13"
+
+#endif /* PLATFORM_OID_H_ */
diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk
new file mode 100644 (file)
index 0000000..bcee328
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+# On FVP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
+# Trusted SRAM is the default.
+FVP_TSP_RAM_LOCATION   :=      tsram
+ifeq (${FVP_TSP_RAM_LOCATION}, tsram)
+  FVP_TSP_RAM_LOCATION_ID := FVP_TRUSTED_SRAM_ID
+else ifeq (${FVP_TSP_RAM_LOCATION}, tdram)
+  FVP_TSP_RAM_LOCATION_ID := FVP_TRUSTED_DRAM_ID
+else ifeq (${FVP_TSP_RAM_LOCATION}, dram)
+  FVP_TSP_RAM_LOCATION_ID := FVP_DRAM_ID
+else
+  $(error "Unsupported FVP_TSP_RAM_LOCATION value")
+endif
+
+# Process flags
+$(eval $(call add_define,FVP_TSP_RAM_LOCATION_ID))
+
+PLAT_INCLUDES          :=      -Iplat/fvp/include/
+
+PLAT_BL_COMMON_SOURCES :=      drivers/arm/pl011/pl011_console.S               \
+                               drivers/io/io_fip.c                             \
+                               drivers/io/io_memmap.c                          \
+                               drivers/io/io_semihosting.c                     \
+                               drivers/io/io_storage.c                         \
+                               lib/aarch64/xlat_tables.c                       \
+                               lib/semihosting/semihosting.c                   \
+                               lib/semihosting/aarch64/semihosting_call.S      \
+                               plat/common/aarch64/plat_common.c               \
+                               plat/fvp/fvp_io_storage.c
+
+BL1_SOURCES            +=      drivers/arm/cci400/cci400.c                     \
+                               lib/cpus/aarch64/aem_generic.S                  \
+                               lib/cpus/aarch64/cortex_a53.S                   \
+                               lib/cpus/aarch64/cortex_a57.S                   \
+                               plat/common/aarch64/platform_up_stack.S         \
+                               plat/fvp/bl1_fvp_setup.c                        \
+                               plat/fvp/aarch64/fvp_common.c                   \
+                               plat/fvp/aarch64/fvp_helpers.S
+
+BL2_SOURCES            +=      drivers/arm/tzc400/tzc400.c                     \
+                               plat/common/aarch64/platform_up_stack.S         \
+                               plat/fvp/bl2_fvp_setup.c                        \
+                               plat/fvp/fvp_security.c                         \
+                               plat/fvp/aarch64/fvp_common.c
+
+BL31_SOURCES           +=      drivers/arm/cci400/cci400.c                     \
+                               drivers/arm/gic/arm_gic.c                       \
+                               drivers/arm/gic/gic_v2.c                        \
+                               drivers/arm/gic/gic_v3.c                        \
+                               drivers/arm/tzc400/tzc400.c                     \
+                               lib/cpus/aarch64/aem_generic.S                  \
+                               lib/cpus/aarch64/cortex_a53.S                   \
+                               lib/cpus/aarch64/cortex_a57.S                   \
+                               plat/common/plat_gic.c                          \
+                               plat/common/aarch64/platform_mp_stack.S         \
+                               plat/fvp/bl31_fvp_setup.c                       \
+                               plat/fvp/fvp_pm.c                               \
+                               plat/fvp/fvp_security.c                         \
+                               plat/fvp/fvp_topology.c                         \
+                               plat/fvp/aarch64/fvp_helpers.S                  \
+                               plat/fvp/aarch64/fvp_common.c                   \
+                               plat/fvp/drivers/pwrc/fvp_pwrc.c
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+  BL1_SOURCES          +=      plat/fvp/fvp_trusted_boot.c
+  BL2_SOURCES          +=      plat/fvp/fvp_trusted_boot.c
+endif
diff --git a/plat/fvp/tsp/tsp-fvp.mk b/plat/fvp/tsp/tsp-fvp.mk
new file mode 100644 (file)
index 0000000..d2e112a
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+# TSP source files specific to FVP platform
+BL32_SOURCES           +=      drivers/arm/gic/arm_gic.c                       \
+                               drivers/arm/gic/gic_v2.c                        \
+                               plat/common/aarch64/platform_mp_stack.S         \
+                               plat/common/plat_gic.c                          \
+                               plat/fvp/aarch64/fvp_common.c                   \
+                               plat/fvp/aarch64/fvp_helpers.S                  \
+                               plat/fvp/tsp/tsp_fvp_setup.c
diff --git a/plat/fvp/tsp/tsp_fvp_setup.c b/plat/fvp/tsp/tsp_fvp_setup.c
new file mode 100644 (file)
index 0000000..d8f46bd
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <console.h>
+#include <platform_tsp.h>
+#include "../fvp_def.h"
+#include "../fvp_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+extern unsigned long __BL32_END__;
+
+#if USE_COHERENT_MEM
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+#endif
+
+/*
+ * The next 3 constants identify the extents of the code & RO data region and
+ * the limit of the BL3-2 image. These addresses are used by the MMU setup code
+ * and therefore they must be page-aligned.  It is the responsibility of the
+ * linker script to ensure that __RO_START__, __RO_END__ & & __BL32_END__
+ * linker symbols refer to page-aligned addresses.
+ */
+#define BL32_RO_BASE (unsigned long)(&__RO_START__)
+#define BL32_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL32_END (unsigned long)(&__BL32_END__)
+
+#if USE_COHERENT_MEM
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+void tsp_early_platform_setup(void)
+{
+       /*
+        * Initialize a different console than already in use to display
+        * messages from TSP
+        */
+       console_init(PL011_UART2_BASE, PL011_UART2_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /* Initialize the platform config for future decision making */
+       fvp_config_setup();
+}
+
+/*******************************************************************************
+ * Perform platform specific setup placeholder
+ ******************************************************************************/
+void tsp_platform_setup(void)
+{
+       fvp_gic_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the MMU
+ ******************************************************************************/
+void tsp_plat_arch_setup(void)
+{
+       fvp_configure_mmu_el1(BL32_RO_BASE,
+                             (BL32_END - BL32_RO_BASE),
+                             BL32_RO_BASE,
+                             BL32_RO_LIMIT
+#if USE_COHERENT_MEM
+                             , BL32_COHERENT_RAM_BASE,
+                             BL32_COHERENT_RAM_LIMIT
+#endif
+                             );
+}
diff --git a/plat/hikey/aarch64/bl1_plat_helpers.S b/plat/hikey/aarch64/bl1_plat_helpers.S
new file mode 100644 (file)
index 0000000..d3e6ff6
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include "../hikey_def.h"
+
+       .globl  platform_is_primary_cpu
+       .globl  platform_get_entrypoint
+       .globl  platform_cold_boot_init
+       .globl  plat_secondary_cold_boot_setup
+
+func platform_is_primary_cpu
+       and     x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+       cmp     x0, #0
+       cset    x0, eq
+       ret
+
+       /*
+        * Do we need to know whether it's a warm boot?
+        */
+func platform_get_entrypoint
+       mov     x0, #0
+       ret
+
+func plat_secondary_cold_boot_setup
+cb_panic:
+       b       cb_panic
diff --git a/plat/hikey/aarch64/hikey_common.c b/plat/hikey/aarch64/hikey_common.c
new file mode 100644 (file)
index 0000000..ba1313d
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <xlat_tables.h>
+#include <../hikey_def.h>
+
+#define MAP_DEVICE     MAP_REGION_FLAT(DEVICE_BASE,                    \
+                                       DEVICE_SIZE,                    \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_NS_DRAM    MAP_REGION_FLAT(DRAM_NS_BASE,                   \
+                                       DRAM_NS_SIZE,                   \
+                                       MT_DEVICE | MT_RW | MT_NS)
+
+#define MAP_TSP_MEM    MAP_REGION_FLAT(TSP_SEC_MEM_BASE,               \
+                                       TSP_SEC_MEM_SIZE,               \
+                                       MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_ROM_PARAM  MAP_REGION_FLAT(XG2RAM0_BASE,                   \
+                                       0x1000,                         \
+                                       MT_DEVICE | MT_RW | MT_NS)
+
+#define MAP_SRAM       MAP_REGION_FLAT(SRAM_BASE,                      \
+                                       SRAM_SIZE,                      \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+#if IMAGE_BL1
+static const mmap_region_t hikey_mmap[] = {
+       MAP_DEVICE,
+       MAP_NS_DRAM,
+       MAP_ROM_PARAM,
+       {0}
+};
+#endif
+#if IMAGE_BL2
+static const mmap_region_t hikey_mmap[] = {
+       MAP_DEVICE,
+       MAP_NS_DRAM,
+       MAP_TSP_MEM,
+       MAP_SRAM,
+       {0}
+};
+#endif
+#if IMAGE_BL31
+static const mmap_region_t hikey_mmap[] = {
+       MAP_DEVICE,
+       MAP_NS_DRAM,
+       MAP_TSP_MEM,
+       MAP_SRAM,
+       {0}
+};
+#endif
+#if IMAGE_BL32
+static const mmap_region_t hikey_mmap[] = {
+       MAP_DEVICE,
+       MAP_NS_DRAM,
+       {0}
+};
+#endif
+
+/* Array of secure interrupts to be configured by the gic driver */
+const unsigned int irq_sec_array[] = {
+       IRQ_SEC_PHY_TIMER,
+       IRQ_SEC_SGI_0,
+       IRQ_SEC_SGI_1,
+       IRQ_SEC_SGI_2,
+       IRQ_SEC_SGI_3,
+       IRQ_SEC_SGI_4,
+       IRQ_SEC_SGI_5,
+       IRQ_SEC_SGI_6,
+       IRQ_SEC_SGI_7
+};
+
+const unsigned int num_sec_irqs = sizeof(irq_sec_array) /
+       sizeof(irq_sec_array[0]);
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#define DEFINE_CONFIGURE_MMU_EL(_el)                           \
+       void configure_mmu_el##_el(unsigned long total_base,    \
+                                 unsigned long total_size,     \
+                                 unsigned long ro_start,       \
+                                 unsigned long ro_limit,       \
+                                 unsigned long coh_start,      \
+                                 unsigned long coh_limit)      \
+       {                                                       \
+              mmap_add_region(total_base, total_base,          \
+                              total_size,                      \
+                              MT_MEMORY | MT_RW | MT_SECURE);  \
+              mmap_add_region(ro_start, ro_start,              \
+                              ro_limit - ro_start,             \
+                              MT_MEMORY | MT_RO | MT_SECURE);  \
+              mmap_add_region(coh_start, coh_start,            \
+                              coh_limit - coh_start,           \
+                              MT_DEVICE | MT_RW | MT_SECURE);  \
+              mmap_add(hikey_mmap);                            \
+              init_xlat_tables();                              \
+                                                               \
+              enable_mmu_el##_el(0);                           \
+       }
+
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(1)
+DEFINE_CONFIGURE_MMU_EL(3)
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+       return NS_IMAGE_OFFSET;
+}
+
+uint64_t plat_get_syscnt_freq(void)
+{
+       return 1200000;
+}
+
+void plat_gic_init(void)
+{
+       arm_gic_init(GICC_BASE, GICD_BASE, 0, irq_sec_array, num_sec_irqs);
+}
diff --git a/plat/hikey/aarch64/plat_helpers.S b/plat/hikey/aarch64/plat_helpers.S
new file mode 100644 (file)
index 0000000..02f739c
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a53.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+#include "../hikey_def.h"
+
+       .globl  plat_crash_console_init
+       .globl  plat_crash_console_putc
+       .globl  plat_report_exception
+       .globl  plat_reset_handler
+       .globl  platform_get_core_pos
+       .globl  platform_mem_init
+
+       /* ---------------------------------------------
+        * int plat_crash_console_init(void)
+        * Function to initialize the crash console
+        * without a C Runtime to print crash report.
+        * Clobber list : x0, x1, x2
+        * ---------------------------------------------
+        */
+func plat_crash_console_init
+       mov_imm x0, CRASH_CONSOLE_BASE
+       mov_imm x1, PL011_UART_CLK_IN_HZ
+       mov_imm x2, PL011_BAUDRATE
+       b       console_core_init
+
+       /* ---------------------------------------------
+        * int plat_crash_console_putc(int c)
+        * Function to print a character on the crash
+        * console without a C Runtime.
+        * Clobber list : x1, x2
+        * ---------------------------------------------
+        */
+func plat_crash_console_putc
+       mov_imm x1, CRASH_CONSOLE_BASE
+       b       console_core_putc
+
+       /* ---------------------------------------------
+        * void plat_report_exception(unsigned int type)
+        * Function to report an unhandled exception
+        * with platform-specific means.
+        * On HIKEY platform, it updates the LEDs
+        * to indicate where we are
+        * ---------------------------------------------
+        */
+func plat_report_exception
+       mov     x8, x30
+
+       /* Turn on LED according to x0 (0 -- f) */
+       /*
+       ldr     x2, =0xf7020000
+       and     x1, x0, #1
+       str     w1, [x2, #4]
+       and     x1, x0, #2
+       str     w1, [x2, #8]
+       and     x1, x0, #4
+       str     w1, [x2, #16]
+       and     x1, x0, #8
+       str     w1, [x2, #32]
+       */
+
+       adr     x4, plat_err_str
+       bl      asm_print_str
+
+       adr     x4, esr_el3_str
+       bl      asm_print_str
+
+       mrs     x4, esr_el3
+       bl      asm_print_hex
+
+       adr     x4, elr_el3_str
+       bl      asm_print_str
+
+       mrs     x4, elr_el3
+       bl      asm_print_hex
+
+       mov     x30, x8
+       ret
+
+       /* -----------------------------------------------------
+        * void plat_reset_handler(void);
+        *
+        * Implement workaround for defect id 831273 by enabling
+        * an event stream every 65536 cycles and set the L2 RAM
+        * latencies for Cortex-A57.
+        * -----------------------------------------------------
+        */
+func plat_reset_handler
+       /* In juno, it sets the latency of L2 Data and Tag. How about hikey? */
+       /* Do anything just after reset. At here, do we need? */
+       ret
+
+       /*
+        * Return 0 to 7
+        */
+func platform_get_core_pos
+       and     x1, x0, #MPIDR_CPU_MASK
+       and     x0, x0, #MPIDR_CLUSTER_MASK
+       add     x0, x1, x0, LSR #6
+       ret
+
+       /* -----------------------------------------------------
+        * void platform_mem_init(void);
+        *
+        * We don't need to carry out any memory initialization
+        * on HIKEY. The Secure RAM is accessible straight away.
+        * -----------------------------------------------------
+        */
+func platform_mem_init
+       ret
+
+.section .rodata.rev_err_str, "aS"
+plat_err_str:
+       .asciz "\nPlatform exception reporting:"
+esr_el3_str:
+       .asciz "\nESR_EL3: "
+elr_el3_str:
+       .asciz "\nELR_EL3: "
diff --git a/plat/hikey/bl1_plat_setup.c b/plat/hikey/bl1_plat_setup.c
new file mode 100644 (file)
index 0000000..984c0ee
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <cci400.h>
+#include <console.h>
+#include <ctype.h>
+#include <debug.h>
+#include <errno.h>
+#include <gpio.h>
+#include <hi6220.h>
+#include <hi6553.h>
+#include <mmio.h>
+#include <partitions.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <sp804_timer.h>
+#include <string.h>
+#include "../../bl1/bl1_private.h"
+#include "hikey_def.h"
+#include "hikey_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/* Data structure which holds the extents of the trusted RAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+
+static void hi6220_pmussi_init(void);
+static void hikey_gpio_init(void);
+static void hikey_hi6553_init(void);
+static int query_boot_mode(void);
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+       return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+       const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
+
+       /* Initialize the console to provide early debug support */
+       console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
+
+       hi6220_timer_init();
+       /*
+        * Enable CCI-400 for this cluster. No need for locks as no other cpu is
+        * active at the moment
+        */
+       cci_init(CCI400_BASE,
+                CCI400_SL_IFACE3_CLUSTER_IX,
+                CCI400_SL_IFACE4_CLUSTER_IX);
+       cci_enable_cluster_coherency(read_mpidr());
+
+       /* Allow BL1 to see the whole Trusted RAM */
+       bl1_tzram_layout.total_base = BL1_RW_BASE;
+       bl1_tzram_layout.total_size = BL1_RW_SIZE;
+
+       /* Calculate how much RAM BL1 is using and how much remains free */
+       bl1_tzram_layout.free_base = BL1_RW_BASE;
+       bl1_tzram_layout.free_size = BL1_RW_SIZE;
+       reserve_mem(&bl1_tzram_layout.free_base,
+                   &bl1_tzram_layout.free_size,
+                   BL1_RAM_BASE,
+                   bl1_size);
+
+       INFO("BL1: 0x%lx - 0x%lx [size = %u]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
+            bl1_size);
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architecture setup here. At the
+ * moment this only does basic initialization. Later architectural setup
+ * (bl1_arch_setup()) does not do anything platform specific.
+ ******************************************************************************/
+void bl1_plat_arch_setup(void)
+{
+       configure_mmu_el3(bl1_tzram_layout.total_base,
+                         bl1_tzram_layout.total_size,
+                         BL1_RO_BASE,
+                         BL1_RO_LIMIT,
+                         BL1_COHERENT_RAM_BASE,
+                         BL1_COHERENT_RAM_LIMIT);
+}
+
+static int sd_card_detect(void)
+{
+       int ret;
+       /* configure GPIO8 as nopull */
+       mmio_write_32(0xf8001830, 0);
+       gpio_direction_input(8);
+       ret = gpio_get_value(8);
+       if (!ret)
+               return 1;
+       return 0;
+}
+
+static void hikey_sd_init(void)
+{
+       int ret;
+
+       /* switch pinmux to SD */
+       mmio_write_32(0xf701000c, 0);
+       mmio_write_32(0xf7010010, 0);
+       mmio_write_32(0xf7010014, 0);
+       mmio_write_32(0xf7010018, 0);
+       mmio_write_32(0xf701001c, 0);
+       mmio_write_32(0xf7010020, 0);
+
+       /* input, 16mA or 12mA */
+       mmio_write_32(0xf701080c, 0x64);
+       mmio_write_32(0xf7010810, 0x54);
+       mmio_write_32(0xf7010814, 0x54);
+       mmio_write_32(0xf7010818, 0x54);
+       mmio_write_32(0xf701081c, 0x54);
+       mmio_write_32(0xf7010820, 0x54);
+       ret = sd_card_detect();
+       if (ret)
+               INFO("SD Card has been detected.\n");
+}
+
+static void hikey_jumper_init(void)
+{
+       /* configure GPIO24 as nopull */
+       mmio_write_32(0xf7010950, 0);
+       /* configure GPIO24 as gpio */
+       mmio_write_32(0xf7010140, 0);
+       gpio_direction_input(24);
+       VERBOSE("Jumper value:%d\n", gpio_get_value(24));
+}
+
+static inline char hex2str(unsigned int data)
+{
+       data &= 0xf;
+       if ((data >= 0) && (data <= 9))
+               return (char)(data + 0x30);
+       return (char)(data - 10 + 0x41);
+}
+
+static uint64_t rand(unsigned int data)
+{
+       int64_t quotient, remainder, t;
+
+       quotient = data / 127773;
+       remainder = data % 127773;
+       t = 16807 * remainder - 2836 * quotient;
+       if (t <= 0)
+               t += RANDOM_MAX;
+       return (t % ((uint64_t)RANDOM_MAX + 1));
+}
+
+void generate_serialno(struct random_serial_num *random)
+{
+       unsigned int data, t;
+       int i;
+
+       data = mmio_read_32(AO_SC_SYSTEST_SLICER_CNT0);
+       t = rand(data);
+       random->data = ((uint64_t)t << 32) | data;
+       for (i = 0; i < 8; i++) {
+               random->serialno[i] = hex2str((t >> ((7 - i) << 2)) & 0xf);
+       }
+       for (i = 0; i < 8; i++) {
+               random->serialno[i + 8] = hex2str((data >> ((7 - i) << 2)) & 0xf);
+       }
+       random->serialno[16] = '\0';
+       random->magic = RANDOM_MAGIC;
+}
+
+int assign_serialno(char *cmdbuf, struct random_serial_num *random)
+{
+       int offset, i;
+
+       offset = 0;
+       while (*(cmdbuf + offset) == ' ')
+               offset++;
+       for (i = 0; i < 16; i++) {
+               if (isxdigit(*(cmdbuf + offset + i)))
+                       continue;
+               return -EINVAL;
+       }
+       memcpy(random->serialno, cmdbuf + offset, 16);
+       random->serialno[16] = '\0';
+       random->magic = RANDOM_MAGIC;
+       return 0;
+}
+
+static void hikey_verify_serialno(struct random_serial_num *random)
+{
+       char *serialno;
+
+       serialno = load_serialno();
+       if (serialno == NULL) {
+               generate_serialno(random);
+               flush_random_serialno((unsigned long)&random, sizeof(random));
+       }
+}
+
+/*******************************************************************************
+ * Function which will perform any remaining platform-specific setup that can
+ * occur after the MMU and data cache have been enabled.
+ ******************************************************************************/
+void bl1_platform_setup(void)
+{
+       struct random_serial_num random;
+
+       hikey_gpio_init();
+       hi6220_pmussi_init();
+       hikey_hi6553_init();
+       hi6220_pll_init();
+       hikey_sd_init();
+       hikey_jumper_init();
+
+       io_setup();
+       get_partition();
+       INFO("Hisilicon HiKey platform is initialized\n");
+       if (query_boot_mode()) {
+               NOTICE("Enter fastboot mode...\n");
+               flush_loader_image();
+               hikey_verify_serialno(&random);
+               usb_download();
+       }
+}
+
+/* Get the boot mode (normal boot/usb download/uart download) */
+static int query_boot_mode(void)
+{
+       int boot_mode;
+
+       boot_mode = mmio_read_32(ONCHIPROM_PARAM_BASE);
+       if ((boot_mode < 0) || (boot_mode > 2)) {
+               NOTICE("Invalid boot mode is found:%d\n", boot_mode);
+               panic();
+       }
+       return boot_mode;
+}
+
+/* PMU SSI is the device that could map external PMU register to IO */
+static void hi6220_pmussi_init(void)
+{
+       uint32_t data;
+
+       /*
+        * After reset, PMUSSI stays in reset mode.
+        * Now make it out of reset.
+        */
+       mmio_write_32(AO_SC_PERIPH_RSTDIS4,
+               AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
+       do {
+               data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
+       } while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
+
+       /* set PMU SSI clock latency for read operation */
+       data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3);
+       data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
+       data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3;
+       mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data);
+
+       /* enable PMUSSI clock */
+       data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU |
+              AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU;
+       mmio_write_32(AO_SC_PERIPH_CLKEN5, data);
+       data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI;
+       mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
+
+       /* output high on gpio0 */
+       gpio_direction_output(0);
+       gpio_set_value(0, 1);
+}
+
+static void hikey_hi6553_init(void)
+{
+       int data;
+
+       hi6553_write_8(PERI_EN_MARK, 0x1e);
+       hi6553_write_8(NP_REG_ADJ1, 0);
+       data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC |
+               DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2;
+       hi6553_write_8(DISABLE6_XO_CLK, data);
+
+       /* configure BUCK0 & BUCK1 */
+       hi6553_write_8(BUCK01_CTRL2, 0x5e);
+       hi6553_write_8(BUCK0_CTRL7, 0x10);
+       hi6553_write_8(BUCK1_CTRL7, 0x10);
+       hi6553_write_8(BUCK0_CTRL5, 0x1e);
+       hi6553_write_8(BUCK1_CTRL5, 0x1e);
+       hi6553_write_8(BUCK0_CTRL1, 0xfc);
+       hi6553_write_8(BUCK1_CTRL1, 0xfc);
+
+       /* configure BUCK2 */
+       hi6553_write_8(BUCK2_REG1, 0x4f);
+       hi6553_write_8(BUCK2_REG5, 0x99);
+       hi6553_write_8(BUCK2_REG6, 0x45);
+       mdelay(1);
+       hi6553_write_8(VSET_BUCK2_ADJ, 0x22);
+       mdelay(1);
+
+       /* configure BUCK3 */
+       hi6553_write_8(BUCK3_REG3, 0x02);
+       hi6553_write_8(BUCK3_REG5, 0x99);
+       hi6553_write_8(BUCK3_REG6, 0x41);
+       hi6553_write_8(VSET_BUCK3_ADJ, 0x02);
+       mdelay(1);
+
+       /* configure BUCK4 */
+       hi6553_write_8(BUCK4_REG2, 0x9a);
+       hi6553_write_8(BUCK4_REG5, 0x99);
+       hi6553_write_8(BUCK4_REG6, 0x45);
+
+       /* configure LDO20 */
+       hi6553_write_8(LDO20_REG_ADJ, 0x50);
+
+       hi6553_write_8(NP_REG_CHG, 0x0f);
+       hi6553_write_8(CLK_TOP0, 0x06);
+       hi6553_write_8(CLK_TOP3, 0xc0);
+       hi6553_write_8(CLK_TOP4, 0x00);
+
+       /* configure LDO7 & LDO10 for SD slot */
+       data = hi6553_read_8(LDO7_REG_ADJ);
+       data = (data & 0xf8) | 0x2;
+       hi6553_write_8(LDO7_REG_ADJ, data);
+       mdelay(5);
+       /* enable LDO7 */
+       hi6553_write_8(ENABLE2_LDO1_8, 1 << 6);
+       mdelay(5);
+       data = hi6553_read_8(LDO10_REG_ADJ);
+       data = (data & 0xf8) | 0x5;
+       hi6553_write_8(LDO10_REG_ADJ, data);
+       mdelay(5);
+       /* enable LDO10 */
+       hi6553_write_8(ENABLE3_LDO9_16, 1 << 1);
+       mdelay(5);
+       /* enable LDO15 */
+       data = hi6553_read_8(LDO15_REG_ADJ);
+       data = (data & 0xf8) | 0x4;
+       hi6553_write_8(LDO15_REG_ADJ, data);
+       hi6553_write_8(ENABLE3_LDO9_16, 1 << 6);
+       mdelay(5);
+       /* enable LDO22 */
+       data = hi6553_read_8(LDO22_REG_ADJ);
+       data = (data & 0xf8) | 0x7;
+       hi6553_write_8(LDO22_REG_ADJ, data);
+       hi6553_write_8(ENABLE4_LDO17_22, 1 << 5);
+       mdelay(5);
+
+       /* select 32.764KHz */
+       hi6553_write_8(CLK19M2_600_586_EN, 0x01);
+}
+
+static void hikey_gpio_init(void)
+{
+       gpio_register_device(GPIO0_BASE);
+       gpio_register_device(GPIO1_BASE);
+       gpio_register_device(GPIO2_BASE);
+       gpio_register_device(GPIO3_BASE);
+       gpio_register_device(GPIO4_BASE);
+       gpio_register_device(GPIO5_BASE);
+       gpio_register_device(GPIO6_BASE);
+       gpio_register_device(GPIO7_BASE);
+       gpio_register_device(GPIO8_BASE);
+       gpio_register_device(GPIO9_BASE);
+       gpio_register_device(GPIO10_BASE);
+       gpio_register_device(GPIO11_BASE);
+       gpio_register_device(GPIO12_BASE);
+       gpio_register_device(GPIO13_BASE);
+       gpio_register_device(GPIO14_BASE);
+       gpio_register_device(GPIO15_BASE);
+       gpio_register_device(GPIO16_BASE);
+       gpio_register_device(GPIO17_BASE);
+       gpio_register_device(GPIO18_BASE);
+       gpio_register_device(GPIO19_BASE);
+
+       /* Power on indicator LED (User LED0). */
+       gpio_direction_output(32);
+       gpio_set_value(32, 1);
+       gpio_direction_output(33);
+       gpio_direction_output(34);
+       gpio_direction_output(35);
+
+       /* Initialize PWR_HOLD GPIO */
+       gpio_set_value(0, 1);
+       gpio_direction_output(0);
+}
+
+/*******************************************************************************
+ * Before calling this function BL2 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL2 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image,
+                             entry_point_info_t *bl2_ep)
+{
+       SET_SECURITY_STATE(bl2_ep->h.attr, SECURE);
+       bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+}
diff --git a/plat/hikey/bl2_plat_setup.c b/plat/hikey/bl2_plat_setup.c
new file mode 100644 (file)
index 0000000..0824394
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <partitions.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <mmio.h>
+#include <hi6220.h>
+#include "hikey_def.h"
+#include "hikey_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL2_RO_BASE (unsigned long)(&__RO_START__)
+#define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/* Data structure which holds the extents of the trusted RAM for BL2 */
+static meminfo_t bl2_tzram_layout
+__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE),
+               section("tzfw_coherent_mem")));
+
+/*******************************************************************************
+ * Structure which holds the arguments which need to be passed to BL3-1
+ ******************************************************************************/
+static bl2_to_bl31_params_mem_t bl31_params_mem;
+
+meminfo_t *bl2_plat_sec_mem_layout(void)
+{
+       return &bl2_tzram_layout;
+}
+
+/*******************************************************************************
+ * This function assigns a pointer to the memory that the platform has kept
+ * aside to pass platform specific and trusted firmware related information
+ * to BL31. This memory is allocated by allocating memory to
+ * bl2_to_bl31_params_mem_t structure which is a superset of all the
+ * structure whose information is passed to BL31
+ * NOTE: This function should be called only once and should be done
+ * before generating params to BL31
+ ******************************************************************************/
+bl31_params_t *bl2_plat_get_bl31_params(void)
+{
+       bl31_params_t *bl2_to_bl31_params;
+
+       /*
+        * Initialise the memory for all the arguments that needs to
+        * be passed to BL3-1
+        */
+       memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t));
+
+       /* Assign memory for TF related information */
+       bl2_to_bl31_params = &bl31_params_mem.bl31_params;
+       SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0);
+
+       /* Fill BL3-1 related information */
+       bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY,
+               VERSION_1, 0);
+
+       /* Fill BL3-2 related information if it exists */
+#if BL32_BASE
+       bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
+               VERSION_1, 0);
+       bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
+               VERSION_1, 0);
+#endif
+
+       /* Fill BL3-3 related information */
+       bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
+               PARAM_EP, VERSION_1, 0);
+
+       /* BL3-3 expects to receive the primary CPU MPID (through x0) */
+       bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
+
+       bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY,
+               VERSION_1, 0);
+
+       return bl2_to_bl31_params;
+}
+
+/*******************************************************************************
+ * This function returns a pointer to the shared memory that the platform
+ * has kept to point to entry point information of BL31 to BL2
+ ******************************************************************************/
+struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
+{
+       return &bl31_params_mem.bl31_ep_info;
+}
+
+void init_boardid(void)
+{
+       unsigned int reg;
+
+       /* Set chip id to sram */
+       reg = read_midr_el1();
+       mmio_write_32(MEMORY_AXI_CHIP_ADDR, reg);
+       INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR, reg);
+
+       /* Set board type to sram */
+       mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0x0);
+       INFO("[BDID] [%x] board type: 0\n", MEMORY_AXI_BOARD_TYPE_ADDR);
+
+       /* Set board id to sram */
+       mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b);
+       INFO("[BDID] [%x] board id: 0x2b\n", MEMORY_AXI_BOARD_ID_ADDR);
+
+       mmio_write_32(ACPU_ARM64_FLAGA, 0x1234);
+       mmio_write_32(ACPU_ARM64_FLAGB, 0x5678);
+       return;
+}
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted RAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted RAM.
+ * Copy it to a safe loaction before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+void bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+       /* Initialize the console to provide early debug support */
+       console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /* Setup the BL2 memory layout */
+       bl2_tzram_layout = *mem_layout;
+
+       init_boardid();
+       init_acpu_dvfs();
+
+       io_setup();
+       get_partition();
+}
+
+/*******************************************************************************
+ * Perform platform specific setup, i.e. initialize the IO layer, load BL3-0
+ * image and initialise the memory location to use for passing arguments to
+ * BL3-1.
+ ******************************************************************************/
+void bl2_platform_setup(void)
+{
+       plat_security_setup();
+}
+
+/* Flush the TF params and the TF plat params */
+void bl2_plat_flush_bl31_params(void)
+{
+       flush_dcache_range((unsigned long)&bl31_params_mem,
+                       sizeof(bl2_to_bl31_params_mem_t));
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl2_plat_arch_setup(void)
+{
+       configure_mmu_el1(bl2_tzram_layout.total_base,
+                         bl2_tzram_layout.total_size,
+                         BL2_RO_BASE,
+                         BL2_RO_LIMIT,
+                         BL2_COHERENT_RAM_BASE,
+                         BL2_COHERENT_RAM_LIMIT);
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-0, i.e. anywhere
+ * in trusted RAM as long as it doesn't overwrite BL2.
+ ******************************************************************************/
+void bl2_plat_get_bl30_meminfo(meminfo_t *bl30_meminfo)
+{
+       bl30_meminfo->total_base = BL30_BASE;
+       bl30_meminfo->total_size = BL30_SIZE;
+       bl30_meminfo->free_base  = BL30_BASE;
+       bl30_meminfo->free_size  = BL30_SIZE;
+}
+
+/*******************************************************************************
+ * Transfer BL3-0 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+int bl2_plat_handle_bl30(image_info_t *bl30_image_info)
+{
+       int *buf = (int *)bl30_image_info->image_base;
+
+       INFO("%s: [%x] %x %x %x %x\n",
+            __func__, buf, buf[0], buf[1], buf[2], buf[3]);
+
+       buf += 50;
+       INFO("%s: [%x] %x %x %x %x\n",
+            __func__, buf, buf[0], buf[1], buf[2], buf[3]);
+
+       buf += 50;
+       INFO("%s: [%x] %x %x %x %x\n",
+            __func__, buf, buf[0], buf[1], buf[2], buf[3]);
+
+       buf  = (int *)(bl30_image_info->image_base +
+                      bl30_image_info->image_size);
+       buf -= 4;
+       INFO("%s: [%x] %x %x %x %x\n",
+            __func__, buf, buf[0], buf[1], buf[2], buf[3]);
+
+       /* enable mcu sram */
+       hisi_mcu_enable_sram();
+
+       /* load mcu binary to sram */
+       hisi_mcu_load_image(bl30_image_info->image_base,
+                           bl30_image_info->image_size);
+
+       /* let mcu to run */
+       hisi_mcu_start_run();
+
+       INFO("%s: mcu pc is %x\n",
+               __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2));
+
+       INFO("%s: AO_SC_PERIPH_CLKSTAT4 is %x\n",
+               __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4));
+       return 0;
+}
+
+/*******************************************************************************
+ * Before calling this function BL31 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL31 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl31_ep_info(image_info_t *bl31_image_info,
+                              entry_point_info_t *bl31_ep_info)
+{
+       SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
+       bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+                                      DISABLE_ALL_EXCEPTIONS);
+}
+
+/*******************************************************************************
+ * Before calling this function BL32 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL32 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
+                              entry_point_info_t *bl32_ep_info)
+{
+       SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+       /*
+       * The Secure Payload Dispatcher service is responsible for
+       * setting the SPSR prior to entry into the BL32 image.
+       */
+       bl32_ep_info->spsr = 0;
+}
+
+/*******************************************************************************
+ * Before calling this function BL33 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL33 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl33_ep_info(image_info_t *image,
+                                      entry_point_info_t *bl33_ep_info)
+{
+       unsigned long el_status;
+       unsigned int mode;
+
+       /* Figure out what mode we enter the non-secure world in */
+       el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+       el_status &= ID_AA64PFR0_ELX_MASK;
+
+       if (el_status)
+               mode = MODE_EL2;
+       else
+               mode = MODE_EL1;
+
+       /*
+        * TODO: Consider the possibility of specifying the SPSR in
+        * the FIP ToC and allowing the platform to have a say as
+        * well.
+        */
+       bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX,
+                                      DISABLE_ALL_EXCEPTIONS);
+       SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-2
+ ******************************************************************************/
+void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
+{
+       /*
+        * Populate the extents of memory available for loading BL3-2.
+        */
+       bl32_meminfo->total_base = BL32_BASE;
+       bl32_meminfo->free_base = BL32_BASE;
+       bl32_meminfo->total_size =
+                      (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+       bl32_meminfo->free_size =
+                      (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-3
+ ******************************************************************************/
+void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
+{
+       bl33_meminfo->total_base = DRAM_NS_BASE;
+       bl33_meminfo->total_size = DRAM_NS_SIZE;
+       bl33_meminfo->free_base = DRAM_NS_BASE;
+       bl33_meminfo->free_size = DRAM_NS_SIZE;
+}
diff --git a/plat/hikey/bl31_plat_setup.c b/plat/hikey/bl31_plat_setup.c
new file mode 100644 (file)
index 0000000..305835c
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl31.h>
+#include <bl_common.h>
+#include <cci400.h>
+#include <console.h>
+#include <debug.h>
+#include <hisi_ipc.h>
+#include <hisi_pwrc.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+#include <hi6220_regs_ao.h>
+#include <hi6220.h>
+
+#include "hikey_def.h"
+#include "hikey_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/******************************************************************************
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL3-1 from BL2.
+ ******************************************************************************/
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL3-3 corresponds to the non-secure image type
+ * while BL3-2 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+       entry_point_info_t *next_image_info;
+
+       next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+
+       /* None of the images on this platform can have 0x0 as the entrypoint */
+       if (next_image_info->pc)
+               return next_image_info;
+       else
+               return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 specific platform actions. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables. Also, BL2
+ * has flushed this information to memory, so we are guaranteed to pick up good
+ * data
+ ******************************************************************************/
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+                              void *plat_params_from_bl2)
+{
+       /* Initialize the console to provide early debug support */
+       console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /*
+        * Initialise the CCI-400 driver for BL31 so that it is accessible after
+        * a warm boot. BL1 should have already enabled CCI coherency for this
+        * cluster during cold boot.
+        */
+       cci_init(CCI400_BASE,
+                CCI400_SL_IFACE3_CLUSTER_IX,
+                CCI400_SL_IFACE4_CLUSTER_IX);
+
+       /*
+        * Copy BL3-2 and BL3-3 entry point information.
+        * They are stored in Secure RAM, in BL2's address space.
+        */
+       bl32_ep_info = *from_bl2->bl32_ep_info;
+       bl33_ep_info = *from_bl2->bl33_ep_info;
+}
+
+static void init_rtc(void)
+{
+       uint32_t data;
+
+       data = mmio_read_32(AO_SC_PERIPH_CLKEN4);
+       data |= AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N;
+       mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
+}
+
+static void init_edma(void)
+{
+       int i;
+
+       mmio_write_32(EDMAC_SEC_CTRL, 0x3);
+
+       for (i = 0; i <= 15; i++) {
+               VERBOSE("EDMAC_AXI_CONF(%d): data:0x%x\n", i, mmio_read_32(EDMAC_AXI_CONF(i)));
+               mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18));
+               VERBOSE("EDMAC_AXI_CONF(%d): data:0x%x\n", i, mmio_read_32(EDMAC_AXI_CONF(i)));
+       }
+}
+
+/*******************************************************************************
+ * Initialize the GIC.
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+       /* Initialize the gic cpu and distributor interfaces */
+       plat_gic_init();
+       arm_gic_setup();
+
+       init_rtc();
+       init_edma();
+       hisi_ipc_init();
+       hisi_pwrc_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup()
+{
+       configure_mmu_el3(BL31_RO_BASE,
+                         BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE,
+                         BL31_RO_BASE,
+                         BL31_RO_LIMIT,
+                         BL31_COHERENT_RAM_BASE,
+                         BL31_COHERENT_RAM_LIMIT);
+}
diff --git a/plat/hikey/drivers/dw_mmc.c b/plat/hikey/drivers/dw_mmc.c
new file mode 100644 (file)
index 0000000..5eecd0c
--- /dev/null
@@ -0,0 +1,754 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <mmio.h>
+#include <string.h>
+#include <sp804_timer.h>
+#include <dw_mmc.h>
+#include <partitions.h>
+#include <platform_def.h>
+#include <hi6220.h>
+#include <hi6553.h>
+
+#define MMC_PLL                        100000000
+
+#define IDMAC_DES0_DIC         (1 << 1)
+#define IDMAC_DES0_LD          (1 << 2)
+#define IDMAC_DES0_FS          (1 << 3)
+#define IDMAC_DES0_CH          (1 << 4)
+#define IDMAC_DES0_ER          (1 << 5)
+#define IDMAC_DES0_CES         (1 << 30)
+#define IDMAC_DES0_OWN         (1 << 31)
+
+#define IDMAC_DES1_BS1(x)      ((x) & 0x1fff)
+#define IDMAC_DES2_BS2(x)      (((x) & 0x1fff) << 13)
+
+struct idmac_desc {
+       unsigned int            des0;
+       unsigned int            des1;
+       unsigned int            des2;
+       unsigned int            des3;
+};
+
+static inline int mmc_state(unsigned int data)
+{
+       return ((data & MMC_STATUS_CURRENT_STATE_MASK) >>
+               MMC_STATUS_CURRENT_STATE_SHIFT);
+}
+
+static inline int wait_data_ready(void)
+{
+       unsigned int data;
+
+       while (1) {
+               data = mmio_read_32(MMC0_RINTSTS);
+               if (data & (MMC_INT_DCRC | MMC_INT_DRT | MMC_INT_SBE |
+                   MMC_INT_EBE)) {
+                       NOTICE("unwanted interrupts:0x%x\n", data);
+                       return -EINVAL;
+               }
+               if (data & MMC_INT_DTO)
+                       break;
+       }
+       /* clear interrupts */
+       mmio_write_32(MMC0_RINTSTS, ~0);
+       return 0;
+}
+
+static int update_mmc0_clock(void)
+{
+       unsigned int data;
+
+       /* CMD_UPDATE_CLK */
+       data = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY |
+               BIT_CMD_START;
+       mmio_write_32(MMC0_CMD, data);
+       while (1) {
+               data = mmio_read_32(MMC0_CMD);
+               if (!(data & CMD_START_BIT))
+                       break;
+               data = mmio_read_32(MMC0_RINTSTS);
+               if (data & MMC_INT_HLE) {
+                       NOTICE("fail to update mmc clock frequency\n");
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+static int set_mmc0_clock(int rate)
+{
+       int ret, divider, found = 0;
+       unsigned int data;
+
+       for (divider = 1; divider < 256; divider++) {
+               if ((MMC_PLL / (2 * divider)) <= rate) {
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found)
+               return -EINVAL;
+
+       /* wait until mmc is idle */
+       do {
+               data = mmio_read_32(MMC0_STATUS);
+       } while (data & MMC_STS_DATA_BUSY);
+
+       /* Disable mmc clock first */
+       mmio_write_32(MMC0_CLKENA, 0);
+       do {
+               ret = update_mmc0_clock();
+       } while (ret);
+
+       /* enable mmc clock */
+       do {
+               mmio_write_32(MMC0_CLKENA, 1);
+               mmio_write_32(MMC0_CLKSRC, 0);
+               mmio_write_32(MMC0_CLKDIV, divider);
+               ret = update_mmc0_clock();
+       } while (ret);
+       return 0;
+}
+
+static void set_mmc0_io(void)
+{
+       mmio_write_32(MMC0_CTYPE, MMC_8BIT_MODE);
+       mmio_write_32(MMC0_TMOUT, ~0);  /* maxium timeout value */
+       mmio_write_32(MMC0_DEBNCE, 0x00ffffff);
+       mmio_write_32(MMC0_BLKSIZ, MMC_BLOCK_SIZE);
+       mmio_write_32(MMC0_BYTCNT, 256 * 1024);
+}
+
+static int mmc0_send_cmd(unsigned int cmd, unsigned int arg, unsigned int *buf)
+{
+       unsigned int data, err_mask;
+
+       if (!buf) {
+               NOTICE("buf is invalid\n");
+               return -EFAULT;
+       }
+
+       mmio_write_32(MMC0_CMDARG, arg);
+
+       /* clear interrupts */
+       mmio_write_32(MMC0_RINTSTS, ~0);
+
+       switch (cmd) {
+       case 0:
+               data = BIT_CMD_SEND_INIT;
+               break;
+       case 1:
+               data = BIT_CMD_RESPONSE_EXPECT;
+               break;
+       case 2:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
+                       BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;
+               break;
+       case 3:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+                       BIT_CMD_SEND_INIT;
+               break;
+       case 8:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+                       BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
+                       BIT_CMD_WAIT_PRVDATA_COMPLETE;
+               break;
+       case 9:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+                       BIT_CMD_LONG_RESPONSE;
+               break;
+       case 12:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+                       BIT_CMD_STOP_ABORT_CMD;
+               break;
+       case 17:
+       case 18:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+                       BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
+                       BIT_CMD_WAIT_PRVDATA_COMPLETE;
+               break;
+       case 24:
+       case 25:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+                       BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE |
+                       BIT_CMD_WAIT_PRVDATA_COMPLETE;
+               break;
+       case 30:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
+                       BIT_CMD_DATA_EXPECTED;
+               break;
+       case 7:
+               if (arg)
+                       data = BIT_CMD_RESPONSE_EXPECT |
+                               BIT_CMD_CHECK_RESPONSE_CRC;
+               else
+                       data = 0;
+               break;
+       default:
+               data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
+               break;
+       }
+       data |= (cmd & 0x3f) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
+       mmio_write_32(MMC0_CMD, data);
+       err_mask = MMC_INT_EBE | MMC_INT_HLE | MMC_INT_RTO | MMC_INT_RCRC |
+                  MMC_INT_RE;
+       do {
+               data = mmio_read_32(MMC0_RINTSTS);
+               if (data & err_mask) {
+                       NOTICE("mmc: error status 0x%x\n", data);
+                       return -EIO;
+               }
+       } while (!(data & MMC_INT_CMD_DONE));
+
+       buf[0] = mmio_read_32(MMC0_RESP0);
+       if ((cmd == 2) || (cmd == 9)) {
+               buf[1] = mmio_read_32(MMC0_RESP1);
+               buf[2] = mmio_read_32(MMC0_RESP2);
+               buf[3] = mmio_read_32(MMC0_RESP3);
+       }
+       return 0;
+}
+
+/* Only print error message if it meets failure? */
+static void mmc0_check_tran_mode(void)
+{
+       unsigned int buf[4];
+       int ret;
+
+       mmio_write_32(MMC0_RINTSTS, ~0);
+
+       while (1) {
+               ret = mmc0_send_cmd(13, EMMC_FIX_RCA << 16, buf);
+               if (ret) {
+                       NOTICE("failed on command 13\n");
+                       return;
+               }
+               if (((buf[0] >> 9) & 0xf) == 4)
+                       return;
+       }
+}
+
+static int mmc0_update_ext_csd(int index, int value)
+{
+       unsigned int arg, data, buf[4];
+       int ret;
+
+       arg = 3 << 24;
+       arg |= (index & 0xff) << 16;
+       arg |= (value & 0xff) << 8;
+       arg |= 1;
+       memset(buf, 0, 4 * sizeof(buf[0]));
+
+       ret = mmc0_send_cmd(6, arg, buf);
+       if (ret) {
+               NOTICE("failed to send command 6\n");
+               return ret;
+       }
+
+       /* wait busy de-assert */
+       while (1) {
+               data = mmio_read_32(MMC0_STATUS);
+               if (!(data & MMC_STS_DATA_BUSY))
+                       break;
+       }
+
+       do {
+               ret = mmc0_send_cmd(13, EMMC_FIX_RCA << 16, buf);
+               if (ret) {
+                       NOTICE("failed to send command 13\n");
+                       return ret;
+               }
+
+               if (buf[0] & MMC_STATUS_SWITCH_ERROR) {
+                       NOTICE("maybe switch mmc mode error\n");
+                       return -1;
+               }
+       } while (mmc_state(buf[0]) == MMC_STATE_PRG);
+
+       return 0;
+}
+
+#define EXTCSD_BUS_WIDTH               183
+
+static int mmc0_set_clock_and_width(int rate, int width)
+{
+       int ret;
+
+       switch (width) {
+       case 0:
+               mmio_write_32(MMC0_CTYPE, 0);
+               ret = mmc0_update_ext_csd(EXTCSD_BUS_WIDTH, 0);
+               break;
+       case 8:
+               mmio_write_32(MMC0_CTYPE, 1 << 16);
+               ret = mmc0_update_ext_csd(EXTCSD_BUS_WIDTH, 2 + 4);
+               mmio_write_32(MMC0_UHSREG, 1 << 16);
+               break;
+       default:
+               NOTICE("wrong bus width:%d\n", width);
+               return -EINVAL;
+       }
+       if (ret) {
+               NOTICE("return failure on %s, %d\n", __func__, __LINE__);
+               return ret;
+       }
+
+       set_mmc0_clock(rate);
+       return 0;
+}
+
+static int manu_id;
+
+#define EXTCSD_HS_TIMING               185
+
+#ifdef EMMC_READ_EXT_CSD
+static int mmc0_read_ext_csd(unsigned int dst_start);
+#endif
+static int enum_mmc0_card(void)
+{
+       unsigned int buf[4], cid[4];
+       int ret = 0, i, version;
+
+       /* CMD0: reset to IDLE */
+       ret = mmc0_send_cmd(0, 0, buf);
+       if (ret) {
+               NOTICE("failed to send IDLE command\n");
+               return ret;
+       }
+
+       while (1) {
+               udelay(100);
+               /* CMD1: READY */
+               ret = mmc0_send_cmd(1, 0x40ff8000, buf);
+               if (ret) {
+                       NOTICE("failed to send READY command\n");
+                       return ret;
+               }
+               if (buf[0] & 0x80000000)
+                       break;
+       }
+
+       /* CMD2: IDENT */
+       ret = mmc0_send_cmd(2, 0, buf);
+       if (ret) {
+               NOTICE("failed to send IDENT command\n");
+               return ret;
+       }
+       VERBOSE("manuid:");
+       for (i = 0; i < 4; i++) {
+               cid[i] = buf[i];
+               VERBOSE(" 0x%x", cid[i]);
+       }
+       VERBOSE("\n");
+
+       /* CMD3: STBY */
+       ret = mmc0_send_cmd(3, EMMC_FIX_RCA << 16, buf);
+       if (ret) {
+               NOTICE("failed to send STBY command\n");
+               return ret;
+       }
+
+       /* CMD9: get CSD */
+       ret = mmc0_send_cmd(9, EMMC_FIX_RCA << 16, buf);
+       if (ret) {
+               NOTICE("failed to get CSD\n");
+               return ret;
+       }
+       VERBOSE("CSD: %x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]);
+       version = (buf[3] >> 26) & 0xf;
+       switch (version) {
+       case 0: /* MMC v1.0-v1.2 */
+       case 1: /* MMC v1.4 */
+               manu_id = (cid[3] >> 8) & 0xffffff;
+               break;
+       case 2: /* MMC v2.0-v2.2 */
+       case 3: /* MMC v3.1-v3.3 */
+       case 4: /* MMC v4 */
+               manu_id = (cid[3] >> 24) & 0xff;
+               break;
+       default:
+               WARN("wrong mmc version (%d) is specified.\n", version);
+               break;
+       }
+
+       VERBOSE("mmc version:%d\n", version);
+       /* CMD7: TRAN */
+       ret = mmc0_send_cmd(7, EMMC_FIX_RCA << 16, buf);
+       if (ret) {
+               NOTICE("failed to send TRAN command\n");
+               return ret;
+       }
+       mmc0_check_tran_mode();
+
+       mmc0_set_clock_and_width(400000, 0);
+#ifdef EMMC_READ_EXT_CSD
+       mmc0_read_ext_csd(0x50000);
+#endif
+       ret = mmc0_update_ext_csd(EXTCSD_HS_TIMING, 1);
+       if (ret) {
+               NOTICE("alter HS mode fail\n");
+       }
+
+       ret = mmc0_set_clock_and_width(50000000, 8);
+       return ret;
+}
+
+static int enable_mmc0(void)
+{
+       unsigned int data;
+
+       /* reset mmc0 */
+       data = MMC_CTRL_RESET | MMC_FIFO_RESET | MMC_DMA_RESET;
+       mmio_write_32(MMC0_CTRL, data);
+       /* wait until reset operation finished */
+       do {
+               data = mmio_read_32(MMC0_CTRL);
+       } while (data);
+
+       data = MMC_INT_EN | MMC_DMA_EN;
+       mmio_write_32(MMC0_CTRL, data);
+
+       mmio_write_32(MMC0_INTMASK, 0x0);
+       mmio_write_32(MMC0_RINTSTS, ~0);
+       mmio_write_32(MMC0_IDINTEN, ~0);
+       mmio_write_32(MMC0_IDSTS, ~0);
+
+       mmio_write_32(MMC0_BLKSIZ, MMC_BLOCK_SIZE);
+       mmio_write_32(MMC0_BMOD, MMC_IDMAC_SWRESET);
+       do {
+               data = mmio_read_32(MMC0_BMOD);
+       } while (data & MMC_IDMAC_SWRESET);
+
+       data |= MMC_IDMAC_ENABLE | MMC_IDMAC_FB;
+       mmio_write_32(MMC0_BMOD, data);
+
+       data = MMC_DMA_BURST_SIZE(2) | MMC_FIFO_TWMARK(8) | MMC_FIFO_RWMARK(7);
+       mmio_write_32(MMC0_FIFOTH, data);
+       data = MMC_CARD_RD_THR(512) | MMC_CARD_RD_THR_EN;
+       mmio_write_32(MMC0_CARDTHRCTL, data);
+
+       udelay(100);
+       set_mmc0_clock(378000);
+       udelay(100);
+
+       set_mmc0_io();
+       return 0;
+}
+
+#define MMC_BLOCK_SIZE                 512
+#define MMC_DMA_MAX_BUFFER_SIZE                (512 * 8)
+
+#ifdef EMMC_READ_EXT_CSD
+static int mmc0_read_ext_csd(unsigned int dst_start)
+{
+       unsigned int blk_cnt, bytes, desc_num, buf[4], data;
+       struct idmac_desc *desc = NULL;
+       int i, ret, last_idx;
+       uintptr_t src_addr, dst_addr = dst_start;
+
+       blk_cnt = 1;
+       bytes = blk_cnt * MMC_BLOCK_SIZE;
+       memset((void *)MMC_DATA_BASE, 0, bytes);
+
+       mmio_write_32(MMC0_BYTCNT, bytes);
+
+       mmio_write_32(MMC0_RINTSTS, ~0);
+
+       desc_num = (bytes + MMC_DMA_MAX_BUFFER_SIZE - 1) /
+                  MMC_DMA_MAX_BUFFER_SIZE;
+
+       desc = (struct idmac_desc *)MMC_DESC_BASE;
+
+       for (i = 0; i < desc_num; i++) {
+               (desc + i)->des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH |
+                                  IDMAC_DES0_DIC;
+               (desc + i)->des1 = IDMAC_DES1_BS1(MMC_DMA_MAX_BUFFER_SIZE);
+               /* buffer address */
+               (desc + i)->des2 = MMC_DATA_BASE + MMC_DMA_MAX_BUFFER_SIZE * i;
+               /* next descriptor address */
+               (desc + i)->des3 = MMC_DESC_BASE +
+                                  (sizeof(struct idmac_desc) * (i + 1));
+       }
+       /* first descriptor */
+       desc->des0 |= IDMAC_DES0_FS;
+       /* last descriptor */
+       last_idx = desc_num - 1;
+       (desc + last_idx)->des0 |= IDMAC_DES0_LD;
+       (desc + last_idx)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH);
+       (desc + last_idx)->des1 = IDMAC_DES1_BS1(bytes - (last_idx *
+                                 MMC_DMA_MAX_BUFFER_SIZE));
+       /* set next descriptor address as 0 */
+       (desc + last_idx)->des3 = 0;
+
+       mmio_write_32(MMC0_DBADDR, MMC_DESC_BASE);
+
+       /* read extended CSD */
+       ret = mmc0_send_cmd(8, EMMC_FIX_RCA << 16, buf);
+       if (ret) {
+               NOTICE("failed to send CMD8\n");
+               mmio_write_32(MMC0_RINTSTS, ~0);
+               return -EFAULT;
+       }
+
+       ret = wait_data_ready();
+       if (ret)
+               return ret;
+
+       if (blk_cnt > 1) {
+               ret = mmc0_send_cmd(12, EMMC_FIX_RCA << 16, buf);
+               if (ret) {
+                       NOTICE("failed to send Stop Transmission command\n");
+                       return ret;
+               }
+               mmio_write_32(MMC0_RINTSTS, ~0);
+       }
+       src_addr = MMC_DATA_BASE;
+       memcpy((void *)dst_addr, (void *)src_addr, MMC_BLOCK_SIZE);
+
+       return 0;
+}
+#endif
+
+int mmc0_read(unsigned long src_start, size_t src_size,
+               unsigned long dst_start, uint32_t boot_partition)
+{
+       unsigned int src_blk_start = src_start / MMC_BLOCK_SIZE;
+       unsigned int src_blk_cnt, offset, bytes, desc_num, buf[4];
+       struct idmac_desc *desc = NULL;
+       int i, ret, last_idx;
+       uintptr_t src_addr, dst_addr = dst_start;
+
+       if (boot_partition) {
+               /* switch to boot partition 1 */
+               ret = mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG,
+                                         PART_CFG_BOOT_PARTITION1_ENABLE |
+                                         PART_CFG_PARTITION1_ACCESS);
+               if (ret) {
+                       NOTICE("fail to switch eMMC boot partition\n");
+                       return ret;
+               }
+       }
+       offset = src_start % MMC_BLOCK_SIZE;
+       src_blk_cnt = (src_size + offset + MMC_BLOCK_SIZE - 1) / MMC_BLOCK_SIZE;
+       bytes = src_blk_cnt * MMC_BLOCK_SIZE;
+
+       mmio_write_32(MMC0_BYTCNT, bytes);
+
+       mmio_write_32(MMC0_RINTSTS, ~0);
+
+       desc_num = (bytes + MMC_DMA_MAX_BUFFER_SIZE - 1) /
+                  MMC_DMA_MAX_BUFFER_SIZE;
+
+       desc = (struct idmac_desc *)MMC_DESC_BASE;
+
+       for (i = 0; i < desc_num; i++) {
+               (desc + i)->des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH |
+                                  IDMAC_DES0_DIC;
+               (desc + i)->des1 = IDMAC_DES1_BS1(MMC_DMA_MAX_BUFFER_SIZE);
+               /* buffer address */
+               (desc + i)->des2 = MMC_DATA_BASE + MMC_DMA_MAX_BUFFER_SIZE * i;
+               /* next descriptor address */
+               (desc + i)->des3 = MMC_DESC_BASE +
+                                  (sizeof(struct idmac_desc) * (i + 1));
+       }
+       /* first descriptor */
+       desc->des0 |= IDMAC_DES0_FS;
+       /* last descriptor */
+       last_idx = desc_num - 1;
+       (desc + last_idx)->des0 |= IDMAC_DES0_LD;
+       (desc + last_idx)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH);
+       (desc + last_idx)->des1 = IDMAC_DES1_BS1(bytes - (last_idx *
+                                 MMC_DMA_MAX_BUFFER_SIZE));
+       /* set next descriptor address as 0 */
+       (desc + last_idx)->des3 = 0;
+
+       mmio_write_32(MMC0_DBADDR, MMC_DESC_BASE);
+
+       ret = mmc0_send_cmd(23, src_blk_cnt & 0xffff, buf);
+       if (ret) {
+               NOTICE("failed to send CMD23\n");
+               mmio_write_32(MMC0_RINTSTS, ~0);
+               return -EFAULT;
+       }
+       /* multiple read */
+       ret = mmc0_send_cmd(18, src_blk_start, buf);
+       if (ret) {
+               NOTICE("failed to send CMD18\n");
+               mmio_write_32(MMC0_RINTSTS, ~0);
+               return -EFAULT;
+       }
+
+       ret = wait_data_ready();
+       if (ret)
+               return ret;
+
+       src_addr = MMC_DATA_BASE + offset;
+       memcpy((void *)dst_addr, (void *)src_addr, src_size);
+
+       if (boot_partition) {
+               /* switch back to normal partition */
+               ret = mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG,
+                                         PART_CFG_BOOT_PARTITION1_ENABLE);
+               if (ret)
+                       NOTICE("fail to switch eMMC normal partition\n");
+       }
+       return ret;
+}
+
+static int write_multi_blocks(unsigned int lba, unsigned int count,
+                             unsigned int buffer, unsigned int boot_partition)
+{
+       unsigned int bytes, resp_buf[4], desc_num;
+       struct idmac_desc *desc = NULL;
+       int ret, last_idx, i;
+
+       if (buffer % 4) {
+               NOTICE("invalid buffer address:0x%x\n", buffer);
+               return -EINVAL;
+       }
+       if (boot_partition) {
+               /* switch to boot partition 1 */
+               ret = mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG,
+                                         PART_CFG_BOOT_PARTITION1_ENABLE |
+                                         PART_CFG_PARTITION1_ACCESS);
+               if (ret) {
+                       NOTICE("fail to switch eMMC boot partition\n");
+                       return ret;
+               }
+       }
+       bytes = MMC_BLOCK_SIZE * count;
+
+       mmio_write_32(MMC0_BYTCNT, bytes);
+       mmio_write_32(MMC0_RINTSTS, ~0);
+
+       desc_num = (bytes + MMC_DMA_MAX_BUFFER_SIZE - 1) /
+                  MMC_DMA_MAX_BUFFER_SIZE;
+
+       desc = (struct idmac_desc *)MMC_DESC_BASE;
+
+       for (i = 0; i < desc_num; i++) {
+               (desc + i)->des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH |
+                                  IDMAC_DES0_DIC;
+               (desc + i)->des1 = IDMAC_DES1_BS1(MMC_DMA_MAX_BUFFER_SIZE);
+               /* buffer address */
+               (desc + i)->des2 = buffer + MMC_DMA_MAX_BUFFER_SIZE * i;
+               /* next descriptor address */
+               (desc + i)->des3 = MMC_DESC_BASE +
+                                  (sizeof(struct idmac_desc) * (i + 1));
+       }
+       /* first descriptor */
+       desc->des0 |= IDMAC_DES0_FS;
+       /* last descriptor */
+       last_idx = desc_num - 1;
+       (desc + last_idx)->des0 |= IDMAC_DES0_LD;
+       (desc + last_idx)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH);
+       (desc + last_idx)->des1 = IDMAC_DES1_BS1(bytes - (last_idx *
+                                 MMC_DMA_MAX_BUFFER_SIZE));
+       /* set next descriptor address as 0 */
+       (desc + last_idx)->des3 = 0;
+
+       mmio_write_32(MMC0_DBADDR, MMC_DESC_BASE);
+
+       ret = mmc0_send_cmd(25, lba, resp_buf);
+       if (ret) {
+               NOTICE("failed to send CMD25\n");
+               mmio_write_32(MMC0_RINTSTS, ~0);
+               return -EFAULT;
+       }
+       ret = wait_data_ready();
+       if (ret)
+               return ret;
+
+       ret = mmc0_send_cmd(12, EMMC_FIX_RCA << 16, resp_buf);
+       if (ret) {
+               NOTICE("failed to send CMD12\n");
+               mmio_write_32(MMC0_RINTSTS, ~0);
+               return -EFAULT;
+       }
+
+       do {
+               ret = mmc0_send_cmd(13, EMMC_FIX_RCA << 16, resp_buf);
+               if (ret) {
+                       NOTICE("failed to send command 13\n");
+                       return ret;
+               }
+       } while (!(resp_buf[0] & MMC_STATUS_READY_FOR_DATA) ||
+                (mmc_state(resp_buf[0] != MMC_STATE_TRAN)));
+
+       if (boot_partition) {
+               /* switch back to normal partition */
+               ret = mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG,
+                                         PART_CFG_BOOT_PARTITION1_ENABLE);
+               if (ret)
+                       NOTICE("fail to switch eMMC normal partition\n");
+       }
+       return ret;
+}
+
+int mmc0_write(unsigned long mmc_start, size_t size,
+               unsigned long buffer, uint32_t boot_partition)
+{
+       unsigned int mmc_blk_start = mmc_start / MMC_BLOCK_SIZE;
+       unsigned int mmc_blk_cnt, offset;
+
+       offset = mmc_start % MMC_BLOCK_SIZE;
+       mmc_blk_cnt = (size + offset + MMC_BLOCK_SIZE - 1) / MMC_BLOCK_SIZE;
+
+       return write_multi_blocks(mmc_blk_start, mmc_blk_cnt, buffer,
+                                 boot_partition);
+}
+
+int init_mmc(void)
+{
+       int ret;
+
+       enable_mmc0();
+
+       ret = enum_mmc0_card();
+       if (ret)
+               return ret;
+
+       /* set boot mode to 8-bit */
+       mmc0_update_ext_csd(177, 2);
+       /* response to RESET signal */
+       mmc0_update_ext_csd(162, 1);
+       /* set access userdata area */
+       mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG,
+                           PART_CFG_BOOT_PARTITION1_ENABLE);
+
+       mmio_write_32(MMC0_RINTSTS, ~0);
+
+       return 0;
+}
diff --git a/plat/hikey/drivers/hi6553.c b/plat/hikey/drivers/hi6553.c
new file mode 100644 (file)
index 0000000..521c59a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <mmio.h>
+#include <hi6553.h>
+#include <hi6220.h>
+
+unsigned char hi6553_read_8(unsigned int offset)
+{
+       return mmio_read_8(PMUSSI_BASE + (offset << 2));
+}
+
+void hi6553_write_8(unsigned int offset, unsigned int value)
+{
+       mmio_write_8(PMUSSI_BASE + (offset << 2), value);
+}
diff --git a/plat/hikey/drivers/hisi_dvfs.c b/plat/hikey/drivers/hisi_dvfs.c
new file mode 100644 (file)
index 0000000..3fb4a8e
--- /dev/null
@@ -0,0 +1,808 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <partitions.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <mmio.h>
+#include <hi6220.h>
+#include <hi6553.h>
+
+#define ACPU_FREQ_MAX_NUM              5
+#define        ACPU_OPP_NUM                    7
+
+#define ACPU_VALID_VOLTAGE_MAGIC       (0x5A5AC5C5)
+
+#define ACPU_WAIT_TIMEOUT              (200)
+#define ACPU_WAIT_FOR_WFI_TIMOUT       (2000)
+#define ACPU_DFS_STATE_CNT             (0x10000)
+
+struct acpu_dvfs_sram_stru {
+       unsigned int magic;
+       unsigned int support_freq_num;
+       unsigned int support_freq_max;
+       unsigned int start_prof;
+       unsigned int vol[ACPU_OPP_NUM];
+};
+
+struct acpu_volt_cal_para {
+       unsigned int freq;
+       unsigned int ul_vol;
+       unsigned int dl_vol;
+       unsigned int core_ref_hpm;
+};
+
+struct ddr_volt_cal_para {
+       unsigned int freq;
+       unsigned int ul_vol;
+       unsigned int dl_vol;
+       unsigned int ddr_ref_hpm;
+};
+
+struct acpu_dvfs_opp_para {
+       unsigned int freq;
+       unsigned int acpu_clk_profile0;
+       unsigned int acpu_clk_profile1;
+       unsigned int acpu_vol_profile;
+       unsigned int acpu_pll_freq;
+       unsigned int acpu_pll_frac;
+};
+
+unsigned int efuse_acpu_freq[]= {
+       1200000, 1250000, 1300000, 1350000,
+       1400000, 1450000, 1500000, 1550000,
+       1600000, 1650000, 1700000, 1750000,
+       1800000, 1850000, 1900000, 1950000,
+};
+
+struct acpu_dvfs_opp_para hi6220_acpu_profile[] = {
+       { 208000,  0x61E5, 0x022, 0x3A, 0x5220102B, 0x05555555 },
+       { 432000,  0x10A6, 0x121, 0x3A, 0x5120102D, 0x10000005 },
+       { 729000,  0x2283, 0x100, 0x4A, 0x51101026, 0x10000005 },
+       { 960000,  0x1211, 0x100, 0x5B, 0x51101032, 0x10000005 },
+       { 1200000, 0x1211, 0x100, 0x6B, 0x5110207D, 0x10000005 },
+       { 1400000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 },
+       { 1500000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 },
+};
+
+struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile;
+struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf =
+       (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR;
+
+static inline void write_reg_mask(uintptr_t addr,
+                                 uint32_t val, uint32_t mask)
+{
+       uint32_t reg;
+
+       reg = mmio_read_32(addr);
+       reg = (reg & ~(mask)) | val;
+       mmio_write_32(addr, reg);
+}
+
+static inline uint32_t read_reg_mask(uintptr_t addr,
+                                    uint32_t mask, uint32_t offset)
+{
+       uint32_t reg;
+
+       reg = mmio_read_32(addr);
+       reg &= (mask << offset);
+       return (reg >> offset);
+}
+
+static int acpu_dvfs_syspll_cfg(unsigned int prof_id)
+{
+       uint32_t reg0 = 0;
+       uint32_t count = 0;
+       uint32_t clk_div_status = 0;
+
+       /*
+        * step 1:
+        *  - ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3;
+        *  - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1;
+        */
+       write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x3 << 12, 0x3 << 12);
+       write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 4,  0x1 << 4);
+
+       /*
+        * step 2:
+        *  - ACPUSYSPLLCFG.acpu_syspll_div_cfg:
+        *     208MHz, set to 0x5;
+        *     500MHz, set to 0x2;
+        *     other opps set to 0x1
+        */
+       if (prof_id == 0)
+               write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x5 << 0, 0x7 << 0);
+       else if (prof_id == 1)
+               write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x2 << 0, 0x7 << 0);
+       else
+               write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 0, 0x7 << 0);
+
+       /*
+        * step 3:
+        *  - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x3;
+        *  - ACPU_SC_VD_CTRL.tune_en_dif = 0
+        *  - ACPU_SC_VD_CTRL.tune_en_int = 0
+        *  - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1
+        *  - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1
+        */
+       clk_div_status = 0x3;
+       do {
+               reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, 20);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: clk div status timeout!\n", __func__);
+                       return -1;
+               }
+       } while(clk_div_status != reg0);
+
+       write_reg_mask(ACPU_SC_VD_CTRL, 0x0, (0x1 << 0) | (0x1 << 11));
+       write_reg_mask(PMCTRL_ACPUCLKDIV, 0x1 << 8, 0x3 << 8);
+       write_reg_mask(PMCTRL_ACPUPLLSEL, 0x1 << 0, 0x1 << 0);
+
+       return 0;
+}
+
+static void acpu_dvfs_clk_div_cfg(unsigned int prof_id,
+                                 unsigned int *cpuext_cfg,
+                                 unsigned int *acpu_ddr_cfg)
+{
+       if (0 == prof_id) {
+               write_reg_mask(PMCTRL_ACPUCLKDIV,
+                       (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+                       (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START),
+                       (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+                       (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START));
+               *cpuext_cfg = 0x1;
+               *acpu_ddr_cfg = 0x1;
+       } else if (1 == prof_id) {
+               write_reg_mask(PMCTRL_ACPUCLKDIV,
+                       (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+                       (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START),
+                       (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+                       (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START));
+               *cpuext_cfg = 0x1;
+               *acpu_ddr_cfg = 0x1;
+       } else {
+               /* ddr has not been inited */
+               write_reg_mask(PMCTRL_ACPUCLKDIV,
+                       (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+                       (0x0 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START),
+                       (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+                       (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START));
+               *cpuext_cfg = 0x1;
+               *acpu_ddr_cfg = 0x0;
+       }
+
+       return;
+}
+
+static int acpu_dvfs_freq_ascend(unsigned int cur_prof, unsigned int tar_prof)
+{
+       unsigned int reg0 = 0;
+       unsigned int reg1 = 0;
+       unsigned int reg2 = 0;
+       unsigned int count = 0;
+       unsigned int cpuext_cfg_val = 0;
+       unsigned int acpu_ddr_cfg_val = 0;
+       int ret = 0;
+
+       /*
+        * step 1:
+        *  - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3;
+        *  - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1;
+        *
+        * step 2:
+        *  - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x5 (208MHz)
+        *  - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x2 (500MHz)
+        *  - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x1 (Other OPPs)
+        *
+        * step 3:
+        *  - ACPU_SC_CPU_STAT.clk_div_status_vd = 0x3;
+        *  - ACPU_SC_VD_CTRL.tune_en_dif = 0x0;
+        *  - ACPU_SC_VD_CTRL.tune_en_int = 0x0;
+        *  - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1;
+        *  - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1
+        */
+       ret = acpu_dvfs_syspll_cfg(cur_prof);
+       if (ret)
+               return -1;
+
+       /*
+        * step 4:
+        *  - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1,
+                       SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: syspll sw status timeout\n", __func__);
+                       return -1;
+               }
+       } while(0x1 != reg0);
+
+       /* Enable VD functionality if > 800MHz */
+       if (acpu_dvfs_profile[tar_prof].freq > 800000) {
+
+               write_reg_mask(ACPU_SC_VD_HPM_CTRL,
+                       HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK);
+
+               /*
+                * step 5:
+                *  - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A;
+                *  - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB;
+                */
+               write_reg_mask(ACPU_SC_VD_HPM_CTRL,
+                       HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK);
+               write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL,
+                       ACPU_SC_VD_MASK_PATTERN_VAL,
+                       ACPU_SC_VD_MASK_PATTERN_MASK);
+
+               /*
+                * step 6:
+                *  - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF;
+                *  - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF;
+                *  - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF;
+                *  - ACPU_SC_VD_DLY_FIXED_CTRL  = 0x1;
+                */
+               mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF);
+               mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF);
+               mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF);
+               mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1);
+
+               /*
+                * step 7:
+                *  - ACPU_SC_VD_CTRL.shift_table0 = 0x1;
+                *  - ACPU_SC_VD_CTRL.shift_table1 = 0x3;
+                *  - ACPU_SC_VD_CTRL.shift_table2 = 0x5;
+                *  - ACPU_SC_VD_CTRL.shift_table3 = 0x6;
+                *
+                * step 8:
+                *  - ACPU_SC_VD_CTRL.tune = 0x7;
+                */
+               write_reg_mask(ACPU_SC_VD_CTRL,
+                       ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL,
+                       ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK);
+       }
+
+       /* step 9: ACPUPLLCTRL.acpupll_en_cfg = 0x0 */
+       write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0,
+               0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START);
+
+       /* step 10: set PMCTRL_ACPUPLLFREQ and PMCTRL_ACPUPLLFRAC */
+       mmio_write_32(PMCTRL_ACPUPLLFREQ,
+               acpu_dvfs_profile[tar_prof].acpu_pll_freq);
+       mmio_write_32(PMCTRL_ACPUPLLFRAC,
+               acpu_dvfs_profile[tar_prof].acpu_pll_frac);
+
+       /*
+        * step 11:
+        *  - wait for 1us;
+        *  - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1
+        */
+       count = 0 ;
+       while (count < ACPU_WAIT_TIMEOUT) {
+               count++;
+       }
+       write_reg_mask(PMCTRL_ACPUPLLCTRL,
+               0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START,
+               0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START);
+
+       /* step 12: PMCTRL_ACPUVOLPMUADDR = 0x100da */
+       mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da);
+
+       /*
+        * step 13:
+        *  - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (208MHz);
+        *  - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (500MHz);
+        *  - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x20 (798MHz);
+        *  - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1300MHz);
+        *  - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1500MHz);
+        */
+       write_reg_mask(PMCTRL_ACPUDESTVOL,
+               acpu_dvfs_profile[tar_prof].acpu_vol_profile,
+               ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1));
+
+       /*
+        * step 14:
+        *  - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol
+        *  - Polling ACPUVOLTIMEOUT.acpu_vol_timeout == 0x1
+        *  - Config PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg
+        *  - Config ACPUCLKDIV.cpuext_clk_div_cfg;
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F,
+                       SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START);
+               reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F,
+                       SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START);
+               reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1,
+                       SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: acpu destvol cfg timeout.\n", __func__);
+                       return -1;
+               }
+       } while((reg0 != reg1) || (0x1 != reg2));
+
+       acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val);
+
+       /*
+        * step 15:
+        *  - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat;
+        *  - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat;
+        *  - ACPUPLLCTRL.acpupll_timeout = 0x1;
+        *  - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0;
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3,
+                       SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START);
+               reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3,
+                       SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START);
+               reg2 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1,
+                       SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: acpu clk div cfg timeout.\n", __func__);
+                       return -1;
+               }
+       } while((cpuext_cfg_val != reg1) ||
+               (acpu_ddr_cfg_val != reg0) ||
+               (0x1 != reg2));
+
+       write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0,
+               0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START);
+
+       /*
+        * step 16:
+        *  - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1;
+        *  - ACPU_SC_VD_CTRL.force_clk_en = 0x0;
+        *  - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0;
+        *  - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0;
+        *  - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0;
+        *  - ACPU_SC_VD_CTRL.div_en_dif = 0x1;
+        *  - ACPU_SC_VD_CTRL.tune_en_int = 0x1;
+        *  - ACPU_SC_VD_CTRL.tune_en_dif = 0x1;
+        *  - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0;
+        *  - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0;
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1,
+                       SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: acpu pll sw status timeout.\n", __func__);
+                       return -1;
+               }
+       } while(0x1 != reg0);
+
+       if (acpu_dvfs_profile[tar_prof].freq > 800000)
+               write_reg_mask(ACPU_SC_VD_CTRL,
+                       ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK);
+
+       write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0,
+               (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) |
+               (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START));
+
+       return 0;
+}
+
+static int acpu_dvfs_freq_descend(unsigned int cur_prof, unsigned int tar_prof)
+{
+       unsigned int reg0 = 0;
+       unsigned int reg1 = 0;
+       unsigned int reg2 = 0;
+       unsigned int count = 0;
+       unsigned int cpuext_cfg_val = 0;
+       unsigned int acpu_ddr_cfg_val = 0;
+       int ret = 0;
+
+       ret = acpu_dvfs_syspll_cfg(tar_prof);
+       if (ret)
+               return -1;
+
+       /*
+        * step 4:
+        *  - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 2);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: syspll sw status timeout.\n", __func__);
+                       return -1;
+               }
+       } while(0x1 != reg0);
+
+       /*
+        * Step 5:
+        *  - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x0
+        */
+       write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, 0x1 << 0);
+
+       /*
+        * step 6
+        *  - Config PMCTRL_ACPUPLLFREQ and ACPUPLLFRAC
+        */
+       mmio_write_32(PMCTRL_ACPUPLLFREQ, acpu_dvfs_profile[tar_prof].acpu_pll_freq);
+       mmio_write_32(PMCTRL_ACPUPLLFRAC, acpu_dvfs_profile[tar_prof].acpu_pll_frac);
+
+       /*
+        * step 7:
+        *  - Wait 1us;
+        *  - Config PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1
+        */
+       count = 0 ;
+       while (count < ACPU_WAIT_TIMEOUT) {
+               count++;
+       }
+
+       write_reg_mask(PMCTRL_ACPUPLLCTRL,
+               0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START,
+               0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START);
+
+       /* Enable VD functionality if > 800MHz */
+       if (acpu_dvfs_profile[tar_prof].freq > 800000) {
+
+               write_reg_mask(ACPU_SC_VD_HPM_CTRL,
+                       HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK);
+
+               /*
+                * step 9:
+                *  - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A;
+                *  - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB;
+                */
+               write_reg_mask(ACPU_SC_VD_HPM_CTRL,
+                       HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK);
+               write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL,
+                       ACPU_SC_VD_MASK_PATTERN_VAL,
+                       ACPU_SC_VD_MASK_PATTERN_MASK);
+
+               /*
+                * step 10:
+                *  - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF;
+                *  - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF;
+                *  - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF;
+                *  - ACPU_SC_VD_DLY_FIXED_CTRL  = 0x1;
+                */
+               mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF);
+               mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF);
+               mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF);
+               mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1);
+
+               /*
+                * step 11:
+                *  - ACPU_SC_VD_CTRL.shift_table0 = 0x1;
+                *  - ACPU_SC_VD_CTRL.shift_table1 = 0x3;
+                *  - ACPU_SC_VD_CTRL.shift_table2 = 0x5;
+                *  - ACPU_SC_VD_CTRL.shift_table3 = 0x6;
+                *
+                * step 12:
+                *  - ACPU_SC_VD_CTRL.tune = 0x7;
+                */
+               write_reg_mask(ACPU_SC_VD_CTRL,
+                       ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL,
+                       ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK);
+       }
+
+       /*
+        * step 13:
+        *  - Pollig PMCTRL_ACPUPLLCTRL.acpupll_timeout == 0x1;
+        *  - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0;
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1,
+                       SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: acpupll timeout.\n", __func__);
+                       return -1;
+               }
+       } while(0x1 != reg0);
+
+       write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0,
+               0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START);
+
+       /*
+        * step 14:
+        *  - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1;
+        *  - ACPU_SC_VD_CTRL.force_clk_en = 0x0;
+        *  - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0;
+        *  - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0;
+        *  - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0;
+        *  - ACPU_SC_VD_CTRL.div_en_dif = 0x1;
+        *  - ACPU_SC_VD_CTRL.tune_en_int = 0x1;
+        *  - ACPU_SC_VD_CTRL.tune_en_dif = 0x1;
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1,
+                       SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: acpupll sw status timeout.\n", __func__);
+                       return -1;
+               }
+       } while(0x1 != reg0);
+
+       if (acpu_dvfs_profile[tar_prof].freq > 800000)
+               write_reg_mask(ACPU_SC_VD_CTRL,
+                       ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK);
+
+       /*
+        * step 15:
+        *  - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0;
+        *  - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0;
+        */
+       write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0,
+               (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) |
+               (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START));
+
+       /*
+        * step 16:
+        *  - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x0;
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3,
+                       ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: clk div status timeout.\n", __func__);
+                       return -1;
+               }
+       } while(0x0 != reg0);
+
+       acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val);
+
+       /*
+        * step 17:
+        *  - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat;
+        *  - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat;
+        *  - PMCTRL_ACPUVOLPMUADDR = 0x1006C;
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3,
+                       SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START);
+               reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3,
+                       SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: acpu clk div cfg timeout.\n", __func__);
+                       return -1;
+               }
+       } while((cpuext_cfg_val != reg0) || (acpu_ddr_cfg_val != reg1));
+
+       mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da);
+
+       /*
+        * step 16:
+        *  - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1;
+        *  - ACPU_SC_VD_CTRL.force_clk_en = 0x0;
+        *  - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0;
+        *  - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0;
+        *  - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0;
+        *  - ACPU_SC_VD_CTRL.div_en_dif = 0x1;
+        *  - ACPU_SC_VD_CTRL.tune_en_int = 0x1;
+        *  - ACPU_SC_VD_CTRL.tune_en_dif = 0x1;
+        *  - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0;
+        *  - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0;
+        */
+       write_reg_mask(PMCTRL_ACPUDESTVOL,
+               acpu_dvfs_profile[tar_prof].acpu_vol_profile,
+               ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1));
+
+       /*
+        * step 19:
+        *  - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol
+        *  - ACPUVOLTIMEOUT.acpu_vol_timeout = 0x1;
+        */
+       count = 0;
+       do {
+               reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F,
+                       SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START);
+               reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F,
+                       SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START);
+               reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1,
+                       SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START);
+               if ((count++) > ACPU_DFS_STATE_CNT) {
+                       ERROR("%s: acpu destvol cfg timeout.\n", __func__);
+                       return -1;
+               }
+       } while((reg0 != reg1) || (0x1 != reg2));
+
+       return 0;
+}
+
+int acpu_dvfs_target(unsigned int curr_prof, unsigned int target_prof)
+{
+       int ret = 0;
+
+       if (curr_prof == target_prof) {
+               INFO("%s: target_prof is equal curr_prof: is %d!\n",
+                       __func__, curr_prof);
+               return 0;
+       }
+
+       if ((curr_prof >= ACPU_FREQ_MAX_NUM) ||
+           (target_prof >= ACPU_FREQ_MAX_NUM)) {
+               INFO("%s: invalid parameter %d %d\n",
+                       __func__, curr_prof, target_prof);
+               return -1;
+       }
+
+       if (target_prof > acpu_dvfs_sram_buf->support_freq_num)
+               target_prof = acpu_dvfs_sram_buf->support_freq_num;
+
+       if (target_prof < curr_prof)
+               ret = acpu_dvfs_freq_descend(curr_prof, target_prof);
+       else if (target_prof > curr_prof)
+               ret = acpu_dvfs_freq_ascend(curr_prof, target_prof);
+
+       if (ret) {
+               ERROR("%s: acpu_dvfs_target failed!\n");
+               return -1;
+       }
+
+       /* Complete acpu dvfs setting and set magic number */
+       acpu_dvfs_sram_buf->start_prof = target_prof;
+       acpu_dvfs_sram_buf->magic = ACPU_VALID_VOLTAGE_MAGIC;
+
+       mmio_write_32(DDR_DFS_FREQ_ADDR, 800000);
+       return 0;
+}
+
+static int acpu_dvfs_set_freq(void)
+{
+       unsigned int i;
+       unsigned int curr_prof;
+       unsigned int target_prof;
+       unsigned int max_freq = 0;
+
+       max_freq = acpu_dvfs_sram_buf->support_freq_max;
+
+       for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) {
+
+               if (max_freq == hi6220_acpu_profile[i].freq) {
+                       target_prof = i;
+                       break;
+               }
+       }
+
+       if (i == acpu_dvfs_sram_buf->support_freq_num) {
+               ERROR("%s: cannot found max freq profile\n", __func__);
+               return -1;
+       }
+
+       curr_prof = 0;
+       target_prof = i;
+
+       /* if max freq is 208MHz, do nothing */
+       if (curr_prof == target_prof)
+               return 0;
+
+       if (acpu_dvfs_target(curr_prof, target_prof)) {
+               ERROR("%s: set acpu freq failed!", __func__);
+               return -1;
+       }
+
+       INFO("%s: support freq num is %d\n",
+               __func__, acpu_dvfs_sram_buf->support_freq_num);
+       INFO("%s: start prof is 0x%x\n",
+               __func__,  acpu_dvfs_sram_buf->start_prof);
+       INFO("%s: magic is 0x%x\n",
+               __func__, acpu_dvfs_sram_buf->magic);
+       INFO("%s: voltage:\n", __func__);
+       for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++)
+               INFO("  - %d: 0x%x\n", i, acpu_dvfs_sram_buf->vol[i]);
+
+       NOTICE("%s: set acpu freq success!", __func__);
+        return 0;
+}
+
+struct acpu_dvfs_volt_setting
+{
+       unsigned int magic;
+       unsigned int support_freq_num;
+       unsigned int support_freq_max;
+       unsigned int start_prof;
+       unsigned int vol[7];
+       unsigned int hmp_dly_threshold[7];
+};
+
+static void acpu_dvfs_volt_init(void)
+{
+       struct acpu_dvfs_volt_setting *volt;
+
+       /*
+        * - set default voltage;
+        * - set pmu address;
+        * - set voltage up and down step;
+        * - set voltage stable time;
+        */
+       mmio_write_32(PMCTRL_ACPUDFTVOL, 0x4a);
+       mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0xda);
+       mmio_write_32(PMCTRL_ACPUVOLUPSTEP, 0x1);
+       mmio_write_32(PMCTRL_ACPUVOLDNSTEP, 0x1);
+       mmio_write_32(PMCTRL_ACPUPMUVOLUPTIME, 0x60);
+       mmio_write_32(PMCTRL_ACPUPMUVOLDNTIME, 0x60);
+       mmio_write_32(PMCTRL_ACPUCLKOFFCFG, 0x1000);
+
+       volt= (void *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR;
+       volt->magic = 0x5a5ac5c5;
+       volt->support_freq_num = 5;
+       volt->support_freq_max = 1200000;
+       volt->start_prof = 4;
+       volt->vol[0] = 0x49;
+       volt->vol[1] = 0x49;
+       volt->vol[2] = 0x50;
+       volt->vol[3] = 0x60;
+       volt->vol[4] = 0x78;
+       volt->vol[5] = 0x78;
+       volt->vol[6] = 0x78;
+
+       volt->hmp_dly_threshold[0] = 0x0;
+       volt->hmp_dly_threshold[1] = 0x0;
+       volt->hmp_dly_threshold[2] = 0x0;
+       volt->hmp_dly_threshold[3] = 0x0e8b0e45;
+       volt->hmp_dly_threshold[4] = 0x10691023;
+       volt->hmp_dly_threshold[5] = 0x10691023;
+       volt->hmp_dly_threshold[6] = 0x10691023;
+
+       INFO("%s: success!\n", __func__);
+}
+
+void init_acpu_dvfs(void)
+{
+       unsigned int i = 0;
+
+       INFO("%s: pmic version %d\n", __func__, hi6553_read_8(VERSION_REG));
+
+       /* init parameters */
+       mmio_write_32(ACPU_CHIP_MAX_FREQ, efuse_acpu_freq[8]);
+       INFO("%s: ACPU_CHIP_MAX_FREQ=0x%x.\n",
+               __func__, mmio_read_32(ACPU_CHIP_MAX_FREQ));
+
+        /* set maximum support frequency to 1.2GHz */
+        for(i = 0; i < ACPU_FREQ_MAX_NUM; i++)
+               acpu_dvfs_sram_buf->vol[i] = hi6220_acpu_profile[i].acpu_vol_profile;
+
+        acpu_dvfs_sram_buf->support_freq_num = ACPU_FREQ_MAX_NUM;
+        acpu_dvfs_sram_buf->support_freq_max = 1200000;
+
+       /* init acpu dvfs */
+       acpu_dvfs_volt_init();
+       acpu_dvfs_set_freq();
+
+       return;
+}
diff --git a/plat/hikey/drivers/hisi_ipc.c b/plat/hikey/drivers/hisi_ipc.c
new file mode 100644 (file)
index 0000000..c3b34d3
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hisi_ipc.h>
+#include <hisi_sram_map.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define BIT(x) (0x1 << (x))
+
+static int  _ipc_init = 0;
+
+static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = {
+       {
+               HISI_IPC_MCU_INT_SRC_ACPU0_PD,
+               HISI_IPC_MCU_INT_SRC_ACPU1_PD,
+               HISI_IPC_MCU_INT_SRC_ACPU2_PD,
+               HISI_IPC_MCU_INT_SRC_ACPU3_PD,
+       },
+       {
+               HISI_IPC_MCU_INT_SRC_ACPU4_PD,
+               HISI_IPC_MCU_INT_SRC_ACPU5_PD,
+               HISI_IPC_MCU_INT_SRC_ACPU6_PD,
+               HISI_IPC_MCU_INT_SRC_ACPU7_PD,
+       }
+};
+
+int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu,
+                                        unsigned int cluster)
+{
+       unsigned int val = 0, cpu_val = 0;
+       int i;
+
+       val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
+       val = val >> (cluster * 16);
+
+       for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) {
+
+               if (cpu == i)
+                       continue;
+
+               cpu_val = (val >> (i * 4)) & 0xF;
+               if (cpu_val == 0x8)
+                       return 0;
+        }
+
+       return 1;
+}
+
+int hisi_cpus_powered_off_besides_curr(unsigned int cpu)
+{
+       unsigned int val;
+
+       val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
+       return (val == (0x8 << (cpu * 4)));
+}
+
+static void hisi_ipc_send(unsigned int ipc_num)
+{
+       if (!_ipc_init) {
+               printf("error ipc base is null!!!\n");
+               return;
+       }
+
+       mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num);
+}
+
+void hisi_ipc_spin_lock(unsigned int signal)
+{
+       unsigned int hs_ctrl;
+
+       if (signal >= HISI_IPC_INT_SRC_NUM)
+               return;
+
+       do {
+               hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal));
+       } while (hs_ctrl);
+}
+
+void hisi_ipc_spin_unlock(unsigned int signal)
+{
+       if (signal >= HISI_IPC_INT_SRC_NUM)
+               return;
+
+       mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0);
+}
+
+void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster,
+                        unsigned int mode)
+{
+       unsigned int val = 0;
+       unsigned int offset;
+
+       if (mode == HISI_IPC_PM_ON)
+               offset = cluster * 16 + cpu * 4;
+       else
+               offset = cluster * 16 + cpu * 4 + 1;
+
+       hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+       val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
+       val |= (0x01 << offset);
+       mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
+       hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+       hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
+}
+
+void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster)
+{
+       hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON);
+}
+
+void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster)
+{
+       hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF);
+}
+
+void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster,
+                            unsigned int mode)
+{
+       unsigned int val = 0;
+       unsigned int offset;
+
+       if (mode == HISI_IPC_PM_ON)
+               offset = cluster * 4;
+       else
+               offset = cluster * 4 + 1;
+
+       hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+       val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
+       val |= (0x01 << offset);
+       mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
+       hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+       hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
+}
+
+void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster)
+{
+       hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON);
+}
+
+void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster)
+{
+       hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF);
+}
+
+void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster)
+{
+       unsigned int val = 0;
+       unsigned int offset;
+
+       offset = cluster * 16 + cpu * 4 + 2;
+
+       hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+       val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
+       val |= (0x01 << offset);
+       mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
+       hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+       hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
+}
+
+void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster)
+{
+       unsigned int val;
+       unsigned int offset;
+
+       offset = cluster * 4 + 1;
+
+       hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+       if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) {
+               val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
+               val |= (0x01 << offset);
+               mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
+       }
+       hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+       hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
+}
+
+void hisi_ipc_psci_system_off(void)
+{
+       hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD);
+}
+
+int hisi_ipc_init(void)
+{
+       _ipc_init = 1;
+
+       mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8);
+       mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8);
+       return 0;
+}
diff --git a/plat/hikey/drivers/hisi_mcu.c b/plat/hikey/drivers/hisi_mcu.c
new file mode 100644 (file)
index 0000000..50d5f54
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <partitions.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <mmio.h>
+#include <hi6220.h>
+
+#define MCU_SECTION_MAX                30
+
+enum MCU_IMAGE_SEC_TYPE_ENUM {
+       MCU_IMAGE_SEC_TYPE_TEXT = 0,    /* text section */
+       MCU_IMAGE_SEC_TYPE_DATA,        /* data section */
+       MCU_IMAGE_SEC_TYPE_BUTT
+};
+
+enum MCU_IMAGE_SEC_LOAD_ENUM {
+       MCU_IMAGE_SEC_LOAD_STATIC = 0,
+       MCU_IMAGE_SEC_LOAD_DYNAMIC,
+       MCU_IMAGE_SEC_LOAD_BUFFER,
+       MCU_IMAGE_SEC_LOAD_MODEM_ENTRY,
+       MCU_IMAGE_SEC_LOAD_BUTT
+};
+
+struct mcu_image_sec {
+       unsigned short serial;
+       char type;
+       char load_attr;
+       uint32_t src_offset;            /* offset in image */
+       uint32_t dst_offset;            /* offset in memory */
+       uint32_t size;
+};
+
+struct mcu_image_head {
+       char time_stamp[24];
+       uint32_t image_size;
+       uint32_t secs_num;
+       struct mcu_image_sec secs[MCU_SECTION_MAX];
+};
+
+#define SOC_SRAM_M3_BASE_ADDR          (0xF6000000)
+
+#define MCU_SRAM_SIZE                  (0x0000C000)
+#define MCU_CACHE_SIZE                 (0x00004000)
+#define MCU_CODE_SIZE                  (MCU_SRAM_SIZE - MCU_CACHE_SIZE)
+
+#define MCU_SYS_MEM_ADDR               (0x05E00000)
+#define MCU_SYS_MEM_SIZE               (0x00100000)
+
+#if 0
+static uint32_t ap2mcu_addr(uint32_t ap_addr)
+{
+       if (ap_addr >= SOC_SRAM_M3_BASE_ADDR &&
+           ap_addr < SOC_SRAM_M3_BASE_ADDR + MCU_SRAM_SIZE)
+               return ap_addr - SOC_SRAM_M3_BASE_ADDR;
+       else if (ap_addr >= MCU_SYS_MEM_ADDR &&
+                ap_addr < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE )
+               return ap_addr - MCU_SYS_MEM_ADDR + MCU_SRAM_SIZE;
+       else
+               return ap_addr;
+}
+#endif
+
+static uint32_t mcu2ap_addr(uint32_t mcu_addr)
+{
+       if (mcu_addr < MCU_CODE_SIZE)
+               return (mcu_addr + SOC_SRAM_M3_BASE_ADDR);
+       else if ((mcu_addr >= MCU_SRAM_SIZE) &&
+                (mcu_addr < MCU_SRAM_SIZE + MCU_SYS_MEM_SIZE))
+               return mcu_addr - MCU_SRAM_SIZE + MCU_SYS_MEM_ADDR;
+       else
+               return mcu_addr;
+}
+
+static int is_binary_header_invalid(struct mcu_image_head *head,
+                                   unsigned length)
+{
+       /* invalid cases */
+       if ((head->image_size == 0) ||
+           (head->image_size > length) ||
+           (head->secs_num > MCU_SECTION_MAX) ||
+           (head->secs_num == 0))
+               return 1;
+
+        return 0;
+}
+
+static int is_binary_section_invalid(struct mcu_image_sec *sec,
+                                    struct mcu_image_head *head)
+{
+       unsigned long ap_dst_offset = 0;
+
+       if ((sec->serial >= head->secs_num) ||
+           (sec->src_offset + sec->size > head->image_size))
+               return 1;
+
+       if ((sec->type >= MCU_IMAGE_SEC_TYPE_BUTT) ||
+           (sec->load_attr >= MCU_IMAGE_SEC_LOAD_BUTT))
+               return 1;
+
+        ap_dst_offset = mcu2ap_addr(sec->dst_offset);
+        if ((ap_dst_offset >= SOC_SRAM_M3_BASE_ADDR) &&
+           (ap_dst_offset < SOC_SRAM_M3_BASE_ADDR + 0x20000 - sec->size))
+               return 0;
+        else if ((ap_dst_offset >= MCU_SYS_MEM_ADDR) &&
+                (ap_dst_offset < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE - sec->size))
+               return 0;
+        else if ((ap_dst_offset >= 0xfff8e000) &&
+                (ap_dst_offset < 0xfff91c00 - sec->size))
+               return 0;
+
+       ERROR("%s: mcu destination address invalid.\n", __func__);
+       ERROR("%s: number=%d, dst offset=%d size=%d\n",
+               __func__, sec->serial, sec->dst_offset, sec->size);
+       return 1;
+}
+
+void hisi_mcu_enable_sram(void)
+{
+       mmio_write_32(AO_SC_PERIPH_CLKEN4,
+                     AO_SC_PERIPH_CLKEN4_HCLK_IPC_S |
+                     AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS);
+
+       /* set register to enable dvfs which is used by mcu */
+       mmio_write_32(PERI_SC_RESERVED8_ADDR, 0x0A001022);
+
+       /* mcu mem is powered on, need de-assert reset */
+       mmio_write_32(AO_SC_PERIPH_RSTDIS4,
+                     AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N);
+
+       /* enable mcu hclk */
+       mmio_write_32(AO_SC_PERIPH_CLKEN4,
+                     AO_SC_PERIPH_CLKEN4_HCLK_MCU |
+                     AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP);
+}
+
+void hisi_mcu_start_run(void)
+{
+       unsigned int val;
+
+#if 0
+        /* set mcu's self loop instruction 0xE7FE at entry point */
+        val = mmio_read_32((SOC_SRAM_M3_BASE_ADDR + 0x200));
+        val &= 0xFFFF0000;
+        val |= 0xE7FE;
+        mmio_write_32((SOC_SRAM_M3_BASE_ADDR + 0x200), val);
+#endif
+
+       /* set mcu ddr remap configuration */
+       mmio_write_32(AO_SC_MCU_SUBSYS_CTRL2, MCU_SYS_MEM_ADDR);
+
+       /* de-assert reset for mcu and to run */
+       mmio_write_32(AO_SC_PERIPH_RSTDIS4,
+               AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N |
+               AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N |
+               AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N |
+               AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N);
+
+       val = mmio_read_32(AO_SC_SYS_CTRL2);
+       mmio_write_32(AO_SC_SYS_CTRL2,
+               val | AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR);
+
+       INFO("%s: AO_SC_SYS_CTRL2=%x\n", __func__,
+               mmio_read_32(AO_SC_SYS_CTRL2));
+}
+
+int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size)
+{
+       unsigned int i;
+       struct mcu_image_head *head;
+       char *buf;
+
+       head = (struct mcu_image_head *)image_base;
+       if (is_binary_header_invalid(head, image_size)) {
+               ERROR("Invalid %s image header.\n", head->time_stamp);
+               return -1;
+       }
+
+       buf = (char *)head;
+       for (i = 0; i < head->secs_num; i++) {
+
+               int *src, *dst;
+
+               /* check the sections */
+               if (is_binary_section_invalid(&head->secs[i], head)) {
+                       ERROR("Invalid mcu section.\n");
+                       return -1;
+               }
+
+               /* check if the section is static-loaded */
+               if (head->secs[i].load_attr != MCU_IMAGE_SEC_LOAD_STATIC)
+                       continue;
+
+               /* copy the sections */
+               src = (int *)(intptr_t)(buf + head->secs[i].src_offset);
+               dst = (int *)(intptr_t)mcu2ap_addr(head->secs[i].dst_offset);
+
+               memcpy((void *)dst, (void *)src, head->secs[i].size);
+
+               INFO("%s: mcu sections %d:\n", __func__, i);
+               INFO("%s:  src  = 0x%x\n", __func__, src);
+               INFO("%s:  dst  = 0x%x\n", __func__, dst);
+               INFO("%s:  size = %d\n", __func__, head->secs[i].size);
+
+               INFO("%s:  [SRC 0x%x] 0x%x 0x%x 0x%x 0x%x\n", __func__,
+                       src, src[0], src[1], src[2], src[3]);
+               INFO("%s:  [DST 0x%x] 0x%x 0x%x 0x%x 0x%x\n", __func__,
+                       dst, dst[0], dst[1], dst[2], dst[3]);
+       }
+
+       return 0;
+}
diff --git a/plat/hikey/drivers/hisi_pwrc.c b/plat/hikey/drivers/hisi_pwrc.c
new file mode 100644 (file)
index 0000000..9f189da
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bakery_lock.h>
+#include <mmio.h>
+#include <hisi_ipc.h>
+#include <hisi_pwrc.h>
+#include <hisi_sram_map.h>
+#include <hi6220_regs_acpu.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <platform_def.h>
+
+#define CLUSTER_CORE_COUNT             (4)
+#define CLUSTER_CORE_MASK              ((1 << CLUSTER_CORE_COUNT) - 1)
+
+#define BIT(x) (0x1 << (x))
+
+void hisi_pwrc_set_core_bx_addr(unsigned int core, unsigned int cluster,
+                               uintptr_t entry_point)
+{
+       uintptr_t *core_entry = (uintptr_t *)PWRCTRL_ACPU_ASM_D_ARM_PARA_AD;
+       unsigned int i;
+
+       if (!core_entry) {
+               printf("%s: core entry point is null!\n", __func__);
+               return;
+       }
+
+       i = cluster * CLUSTER_CORE_COUNT + core;
+       mmio_write_64((uintptr_t)(core_entry + i), entry_point);
+}
+
+void hisi_pwrc_set_cluster_wfi(unsigned int cluster)
+{
+       unsigned int reg = 0;
+
+       if (cluster == 0) {
+               reg = mmio_read_32(ACPU_CTRL_BASE + 0x0E4);
+               reg |= BIT(0);
+               mmio_write_32(ACPU_CTRL_BASE + 0x0E4, reg);
+       } else if (cluster == 1) {
+               reg = mmio_read_32(ACPU_CTRL_BASE + 0x0E4);
+               reg |= BIT(16);
+               mmio_write_32(ACPU_CTRL_BASE + 0x0E4, reg);
+       }
+}
+
+int hisi_pwrc_setup(void)
+{
+       unsigned int reg;
+       extern char pm_asm_code[], pm_asm_code_end[];
+       extern char v7_asm[], v7_asm_end[];
+
+       mmio_write_32(ACPU_SC_CPUx_RVBARADDR(0), PWRCTRL_ACPU_ASM_CODE_BASE >> 2);
+       mmio_write_32(ACPU_SC_CPUx_RVBARADDR(1), PWRCTRL_ACPU_ASM_CODE_BASE >> 2);
+       mmio_write_32(ACPU_SC_CPUx_RVBARADDR(2), PWRCTRL_ACPU_ASM_CODE_BASE >> 2);
+       mmio_write_32(ACPU_SC_CPUx_RVBARADDR(3), PWRCTRL_ACPU_ASM_CODE_BASE >> 2);
+       mmio_write_32(ACPU_SC_CPUx_RVBARADDR(4), PWRCTRL_ACPU_ASM_CODE_BASE >> 2);
+       mmio_write_32(ACPU_SC_CPUx_RVBARADDR(5), PWRCTRL_ACPU_ASM_CODE_BASE >> 2);
+       mmio_write_32(ACPU_SC_CPUx_RVBARADDR(6), PWRCTRL_ACPU_ASM_CODE_BASE >> 2);
+       mmio_write_32(ACPU_SC_CPUx_RVBARADDR(7), PWRCTRL_ACPU_ASM_CODE_BASE >> 2);
+
+       memset((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, 0, 0x400);
+       memcpy((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, (void *)v7_asm,
+              v7_asm_end - v7_asm);
+
+       memcpy((void *)PWRCTRL_ACPU_ASM_CODE_BASE, (void *)pm_asm_code,
+              pm_asm_code_end - pm_asm_code);
+
+       reg = mmio_read_32(0xF7800000 + 0x004);
+       reg |= BIT(0x1) | BIT(17);
+       mmio_write_32(0xF7800000 + 0x004, reg);
+
+       return 0;
+}
diff --git a/plat/hikey/drivers/hisi_pwrc_sram.S b/plat/hikey/drivers/hisi_pwrc_sram.S
new file mode 100644 (file)
index 0000000..ae8eec4
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <hisi_sram_map.h>
+
+       .global pm_asm_code
+       .global pm_asm_code_end
+       .global v7_asm
+       .global v7_asm_end
+
+       .align  3
+func pm_asm_code
+       mov     x0, 0
+       msr     oslar_el1, x0
+
+       mrs     x0, s3_1_c15_c2_0
+       bic     x0, x0, #0x1E000000
+       orr     x0, x0, #0x180000
+       orr     x0, x0, #0xe000
+       msr     s3_1_c15_c2_0, x0
+
+       mrs     x3, actlr_el3
+        orr    x3, x3, #(0x1<<5)
+        msr    actlr_el3, x3
+
+        mrs    x3, actlr_el2
+        orr    x3, x3, #(0x1<<5)
+        msr    actlr_el2, x3
+
+       ldr     x3, =PWRCTRL_ACPU_ASM_D_ARM_PARA_AD
+       mrs     x0, mpidr_el1
+       and     x1, x0, #MPIDR_CPU_MASK
+       and     x0, x0, #MPIDR_CLUSTER_MASK
+       add     x0, x1, x0, LSR #6
+pen:   ldr     x4, [x3, x0, LSL #3]
+       cbz     x4, pen
+
+       mov     x0, #0x0
+       mov     x1, #0x0
+       mov     x2, #0x0
+       mov     x3, #0x0
+       br      x4
+
+       .ltorg
+
+pm_asm_code_end:
+
+       .align  3
+       .section .rodata.v7_asm, "aS"
+v7_asm:
+       .word   0xE1A00000      // nop
+       .word   0xE3A02003      // mov r2, #3
+       .word   0xEE0C2F50      // mcr 15, 0, r2, cr12, cr0, {2}
+       .word   0xE320F003      // wfi
+
+       .ltorg
+v7_asm_end:
diff --git a/plat/hikey/drivers/sp804_timer.c b/plat/hikey/drivers/sp804_timer.c
new file mode 100644 (file)
index 0000000..269bf1c
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <hi6220.h>
+#include <mmio.h>
+#include <sp804_timer.h>
+
+/* Init dual timer0 (TIMER00 & TIMER01) */
+void hi6220_timer_init(void)
+{
+       unsigned int data;
+
+       /* select 32KHz as the clock of dual timer0 */
+       /* FIXME: But I find that it's 19.2MHz, not 32KHz. */
+       data = mmio_read_32(AO_SC_TIMER_EN0);
+       while (data & 3) {
+               data &= ~3;
+               data |= 3 << 16;
+               mmio_write_32(AO_SC_TIMER_EN0, data);
+               data = mmio_read_32(AO_SC_TIMER_EN0);
+       }
+       /* enable the pclk of dual timer0 */
+       data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
+       while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) {
+               mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0);
+               data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
+       }
+       /* reset dual timer0 */
+       data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
+       mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0);
+       do {
+               data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
+       } while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0));
+       /* unreset dual timer0 */
+       mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0);
+       do {
+               data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
+       } while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0));
+       
+       /* disable timer00 */
+       mmio_write_32(TIMER00_CONTROL, 0);
+       mmio_write_32(TIMER00_LOAD, 0xffffffff);
+       /* free running */
+       mmio_write_32(TIMER00_CONTROL, 0x82);
+}
+
+static unsigned int get_timer_value(void)
+{
+       return mmio_read_32(TIMER00_VALUE);
+}
+
+void udelay(int us)
+{
+       unsigned int start, cnt, delta, delta_us;
+
+       if (us <= 0)
+               us = 1;
+       /* counter is decreasing */
+       start = get_timer_value();
+       do {
+               cnt = get_timer_value();
+               if (cnt > start) {
+                       delta = 0xffffffff - cnt;
+                       delta += start;
+               } else
+                       delta = start - cnt;
+               delta_us = (delta * 10) / 192;
+       } while (delta_us < us);
+}
+
+void mdelay(int ms)
+{
+       unsigned int start, cnt, delta, delta_ms;
+
+       if (ms <= 0)
+               ms = 1;
+
+       /* counter is decreasing */
+       start = get_timer_value();
+       do {
+               cnt = get_timer_value();
+               if (cnt > start) {
+                       delta = 0xffffffff - cnt;
+                       delta += start;
+               } else
+                       delta = start - cnt;
+               delta_ms = delta / 19200;
+       } while (delta_ms < ms);
+}
diff --git a/plat/hikey/hikey_def.h b/plat/hikey/hikey_def.h
new file mode 100644 (file)
index 0000000..2007633
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIKEY_DEF_H__
+#define __HIKEY_DEF_H__
+
+#define DEVICE_BASE                    0xf4000000
+#define DEVICE_SIZE                    0x05800000
+
+/* The size of DDR RAM is 1GB. */
+#define DRAM_BASE                      0x00000000
+#define DRAM_SIZE                      0x40000000
+
+#define XG2RAM0_BASE                   0xF9800000
+#define XG2RAM0_SIZE                   0x00400000
+
+#define PLAT_TRUSTED_SRAM_ID   0
+#define PLAT_TRUSTED_DRAM_ID   1
+
+/*
+ * DRAM at 0x0000_0000 is divided in two regions:
+ *   - Secure DRAM (default is the top 16MB)
+ *   - Non-Secure DRAM (remaining DRAM starting at DRAM_BASE)
+ */
+#define DRAM_SEC_SIZE                  0x01000000
+#define DRAM_SEC_BASE                  (DRAM_BASE + DRAM_SIZE - DRAM_SEC_SIZE)
+
+#define DRAM_NS_BASE                   DRAM_BASE
+#define DRAM_NS_SIZE                   (DRAM_SIZE - DRAM_SEC_SIZE)
+
+#define SRAM_BASE                      0xFFF80000
+#define SRAM_SIZE                      0x00012000
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+#define GICD_BASE                      0xF6801000
+#define GICC_BASE                      0xF6802000
+
+#define IRQ_SEC_PHY_TIMER              29
+#define IRQ_SEC_SGI_0                  8
+#define IRQ_SEC_SGI_1                  9
+#define IRQ_SEC_SGI_2                  10
+#define IRQ_SEC_SGI_3                  11
+#define IRQ_SEC_SGI_4                  12
+#define IRQ_SEC_SGI_5                  13
+#define IRQ_SEC_SGI_6                  14
+#define IRQ_SEC_SGI_7                  15
+#define IRQ_SEC_SGI_8                  16
+
+/*******************************************************************************
+ * PL011 related constants
+ ******************************************************************************/
+#define PL011_UART0_BASE               0xF8015000
+#define PL011_UART3_BASE               0xF7113000
+
+#define PL011_BAUDRATE                 115200
+
+#define PL011_UART_CLK_IN_HZ           19200000
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define CCI400_BASE                    0xF6E90000
+#define CCI400_SL_IFACE3_CLUSTER_IX    0
+#define CCI400_SL_IFACE4_CLUSTER_IX    1
+
+#endif /* __HIKEY_DEF_H__ */
diff --git a/plat/hikey/hikey_private.h b/plat/hikey/hikey_private.h
new file mode 100644 (file)
index 0000000..0627687
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIKEY_PRIVATE_H__
+#define __HIKEY_PRIVATE_H__
+
+#include <bl_common.h>
+
+/*******************************************************************************
+ * This structure represents the superset of information that is passed to
+ * BL3-1 e.g. while passing control to it from BL2 which is bl31_params
+ * and other platform specific params
+ ******************************************************************************/
+typedef struct bl2_to_bl31_params_mem {
+       struct bl31_params bl31_params;
+       struct image_info bl31_image_info;
+       struct image_info bl32_image_info;
+       struct image_info bl33_image_info;
+       struct entry_point_info bl33_ep_info;
+       struct entry_point_info bl32_ep_info;
+       struct entry_point_info bl31_ep_info;
+} bl2_to_bl31_params_mem_t;
+
+#define RANDOM_MAX             0x7fffffffffffffff
+#define RANDOM_MAGIC           0x9a4dbeaf
+
+struct random_serial_num {
+       uint64_t        magic;
+       uint64_t        data;
+       char            serialno[32];
+};
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void configure_mmu_el1(unsigned long total_base,
+                      unsigned long total_size,
+                      unsigned long ro_start,
+                      unsigned long ro_limit,
+                      unsigned long coh_start,
+                      unsigned long coh_limit);
+void configure_mmu_el3(unsigned long total_base,
+                      unsigned long total_size,
+                      unsigned long ro_start,
+                      unsigned long ro_limit,
+                      unsigned long coh_start,
+                      unsigned long coh_limit);
+extern int flush_loader_image(void);
+extern int flush_user_images(char *cmdbuf, unsigned long addr,
+                            unsigned long length);
+extern int flush_random_serialno(unsigned long addr, unsigned long length);
+extern void generate_serialno(struct random_serial_num *random);
+extern int assign_serialno(char *cmdbuf, struct random_serial_num *random);
+extern char *load_serialno(void);
+extern void hi6220_pll_init(void);
+extern void io_setup(void);
+extern int plat_get_image_source(const char *image_name,
+                                uintptr_t *dev_handle,
+                                uintptr_t *image_spec);
+extern void plat_gic_init(void);
+extern void usb_download(void);
+
+void plat_security_setup(void);
+
+#endif /* __HIKEY_PRIVATE_H__ */
diff --git a/plat/hikey/include/dw_mmc.h b/plat/hikey/include/dw_mmc.h
new file mode 100644 (file)
index 0000000..fc12018
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014, Hisilicon Ltd.
+ * Copyright (c) 2014, Linaro Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DW_MMC_H__
+#define __DW_MMC_H__
+
+#include <stdint.h>
+
+#define MMC0_CTRL                              (MMC0_BASE + 0x000)
+#define MMC0_CLKDIV                            (MMC0_BASE + 0x008)
+#define MMC0_CLKSRC                            (MMC0_BASE + 0x00c)
+#define MMC0_CLKENA                            (MMC0_BASE + 0x010)
+#define MMC0_TMOUT                             (MMC0_BASE + 0x014)
+#define MMC0_CTYPE                             (MMC0_BASE + 0x018)
+#define MMC0_BLKSIZ                            (MMC0_BASE + 0x01c)
+#define MMC0_BYTCNT                            (MMC0_BASE + 0x020)
+#define MMC0_INTMASK                           (MMC0_BASE + 0x024)
+#define MMC0_CMDARG                            (MMC0_BASE + 0x028)
+#define MMC0_CMD                               (MMC0_BASE + 0x02c)
+#define MMC0_RESP0                             (MMC0_BASE + 0x030)
+#define MMC0_RESP1                             (MMC0_BASE + 0x034)
+#define MMC0_RESP2                             (MMC0_BASE + 0x038)
+#define MMC0_RESP3                             (MMC0_BASE + 0x03c)
+#define MMC0_RINTSTS                           (MMC0_BASE + 0x044)
+#define MMC0_STATUS                            (MMC0_BASE + 0x048)
+#define MMC0_FIFOTH                            (MMC0_BASE + 0x04c)
+#define MMC0_DEBNCE                            (MMC0_BASE + 0x064)
+#define MMC0_UHSREG                            (MMC0_BASE + 0x074)
+#define MMC0_BMOD                              (MMC0_BASE + 0x080)
+#define MMC0_DBADDR                            (MMC0_BASE + 0x088)
+#define MMC0_IDSTS                             (MMC0_BASE + 0x08c)
+#define MMC0_IDINTEN                           (MMC0_BASE + 0x090)
+#define MMC0_DSCADDR                           (MMC0_BASE + 0x094)
+#define MMC0_BUFADDR                           (MMC0_BASE + 0x098)
+#define MMC0_CARDTHRCTL                                (MMC0_BASE + 0X100)
+
+#define CMD_UPDATE_CLK                         0x80202000
+#define CMD_START_BIT                          (1 << 31)
+
+#define MMC_8BIT_MODE                          (1 << 16)
+
+#define MMC_BLOCK_SIZE                         512
+
+#define BIT_CMD_RESPONSE_EXPECT                        (1 << 6)
+#define BIT_CMD_LONG_RESPONSE                  (1 << 7)
+#define BIT_CMD_CHECK_RESPONSE_CRC             (1 << 8)
+#define BIT_CMD_DATA_EXPECTED                  (1 << 9)
+#define BIT_CMD_READ                           (0 << 10)
+#define BIT_CMD_WRITE                          (1 << 10)
+#define BIT_CMD_BLOCK_TRANSFER                 (0 << 11)
+#define BIT_CMD_STREAM_TRANSFER                        (1 << 11)
+#define BIT_CMD_SEND_AUTO_STOP                 (1 << 12)
+#define BIT_CMD_WAIT_PRVDATA_COMPLETE          (1 << 13)
+#define BIT_CMD_STOP_ABORT_CMD                 (1 << 14)
+#define BIT_CMD_SEND_INIT                      (1 << 15)
+#define BIT_CMD_UPDATE_CLOCK_ONLY              (1 << 21)
+#define BIT_CMD_READ_CEATA_DEVICE              (1 << 22)
+#define BIT_CMD_CCS_EXPECTED                   (1 << 23)
+#define BIT_CMD_ENABLE_BOOT                    (1 << 24)
+#define BIT_CMD_EXPECT_BOOT_ACK                        (1 << 25)
+#define BIT_CMD_DISABLE_BOOT                   (1 << 26)
+#define BIT_CMD_MANDATORY_BOOT                 (0 << 27)
+#define BIT_CMD_ALTERNATE_BOOT                 (1 << 27)
+#define BIT_CMD_VOLT_SWITCH                    (1 << 28)
+#define BIT_CMD_USE_HOLD_REG                   (1 << 29)
+#define BIT_CMD_START                          (1 << 31)
+
+#define MMC_INT_EBE                    (1 << 15)       /* End-bit Err */
+#define MMC_INT_SBE                    (1 << 13)       /* Start-bit  Err */
+#define MMC_INT_HLE                    (1 << 12)       /* Hardware-lock Err */
+#define MMC_INT_FRUN                   (1 << 11)       /* FIFO UN/OV RUN */
+#define MMC_INT_DRT                    (1 << 9)        /* Data timeout */
+#define MMC_INT_RTO                    (1 << 8)        /* Response timeout */
+#define MMC_INT_DCRC                   (1 << 7)        /* Data CRC err */
+#define MMC_INT_RCRC                   (1 << 6)        /* Response CRC err */
+#define MMC_INT_RXDR                   (1 << 5)
+#define MMC_INT_TXDR                   (1 << 4)
+#define MMC_INT_DTO                    (1 << 3)        /* Data trans over */
+#define MMC_INT_CMD_DONE               (1 << 2)
+#define MMC_INT_RE                     (1 << 1)
+
+#define EMMC_FIX_RCA                           6
+
+/* bits in MMC0_CTRL */
+#define MMC_CTRL_RESET                         (1 << 0)
+#define MMC_FIFO_RESET                         (1 << 1)
+#define MMC_DMA_RESET                          (1 << 2)
+#define MMC_INT_EN                             (1 << 4)
+#define MMC_DMA_EN                             (1 << 25)
+
+#define MMC_STS_DATA_BUSY                      (1 << 9)
+
+#define MMC_STATUS_CURRENT_STATE_MASK  (0xf << 9)
+#define MMC_STATUS_CURRENT_STATE_SHIFT 9
+#define MMC_STATUS_READY_FOR_DATA      (1 << 8)
+#define MMC_STATUS_SWITCH_ERROR                (1 << 7)
+
+#define MMC_STATE_IDLE                 0
+#define MMC_STATE_READY                        1
+#define MMC_STATE_IDENT                        2
+#define MMC_STATE_STBY                 3
+#define MMC_STATE_TRAN                 4
+#define MMC_STATE_DATA                 5
+#define MMC_STATE_RCV                  6
+#define MMC_STATE_PRG                  7
+#define MMC_STATE_DIS                  8
+#define MMC_STATE_BTST                 9
+#define MMC_STATE_SLP                  10
+
+#define EXT_CSD_CACHE_CTRL             33
+#define EXT_CSD_PARTITION_CONFIG       179
+
+#define PART_CFG_BOOT_PARTITION1_ENABLE        (1 << 3)
+#define PART_CFG_PARTITION1_ACCESS     (1 << 0)
+
+#define MMC_IDMAC_ENABLE                       (1 << 7)
+#define MMC_IDMAC_FB                           (1 << 1)
+#define MMC_IDMAC_SWRESET                      (1 << 0)
+
+#define MMC_FIFO_TWMARK(x)                     (x & 0xfff)
+#define MMC_FIFO_RWMARK(x)                     ((x & 0x1ff) << 16)
+#define MMC_DMA_BURST_SIZE(x)                  ((x & 0x7) << 28)
+
+#define MMC_CARD_RD_THR(x)                     ((x & 0xfff) << 16)
+#define MMC_CARD_RD_THR_EN                     (1 << 0)
+
+extern int init_mmc(void);
+extern int mmc0_read(unsigned long, size_t, unsigned long, uint32_t);
+extern int mmc0_write(unsigned long, size_t, unsigned long, uint32_t);
+
+#endif /* __DW_MMC_H */
diff --git a/plat/hikey/include/hi6220.h b/plat/hikey/include/hi6220.h
new file mode 100644 (file)
index 0000000..7ec414d
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HI6220_H__
+#define __HI6220_H__
+
+#include <hi6220_regs_acpu.h>
+#include <hi6220_regs_ao.h>
+#include <hi6220_regs_peri.h>
+#include <hi6220_regs_pmctrl.h>
+
+#include <hisi_mcu.h>
+#include <hisi_sram_map.h>
+
+#define MEDIA_CTRL_BASE                                0xf4410000
+#define MEDIA_SUBSYS_CTRL2                     (MEDIA_CTRL_BASE + 0x508)
+#define MEDIA_SUBSYS_NOC_DFS                   (MEDIA_CTRL_BASE + 0x510)
+#define MEDIA_SUBSYS_CTRL5                     (MEDIA_CTRL_BASE + 0x51c)
+
+#define MMC0_BASE                              0xf723d000
+#define MMC1_BASE                              0xf723e000
+
+#define EDMAC_BASE                             0xf7370000
+#define EDMAC_SEC_CTRL                         (EDMAC_BASE + 0x694)
+#define EDMAC_AXI_CONF(x)                      (EDMAC_BASE + 0x820 + (x << 6))
+
+#define PMUSSI_BASE                            0xf8000000
+
+#define TIMER0_BASE                            0xf8008000
+#define TIMER00_LOAD                           (TIMER0_BASE + 0x000)
+#define TIMER00_VALUE                          (TIMER0_BASE + 0x004)
+#define TIMER00_CONTROL                                (TIMER0_BASE + 0x008)
+#define TIMER00_BGLOAD                         (TIMER0_BASE + 0x018)
+
+#define GPIO0_BASE                             0xf8011000
+#define GPIO1_BASE                             0xf8012000
+#define GPIO2_BASE                             0xf8013000
+#define GPIO3_BASE                             0xf8014000
+#define GPIO4_BASE                             0xf7020000
+#define GPIO5_BASE                             0xf7021000
+#define GPIO6_BASE                             0xf7022000
+#define GPIO7_BASE                             0xf7023000
+#define GPIO8_BASE                             0xf7024000
+#define GPIO9_BASE                             0xf7025000
+#define GPIO10_BASE                            0xf7026000
+#define GPIO11_BASE                            0xf7027000
+#define GPIO12_BASE                            0xf7028000
+#define GPIO13_BASE                            0xf7029000
+#define GPIO14_BASE                            0xf702a000
+#define GPIO15_BASE                            0xf702b000
+#define GPIO16_BASE                            0xf702c000
+#define GPIO17_BASE                            0xf702d000
+#define GPIO18_BASE                            0xf702e000
+#define GPIO19_BASE                            0xf702f000
+
+extern void init_acpu_dvfs(void);
+
+#endif /* __HI6220_H__ */
diff --git a/plat/hikey/include/hi6220_regs_acpu.h b/plat/hikey/include/hi6220_regs_acpu.h
new file mode 100644 (file)
index 0000000..19dc15d
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HI6220_REGS_ACPU_H__
+#define __HI6220_REGS_ACPU_H__
+
+#define ACPU_CTRL_BASE                         0xF6504000
+
+#define ACPU_SC_CPU_CTRL                       (ACPU_CTRL_BASE + 0x000)
+#define ACPU_SC_CPU_STAT                       (ACPU_CTRL_BASE + 0x008)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2               (1 << 0)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2_SHIFT         (0)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0                        (1 << 1)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0_SHIFT          (1)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1                        (1 << 2)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1_SHIFT          (2)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2                        (1 << 3)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2_SHIFT          (3)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3                        (1 << 4)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3_SHIFT          (4)
+#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2            (1 << 8)
+#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2_SHIFT      (8)
+#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI              (1 << 9)
+#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI_SHIFT                (9)
+#define ACPU_SC_CPU_STAT_L2FLSHUDONE0                  (1 << 16)
+#define ACPU_SC_CPU_STAT_L2FLSHUDONE0_SHIFT            (16)
+#define ACPU_SC_CPU_STAT_L2FLSHUDONE1                  (1 << 17)
+#define ACPU_SC_CPU_STAT_L2FLSHUDONE1_SHIFT            (17)
+#define ACPU_SC_CPU_STAT_CCI400_ACTIVE                 (1 << 18)
+#define ACPU_SC_CPU_STAT_CCI400_ACTIVE_SHIFT           (18)
+#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD             (1 << 20)
+#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT       (20)
+
+#define ACPU_SC_CLKEN                          (ACPU_CTRL_BASE + 0x00c)
+#define HPM_L2_1_CLKEN                         (1 << 9)
+#define G_CPU_1_CLKEN                          (1 << 8)
+#define HPM_L2_CLKEN                           (1 << 1)
+#define G_CPU_CLKEN                            (1 << 0)
+
+#define ACPU_SC_CLKDIS                         (ACPU_CTRL_BASE + 0x010)
+#define ACPU_SC_CLK_STAT                       (ACPU_CTRL_BASE + 0x014)
+#define ACPU_SC_RSTEN                          (ACPU_CTRL_BASE + 0x018)
+#define SRST_PRESET1_RSTEN                     (1 << 11)
+#define SRST_PRESET0_RSTEN                     (1 << 10)
+#define SRST_CLUSTER1_RSTEN                    (1 << 9)
+#define SRST_CLUSTER0_RSTEN                    (1 << 8)
+#define SRST_L2_HPM_1_RSTEN                    (1 << 5)
+#define SRST_AARM_L2_1_RSTEN                   (1 << 4)
+#define SRST_L2_HPM_0_RSTEN                    (1 << 3)
+#define SRST_AARM_L2_0_RSTEN                   (1 << 1)
+#define SRST_CLUSTER1                          (SRST_PRESET1_RSTEN | \
+                                                SRST_CLUSTER1_RSTEN | \
+                                                SRST_L2_HPM_1_RSTEN | \
+                                                SRST_AARM_L2_1_RSTEN)
+#define SRST_CLUSTER0                          (SRST_PRESET0_RSTEN | \
+                                                SRST_CLUSTER0_RSTEN | \
+                                                SRST_L2_HPM_0_RSTEN | \
+                                                SRST_AARM_L2_0_RSTEN)
+
+#define ACPU_SC_RSTDIS                         (ACPU_CTRL_BASE + 0x01c)
+#define ACPU_SC_RST_STAT                       (ACPU_CTRL_BASE + 0x020)
+#define ACPU_SC_PDBGUP_MBIST                   (ACPU_CTRL_BASE + 0x02c)
+#define PDBGUP_CLUSTER1_SHIFT                  8
+
+#define ACPU_SC_VD_CTRL                                (ACPU_CTRL_BASE + 0x054)
+#define ACPU_SC_VD_MASK_PATTERN_CTRL           (ACPU_CTRL_BASE + 0x058)
+#define ACPU_SC_VD_MASK_PATTERN_VAL            (0xCCB << 12)
+#define ACPU_SC_VD_MASK_PATTERN_MASK           ((0x1 << 13) - 1)
+
+#define ACPU_SC_VD_DLY_FIXED_CTRL              (ACPU_CTRL_BASE + 0x05c)
+#define ACPU_SC_VD_DLY_TABLE0_CTRL             (ACPU_CTRL_BASE + 0x060)
+#define ACPU_SC_VD_DLY_TABLE1_CTRL             (ACPU_CTRL_BASE + 0x064)
+#define ACPU_SC_VD_DLY_TABLE2_CTRL             (ACPU_CTRL_BASE + 0x068)
+#define ACPU_SC_VD_HPM_CTRL                    (ACPU_CTRL_BASE + 0x06c)
+#define ACPU_SC_A53_CLUSTER_MTCMOS_EN          (ACPU_CTRL_BASE + 0x088)
+#define PW_MTCMOS_EN_A53_1_EN                  (1 << 1)
+#define PW_MTCMOS_EN_A53_0_EN                  (1 << 0)
+
+#define ACPU_SC_A53_CLUSTER_MTCMOS_STA         (ACPU_CTRL_BASE + 0x090)
+#define ACPU_SC_A53_CLUSTER_ISO_EN             (ACPU_CTRL_BASE + 0x098)
+#define PW_ISO_A53_1_EN                                (1 << 1)
+#define PW_ISO_A53_0_EN                                (1 << 0)
+
+#define ACPU_SC_A53_CLUSTER_ISO_DIS            (ACPU_CTRL_BASE + 0x09c)
+#define ACPU_SC_A53_CLUSTER_ISO_STA            (ACPU_CTRL_BASE + 0x0a0)
+#define ACPU_SC_A53_1_MTCMOS_TIMER             (ACPU_CTRL_BASE + 0x0b4)
+#define ACPU_SC_A53_0_MTCMOS_TIMER             (ACPU_CTRL_BASE + 0x0bc)
+#define ACPU_SC_A53_x_MTCMOS_TIMER(x)          ((x) ? ACPU_SC_A53_1_MTCMOS_TIMER : ACPU_SC_A53_0_MTCMOS_TIMER)
+
+#define ACPU_SC_CPU0_CTRL                      (ACPU_CTRL_BASE + 0x100)
+#define CPU_CTRL_AARCH64_MODE                  (1 << 7)
+
+#define ACPU_SC_CPU0_STAT                      (ACPU_CTRL_BASE + 0x104)
+#define ACPU_SC_CPU0_CLKEN                     (ACPU_CTRL_BASE + 0x108)
+#define CPU_CLKEN_HPM                          (1 << 1)
+
+#define ACPU_SC_CPU0_CLK_STAT                  (ACPU_CTRL_BASE + 0x110)
+
+#define ACPU_SC_CPU0_RSTEN                     (ACPU_CTRL_BASE + 0x114)
+#define ACPU_SC_CPU0_RSTDIS                    (ACPU_CTRL_BASE + 0x118)
+#define ACPU_SC_CPU0_MTCMOS_EN                 (ACPU_CTRL_BASE + 0x120)
+#define CPU_MTCMOS_PW                          (1 << 0)
+
+#define ACPU_SC_CPU0_PW_ISOEN                  (ACPU_CTRL_BASE + 0x130)
+#define CPU_PW_ISO                             (1 << 0)
+
+#define ACPU_SC_CPU0_PW_ISODIS                 (ACPU_CTRL_BASE + 0x134)
+#define ACPU_SC_CPU0_PW_ISO_STAT               (ACPU_CTRL_BASE + 0x138)
+#define ACPU_SC_CPU0_MTCMOS_TIMER_STAT         (ACPU_CTRL_BASE + 0x154)
+#define CPU_MTCMOS_TIMER_STA                   (1 << 0)
+
+#define ACPU_SC_CPU0_RVBARADDR                 (ACPU_CTRL_BASE + 0x158)
+#define ACPU_SC_CPU1_CTRL                      (ACPU_CTRL_BASE + 0x200)
+#define ACPU_SC_CPU1_STAT                      (ACPU_CTRL_BASE + 0x204)
+#define ACPU_SC_CPU1_CLKEN                     (ACPU_CTRL_BASE + 0x208)
+#define ACPU_SC_CPU1_CLK_STAT                  (ACPU_CTRL_BASE + 0x210)
+#define ACPU_SC_CPU1_RSTEN                     (ACPU_CTRL_BASE + 0x214)
+#define ACPU_SC_CPU1_RSTDIS                    (ACPU_CTRL_BASE + 0x218)
+#define ACPU_SC_CPU1_MTCMOS_EN                 (ACPU_CTRL_BASE + 0x220)
+#define ACPU_SC_CPU1_PW_ISODIS                 (ACPU_CTRL_BASE + 0x234)
+#define ACPU_SC_CPU1_PW_ISO_STAT               (ACPU_CTRL_BASE + 0x238)
+#define ACPU_SC_CPU1_MTCMOS_TIMER_STAT         (ACPU_CTRL_BASE + 0x254)
+#define ACPU_SC_CPU1_RVBARADDR                 (ACPU_CTRL_BASE + 0x258)
+#define ACPU_SC_CPU2_CTRL                      (ACPU_CTRL_BASE + 0x300)
+#define ACPU_SC_CPU2_STAT                      (ACPU_CTRL_BASE + 0x304)
+#define ACPU_SC_CPU2_CLKEN                     (ACPU_CTRL_BASE + 0x308)
+#define ACPU_SC_CPU2_CLK_STAT                  (ACPU_CTRL_BASE + 0x310)
+#define ACPU_SC_CPU2_RSTEN                     (ACPU_CTRL_BASE + 0x314)
+#define ACPU_SC_CPU2_RSTDIS                    (ACPU_CTRL_BASE + 0x318)
+#define ACPU_SC_CPU2_MTCMOS_EN                 (ACPU_CTRL_BASE + 0x320)
+#define ACPU_SC_CPU2_PW_ISODIS                 (ACPU_CTRL_BASE + 0x334)
+#define ACPU_SC_CPU2_PW_ISO_STAT               (ACPU_CTRL_BASE + 0x338)
+#define ACPU_SC_CPU2_MTCMOS_TIMER_STAT         (ACPU_CTRL_BASE + 0x354)
+#define ACPU_SC_CPU2_RVBARADDR                 (ACPU_CTRL_BASE + 0x358)
+#define ACPU_SC_CPU3_CTRL                      (ACPU_CTRL_BASE + 0x400)
+#define ACPU_SC_CPU3_STAT                      (ACPU_CTRL_BASE + 0x404)
+#define ACPU_SC_CPU3_CLKEN                     (ACPU_CTRL_BASE + 0x408)
+#define ACPU_SC_CPU3_CLK_STAT                  (ACPU_CTRL_BASE + 0x410)
+#define ACPU_SC_CPU3_RSTEN                     (ACPU_CTRL_BASE + 0x414)
+#define ACPU_SC_CPU3_RSTDIS                    (ACPU_CTRL_BASE + 0x418)
+#define ACPU_SC_CPU3_MTCMOS_EN                 (ACPU_CTRL_BASE + 0x420)
+#define ACPU_SC_CPU3_PW_ISODIS                 (ACPU_CTRL_BASE + 0x434)
+#define ACPU_SC_CPU3_PW_ISO_STAT               (ACPU_CTRL_BASE + 0x438)
+#define ACPU_SC_CPU3_MTCMOS_TIMER_STAT         (ACPU_CTRL_BASE + 0x454)
+#define ACPU_SC_CPU3_RVBARADDR                 (ACPU_CTRL_BASE + 0x458)
+#define ACPU_SC_CPU4_CTRL                      (ACPU_CTRL_BASE + 0x500)
+#define ACPU_SC_CPU4_STAT                      (ACPU_CTRL_BASE + 0x504)
+#define ACPU_SC_CPU4_CLKEN                     (ACPU_CTRL_BASE + 0x508)
+#define ACPU_SC_CPU4_CLK_STAT                  (ACPU_CTRL_BASE + 0x510)
+#define ACPU_SC_CPU4_RSTEN                     (ACPU_CTRL_BASE + 0x514)
+#define ACPU_SC_CPU4_RSTDIS                    (ACPU_CTRL_BASE + 0x518)
+#define ACPU_SC_CPU4_MTCMOS_EN                 (ACPU_CTRL_BASE + 0x520)
+#define ACPU_SC_CPU4_PW_ISODIS                 (ACPU_CTRL_BASE + 0x534)
+#define ACPU_SC_CPU4_PW_ISO_STAT               (ACPU_CTRL_BASE + 0x538)
+#define ACPU_SC_CPU4_MTCMOS_TIMER_STAT         (ACPU_CTRL_BASE + 0x554)
+#define ACPU_SC_CPU4_RVBARADDR                 (ACPU_CTRL_BASE + 0x558)
+#define ACPU_SC_CPU5_CTRL                      (ACPU_CTRL_BASE + 0x600)
+#define ACPU_SC_CPU5_STAT                      (ACPU_CTRL_BASE + 0x604)
+#define ACPU_SC_CPU5_CLKEN                     (ACPU_CTRL_BASE + 0x608)
+#define ACPU_SC_CPU5_CLK_STAT                  (ACPU_CTRL_BASE + 0x610)
+#define ACPU_SC_CPU5_RSTEN                     (ACPU_CTRL_BASE + 0x614)
+#define ACPU_SC_CPU5_RSTDIS                    (ACPU_CTRL_BASE + 0x618)
+#define ACPU_SC_CPU5_MTCMOS_EN                 (ACPU_CTRL_BASE + 0x620)
+#define ACPU_SC_CPU5_PW_ISODIS                 (ACPU_CTRL_BASE + 0x634)
+#define ACPU_SC_CPU5_PW_ISO_STAT               (ACPU_CTRL_BASE + 0x638)
+#define ACPU_SC_CPU5_MTCMOS_TIMER_STAT         (ACPU_CTRL_BASE + 0x654)
+#define ACPU_SC_CPU5_RVBARADDR                 (ACPU_CTRL_BASE + 0x658)
+#define ACPU_SC_CPU6_CTRL                      (ACPU_CTRL_BASE + 0x700)
+#define ACPU_SC_CPU6_STAT                      (ACPU_CTRL_BASE + 0x704)
+#define ACPU_SC_CPU6_CLKEN                     (ACPU_CTRL_BASE + 0x708)
+#define ACPU_SC_CPU6_CLK_STAT                  (ACPU_CTRL_BASE + 0x710)
+#define ACPU_SC_CPU6_RSTEN                     (ACPU_CTRL_BASE + 0x714)
+#define ACPU_SC_CPU6_RSTDIS                    (ACPU_CTRL_BASE + 0x718)
+#define ACPU_SC_CPU6_MTCMOS_EN                 (ACPU_CTRL_BASE + 0x720)
+#define ACPU_SC_CPU6_PW_ISODIS                 (ACPU_CTRL_BASE + 0x734)
+#define ACPU_SC_CPU6_PW_ISO_STAT               (ACPU_CTRL_BASE + 0x738)
+#define ACPU_SC_CPU6_MTCMOS_TIMER_STAT         (ACPU_CTRL_BASE + 0x754)
+#define ACPU_SC_CPU6_RVBARADDR                 (ACPU_CTRL_BASE + 0x758)
+#define ACPU_SC_CPU7_CTRL                      (ACPU_CTRL_BASE + 0x800)
+#define ACPU_SC_CPU7_STAT                      (ACPU_CTRL_BASE + 0x804)
+#define ACPU_SC_CPU7_CLKEN                     (ACPU_CTRL_BASE + 0x808)
+#define ACPU_SC_CPU7_CLK_STAT                  (ACPU_CTRL_BASE + 0x810)
+#define ACPU_SC_CPU7_RSTEN                     (ACPU_CTRL_BASE + 0x814)
+#define ACPU_SC_CPU7_RSTDIS                    (ACPU_CTRL_BASE + 0x818)
+#define ACPU_SC_CPU7_MTCMOS_EN                 (ACPU_CTRL_BASE + 0x820)
+#define ACPU_SC_CPU7_PW_ISODIS                 (ACPU_CTRL_BASE + 0x834)
+#define ACPU_SC_CPU7_PW_ISO_STAT               (ACPU_CTRL_BASE + 0x838)
+#define ACPU_SC_CPU7_MTCMOS_TIMER_STAT         (ACPU_CTRL_BASE + 0x854)
+#define ACPU_SC_CPU7_RVBARADDR                 (ACPU_CTRL_BASE + 0x858)
+#define ACPU_SC_CPUx_CTRL(x)                   ((x < 8) ? (ACPU_SC_CPU0_CTRL + 0x100 * x) : ACPU_SC_CPU0_CTRL)
+#define ACPU_SC_CPUx_STAT(x)                   ((x < 8) ? (ACPU_SC_CPU0_STAT + 0x100 * x) : ACPU_SC_CPU0_STAT)
+#define ACPU_SC_CPUx_CLKEN(x)                  ((x < 8) ? (ACPU_SC_CPU0_CLKEN + 0x100 * x) : ACPU_SC_CPU0_CLKEN)
+#define ACPU_SC_CPUx_CLK_STAT(x)               ((x < 8) ? (ACPU_SC_CPU0_CLK_STAT + 0x100 *x) : ACPU_SC_CPU0_CLK_STAT)
+#define ACPU_SC_CPUx_RSTEN(x)                  ((x < 8) ? (ACPU_SC_CPU0_RSTEN + 0x100 * x) : ACPU_SC_CPU0_RSTEN)
+#define ACPU_SC_CPUx_RSTDIS(x)                 ((x < 8) ? (ACPU_SC_CPU0_RSTDIS + 0x100 * x) : ACPU_SC_CPU0_RSTDIS)
+#define ACPU_SC_CPUx_MTCMOS_EN(x)              ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_EN + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_EN)
+#define ACPU_SC_CPUx_PW_ISODIS(x)              ((x < 8) ? (ACPU_SC_CPU0_PW_ISODIS + 0x100 * x) : ACPU_SC_CPU0_PW_ISODIS)
+#define ACPU_SC_CPUx_PW_ISO_STAT(x)            ((x < 8) ? (ACPU_SC_CPU0_PW_ISO_STAT + 0x100 * x) : ACPU_SC_CPU0_PW_ISO_STAT)
+#define ACPU_SC_CPUx_MTCMOS_TIMER_STAT(x)      ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_TIMER_STAT + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_TIMER_STAT)
+#define ACPU_SC_CPUx_RVBARADDR(x)              ((x < 8) ? (ACPU_SC_CPU0_RVBARADDR + 0x100 * x) : ACPU_SC_CPU0_RVBARADDR)
+
+#define ACPU_SC_CPU_STAT_CLKDIV_VD_MASK                (3 << 20)
+
+#define ACPU_SC_VD_CTRL_TUNE_EN_DIF            (1 << 0)
+#define ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT      (0)
+#define ACPU_SC_VD_CTRL_TUNE                   (1 << 1)
+#define ACPU_SC_VD_CTRL_TUNE_SHIFT             (1)
+#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF       (1 << 7)
+#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT (7)
+#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI       (1 << 8)
+#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT (8)
+#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR                (1 << 9)
+#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR_SHIFT  (9)
+#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN         (1 << 10)
+#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT   (10)
+#define ACPU_SC_VD_CTRL_TUNE_EN_INT            (1 << 11)
+#define ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT      (11)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE0           (1 << 12)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_MASK      (0xf << 12)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT     (12)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE1           (1 << 16)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_MASK      (0xf << 16)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT     (16)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE2           (1 << 20)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_MASK      (0xf << 20)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT     (20)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE3           (1 << 24)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_MASK      (0xf << 24)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT     (24)
+#define ACPU_SC_VD_CTRL_FORCE_CLK_EN           (1 << 28)
+#define ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT     (28)
+#define ACPU_SC_VD_CTRL_DIV_EN_DIF             (1 << 29)
+#define ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT       (29)
+
+#define ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL                        \
+       ((0x1 << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) |  \
+        (0x3 << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) |  \
+        (0x5 << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) |  \
+        (0x6 << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) |  \
+         (0x7 << ACPU_SC_VD_CTRL_TUNE_SHIFT))
+
+#define ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK               \
+       ((0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) |  \
+        (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) |  \
+        (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) |  \
+        (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) |  \
+        (0x3F << ACPU_SC_VD_CTRL_TUNE_SHIFT))
+
+#define ACPU_SC_VD_HPM_CTRL_OSC_DIV            (1 << 0)
+#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT      (0)
+#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK       (0x000000FF)
+#define ACPU_SC_VD_HPM_CTRL_DLY_EXP            (1 << 8)
+#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT      (8)
+#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK       (0x001FFF00)
+
+#define HPM_OSC_DIV_VAL \
+       (0x56 << ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT)
+#define HPM_OSC_DIV_MASK \
+       (ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK)
+
+#define HPM_DLY_EXP_VAL \
+       (0xC7A << ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT)
+#define HPM_DLY_EXP_MASK \
+       (ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK)
+
+#define ACPU_SC_VD_EN_ASIC_VAL                                 \
+       ((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) |          \
+        (0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) |        \
+        (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) |      \
+        (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) |      \
+        (0X0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) |            \
+        (0X0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) |           \
+        (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
+
+#define ACPU_SC_VD_EN_SFT_VAL                                  \
+       ((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) |          \
+        (0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) |        \
+        (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) |      \
+        (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) |      \
+        (0x0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) |            \
+        (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) |           \
+        (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
+
+#define ACPU_SC_VD_EN_MASK                                     \
+       ((0x1 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) |          \
+        (0x1 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) |        \
+        (0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) |      \
+        (0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) |      \
+        (0x1 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) |            \
+        (0x1 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) |           \
+        (0x1 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
+
+#endif /* __HI6220_REGS_ACPU_H__ */
diff --git a/plat/hikey/include/hi6220_regs_ao.h b/plat/hikey/include/hi6220_regs_ao.h
new file mode 100644 (file)
index 0000000..448d18e
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HI6220_AO_H__
+#define __HI6220_AO_H__
+
+#define AO_CTRL_BASE                           0xF7800000
+
+#define AO_SC_SYS_CTRL0                                (AO_CTRL_BASE + 0x000)
+#define AO_SC_SYS_CTRL1                                (AO_CTRL_BASE + 0x004)
+#define AO_SC_SYS_CTRL2                                (AO_CTRL_BASE + 0x008)
+#define AO_SC_SYS_STAT0                                (AO_CTRL_BASE + 0x010)
+#define AO_SC_SYS_STAT1                                (AO_CTRL_BASE + 0x014)
+#define AO_SC_MCU_IMCTRL                       (AO_CTRL_BASE + 0x018)
+#define AO_SC_MCU_IMSTAT                       (AO_CTRL_BASE + 0x01C)
+#define AO_SC_SECONDRY_INT_EN0                 (AO_CTRL_BASE + 0x044)
+#define AO_SC_SECONDRY_INT_STATR0              (AO_CTRL_BASE + 0x048)
+#define AO_SC_SECONDRY_INT_STATM0              (AO_CTRL_BASE + 0x04C)
+#define AO_SC_MCU_WKUP_INT_EN6                 (AO_CTRL_BASE + 0x054)
+#define AO_SC_MCU_WKUP_INT_STATR6              (AO_CTRL_BASE + 0x058)
+#define AO_SC_MCU_WKUP_INT_STATM6              (AO_CTRL_BASE + 0x05C)
+#define AO_SC_MCU_WKUP_INT_EN5                 (AO_CTRL_BASE + 0x064)
+#define AO_SC_MCU_WKUP_INT_STATR5              (AO_CTRL_BASE + 0x068)
+#define AO_SC_MCU_WKUP_INT_STATM5              (AO_CTRL_BASE + 0x06C)
+#define AO_SC_MCU_WKUP_INT_EN4                 (AO_CTRL_BASE + 0x094)
+#define AO_SC_MCU_WKUP_INT_STATR4              (AO_CTRL_BASE + 0x098)
+#define AO_SC_MCU_WKUP_INT_STATM4              (AO_CTRL_BASE + 0x09C)
+#define AO_SC_MCU_WKUP_INT_EN0                 (AO_CTRL_BASE + 0x0A8)
+#define AO_SC_MCU_WKUP_INT_STATR0              (AO_CTRL_BASE + 0x0AC)
+#define AO_SC_MCU_WKUP_INT_STATM0              (AO_CTRL_BASE + 0x0B0)
+#define AO_SC_MCU_WKUP_INT_EN1                 (AO_CTRL_BASE + 0x0B4)
+#define AO_SC_MCU_WKUP_INT_STATR1              (AO_CTRL_BASE + 0x0B8)
+#define AO_SC_MCU_WKUP_INT_STATM1              (AO_CTRL_BASE + 0x0BC)
+#define AO_SC_INT_STATR                                (AO_CTRL_BASE + 0x0C4)
+#define AO_SC_INT_STATM                                (AO_CTRL_BASE + 0x0C8)
+#define AO_SC_INT_CLEAR                                (AO_CTRL_BASE + 0x0CC)
+#define AO_SC_INT_EN_SET                       (AO_CTRL_BASE + 0x0D0)
+#define AO_SC_INT_EN_DIS                       (AO_CTRL_BASE + 0x0D4)
+#define AO_SC_INT_EN_STAT                      (AO_CTRL_BASE + 0x0D8)
+#define AO_SC_INT_STATR1                       (AO_CTRL_BASE + 0x0E4)
+#define AO_SC_INT_STATM1                       (AO_CTRL_BASE + 0x0E8)
+#define AO_SC_INT_CLEAR1                       (AO_CTRL_BASE + 0x0EC)
+#define AO_SC_INT_EN_SET1                      (AO_CTRL_BASE + 0x0F0)
+#define AO_SC_INT_EN_DIS1                      (AO_CTRL_BASE + 0x0F4)
+#define AO_SC_INT_EN_STAT1                     (AO_CTRL_BASE + 0x0F8)
+#define AO_SC_TIMER_EN0                                (AO_CTRL_BASE + 0x1D0)
+#define AO_SC_TIMER_EN1                                (AO_CTRL_BASE + 0x1D4)
+#define AO_SC_TIMER_EN4                                (AO_CTRL_BASE + 0x1F0)
+#define AO_SC_TIMER_EN5                                (AO_CTRL_BASE + 0x1F4)
+#define AO_SC_MCU_SUBSYS_CTRL0                 (AO_CTRL_BASE + 0x400)
+#define AO_SC_MCU_SUBSYS_CTRL1                 (AO_CTRL_BASE + 0x404)
+#define AO_SC_MCU_SUBSYS_CTRL2                 (AO_CTRL_BASE + 0x408)
+#define AO_SC_MCU_SUBSYS_CTRL3                 (AO_CTRL_BASE + 0x40C)
+#define AO_SC_MCU_SUBSYS_CTRL4                 (AO_CTRL_BASE + 0x410)
+#define AO_SC_MCU_SUBSYS_CTRL5                 (AO_CTRL_BASE + 0x414)
+#define AO_SC_MCU_SUBSYS_CTRL6                 (AO_CTRL_BASE + 0x418)
+#define AO_SC_MCU_SUBSYS_CTRL7                 (AO_CTRL_BASE + 0x41C)
+#define AO_SC_MCU_SUBSYS_STAT0                 (AO_CTRL_BASE + 0x440)
+#define AO_SC_MCU_SUBSYS_STAT1                 (AO_CTRL_BASE + 0x444)
+#define AO_SC_MCU_SUBSYS_STAT2                 (AO_CTRL_BASE + 0x448)
+#define AO_SC_MCU_SUBSYS_STAT3                 (AO_CTRL_BASE + 0x44C)
+#define AO_SC_MCU_SUBSYS_STAT4                 (AO_CTRL_BASE + 0x450)
+#define AO_SC_MCU_SUBSYS_STAT5                 (AO_CTRL_BASE + 0x454)
+#define AO_SC_MCU_SUBSYS_STAT6                 (AO_CTRL_BASE + 0x458)
+#define AO_SC_MCU_SUBSYS_STAT7                 (AO_CTRL_BASE + 0x45C)
+#define AO_SC_PERIPH_CLKEN4                    (AO_CTRL_BASE + 0x630)
+#define AO_SC_PERIPH_CLKDIS4                   (AO_CTRL_BASE + 0x634)
+#define AO_SC_PERIPH_CLKSTAT4                  (AO_CTRL_BASE + 0x638)
+#define AO_SC_PERIPH_CLKEN5                    (AO_CTRL_BASE + 0x63C)
+#define AO_SC_PERIPH_CLKDIS5                   (AO_CTRL_BASE + 0x640)
+#define AO_SC_PERIPH_CLKSTAT5                  (AO_CTRL_BASE + 0x644)
+#define AO_SC_PERIPH_RSTEN4                    (AO_CTRL_BASE + 0x6F0)
+#define AO_SC_PERIPH_RSTDIS4                   (AO_CTRL_BASE + 0x6F4)
+#define AO_SC_PERIPH_RSTSTAT4                  (AO_CTRL_BASE + 0x6F8)
+#define AO_SC_PERIPH_RSTEN5                    (AO_CTRL_BASE + 0x6FC)
+#define AO_SC_PERIPH_RSTDIS5                   (AO_CTRL_BASE + 0x700)
+#define AO_SC_PERIPH_RSTSTAT5                  (AO_CTRL_BASE + 0x704)
+#define AO_SC_PW_CLKEN0                                (AO_CTRL_BASE + 0x800)
+#define AO_SC_PW_CLKDIS0                       (AO_CTRL_BASE + 0x804)
+#define AO_SC_PW_CLK_STAT0                     (AO_CTRL_BASE + 0x808)
+#define AO_SC_PW_RSTEN0                                (AO_CTRL_BASE + 0x810)
+#define AO_SC_PW_RSTDIS0                       (AO_CTRL_BASE + 0x814)
+#define AO_SC_PW_RST_STAT0                     (AO_CTRL_BASE + 0x818)
+#define AO_SC_PW_ISOEN0                                (AO_CTRL_BASE + 0x820)
+#define AO_SC_PW_ISODIS0                       (AO_CTRL_BASE + 0x824)
+#define AO_SC_PW_ISO_STAT0                     (AO_CTRL_BASE + 0x828)
+#define AO_SC_PW_MTCMOS_EN0                    (AO_CTRL_BASE + 0x830)
+#define AO_SC_PW_MTCMOS_DIS0                   (AO_CTRL_BASE + 0x834)
+#define AO_SC_PW_MTCMOS_STAT0                  (AO_CTRL_BASE + 0x838)
+#define AO_SC_PW_MTCMOS_ACK_STAT0              (AO_CTRL_BASE + 0x83C)
+#define AO_SC_PW_MTCMOS_TIMEOUT_STAT0          (AO_CTRL_BASE + 0x840)
+#define AO_SC_PW_STAT0                         (AO_CTRL_BASE + 0x850)
+#define AO_SC_PW_STAT1                         (AO_CTRL_BASE + 0x854)
+#define AO_SC_SYSTEST_STAT                     (AO_CTRL_BASE + 0x880)
+#define AO_SC_SYSTEST_SLICER_CNT0              (AO_CTRL_BASE + 0x890)
+#define AO_SC_SYSTEST_SLICER_CNT1              (AO_CTRL_BASE + 0x894)
+#define AO_SC_PW_CTRL1                         (AO_CTRL_BASE + 0x8C8)
+#define AO_SC_PW_CTRL                          (AO_CTRL_BASE + 0x8CC)
+#define AO_SC_MCPU_VOTEEN                      (AO_CTRL_BASE + 0x8D0)
+#define AO_SC_MCPU_VOTEDIS                     (AO_CTRL_BASE + 0x8D4)
+#define AO_SC_MCPU_VOTESTAT                    (AO_CTRL_BASE + 0x8D8)
+#define AO_SC_MCPU_VOTE_MSK0                   (AO_CTRL_BASE + 0x8E0)
+#define AO_SC_MCPU_VOTE_MSK1                   (AO_CTRL_BASE + 0x8E4)
+#define AO_SC_MCPU_VOTESTAT0_MSK               (AO_CTRL_BASE + 0x8E8)
+#define AO_SC_MCPU_VOTESTAT1_MSK               (AO_CTRL_BASE + 0x8EC)
+#define AO_SC_PERI_VOTEEN                      (AO_CTRL_BASE + 0x8F0)
+#define AO_SC_PERI_VOTEDIS                     (AO_CTRL_BASE + 0x8F4)
+#define AO_SC_PERI_VOTESTAT                    (AO_CTRL_BASE + 0x8F8)
+#define AO_SC_PERI_VOTE_MSK0                   (AO_CTRL_BASE + 0x900)
+#define AO_SC_PERI_VOTE_MSK1                   (AO_CTRL_BASE + 0x904)
+#define AO_SC_PERI_VOTESTAT0_MSK               (AO_CTRL_BASE + 0x908)
+#define AO_SC_PERI_VOTESTAT1_MSK               (AO_CTRL_BASE + 0x90C)
+#define AO_SC_ACPU_VOTEEN                      (AO_CTRL_BASE + 0x910)
+#define AO_SC_ACPU_VOTEDIS                     (AO_CTRL_BASE + 0x914)
+#define AO_SC_ACPU_VOTESTAT                    (AO_CTRL_BASE + 0x918)
+#define AO_SC_ACPU_VOTE_MSK0                   (AO_CTRL_BASE + 0x920)
+#define AO_SC_ACPU_VOTE_MSK1                   (AO_CTRL_BASE + 0x924)
+#define AO_SC_ACPU_VOTESTAT0_MSK               (AO_CTRL_BASE + 0x928)
+#define AO_SC_ACPU_VOTESTAT1_MSK               (AO_CTRL_BASE + 0x92C)
+#define AO_SC_MCU_VOTEEN                       (AO_CTRL_BASE + 0x930)
+#define AO_SC_MCU_VOTEDIS                      (AO_CTRL_BASE + 0x934)
+#define AO_SC_MCU_VOTESTAT                     (AO_CTRL_BASE + 0x938)
+#define AO_SC_MCU_VOTE_MSK0                    (AO_CTRL_BASE + 0x940)
+#define AO_SC_MCU_VOTE_MSK1                    (AO_CTRL_BASE + 0x944)
+#define AO_SC_MCU_VOTESTAT0_MSK                        (AO_CTRL_BASE + 0x948)
+#define AO_SC_MCU_VOTESTAT1_MSK                        (AO_CTRL_BASE + 0x94C)
+#define AO_SC_MCU_VOTE1EN                      (AO_CTRL_BASE + 0x960)
+#define AO_SC_MCU_VOTE1DIS                     (AO_CTRL_BASE + 0x964)
+#define AO_SC_MCU_VOTE1STAT                    (AO_CTRL_BASE + 0x968)
+#define AO_SC_MCU_VOTE1_MSK0                   (AO_CTRL_BASE + 0x970)
+#define AO_SC_MCU_VOTE1_MSK1                   (AO_CTRL_BASE + 0x974)
+#define AO_SC_MCU_VOTE1STAT0_MSK               (AO_CTRL_BASE + 0x978)
+#define AO_SC_MCU_VOTE1STAT1_MSK               (AO_CTRL_BASE + 0x97C)
+#define AO_SC_MCU_VOTE2EN                      (AO_CTRL_BASE + 0x980)
+#define AO_SC_MCU_VOTE2DIS                     (AO_CTRL_BASE + 0x984)
+#define AO_SC_MCU_VOTE2STAT                    (AO_CTRL_BASE + 0x988)
+#define AO_SC_MCU_VOTE2_MSK0                   (AO_CTRL_BASE + 0x990)
+#define AO_SC_MCU_VOTE2_MSK1                   (AO_CTRL_BASE + 0x994)
+#define AO_SC_MCU_VOTE2STAT0_MSK               (AO_CTRL_BASE + 0x998)
+#define AO_SC_MCU_VOTE2STAT1_MSK               (AO_CTRL_BASE + 0x99C)
+#define AO_SC_VOTE_CTRL                                (AO_CTRL_BASE + 0x9A0)
+#define AO_SC_VOTE_STAT                                (AO_CTRL_BASE + 0x9A4)
+#define AO_SC_ECONUM                           (AO_CTRL_BASE + 0xF00)
+#define AO_SCCHIPID                            (AO_CTRL_BASE + 0xF10)
+#define AO_SCSOCID                             (AO_CTRL_BASE + 0xF1C)
+#define AO_SC_SOC_FPGA_RTL_DEF                 (AO_CTRL_BASE + 0xFE0)
+#define AO_SC_SOC_FPGA_PR_DEF                  (AO_CTRL_BASE + 0xFE4)
+#define AO_SC_SOC_FPGA_RES_DEF0                        (AO_CTRL_BASE + 0xFE8)
+#define AO_SC_SOC_FPGA_RES_DEF1                        (AO_CTRL_BASE + 0xFEC)
+#define AO_SC_XTAL_CTRL0                       (AO_CTRL_BASE + 0x102)
+#define AO_SC_XTAL_CTRL1                       (AO_CTRL_BASE + 0x102)
+#define AO_SC_XTAL_CTRL3                       (AO_CTRL_BASE + 0x103)
+#define AO_SC_XTAL_CTRL5                       (AO_CTRL_BASE + 0x103)
+#define AO_SC_XTAL_STAT0                       (AO_CTRL_BASE + 0x106)
+#define AO_SC_XTAL_STAT1                       (AO_CTRL_BASE + 0x107)
+#define AO_SC_EFUSE_CHIPID0                    (AO_CTRL_BASE + 0x108)
+#define AO_SC_EFUSE_CHIPID1                    (AO_CTRL_BASE + 0x108)
+#define AO_SC_EFUSE_SYS_CTRL                   (AO_CTRL_BASE + 0x108)
+#define AO_SC_DEBUG_CTRL1                      (AO_CTRL_BASE + 0x128)
+#define AO_SC_DBG_STAT                         (AO_CTRL_BASE + 0x12B)
+#define AO_SC_ARM_DBG_KEY0                     (AO_CTRL_BASE + 0x12B)
+#define AO_SC_RESERVED31                       (AO_CTRL_BASE + 0x13A)
+#define AO_SC_RESERVED32                       (AO_CTRL_BASE + 0x13A)
+#define AO_SC_RESERVED33                       (AO_CTRL_BASE + 0x13A)
+#define AO_SC_RESERVED34                       (AO_CTRL_BASE + 0x13A)
+#define AO_SC_RESERVED35                       (AO_CTRL_BASE + 0x13B)
+#define AO_SC_RESERVED36                       (AO_CTRL_BASE + 0x13B)
+#define AO_SC_RESERVED37                       (AO_CTRL_BASE + 0x13B)
+#define AO_SC_RESERVED38                       (AO_CTRL_BASE + 0x13B)
+#define AO_SC_ALWAYSON_SYS_CTRL0               (AO_CTRL_BASE + 0x148)
+#define AO_SC_ALWAYSON_SYS_CTRL1               (AO_CTRL_BASE + 0x148)
+#define AO_SC_ALWAYSON_SYS_CTRL2               (AO_CTRL_BASE + 0x148)
+#define AO_SC_ALWAYSON_SYS_CTRL3               (AO_CTRL_BASE + 0x148)
+#define AO_SC_ALWAYSON_SYS_CTRL10              (AO_CTRL_BASE + 0x14A)
+#define AO_SC_ALWAYSON_SYS_CTRL11              (AO_CTRL_BASE + 0x14A)
+#define AO_SC_ALWAYSON_SYS_STAT0               (AO_CTRL_BASE + 0x14C)
+#define AO_SC_ALWAYSON_SYS_STAT1               (AO_CTRL_BASE + 0x14C)
+#define AO_SC_ALWAYSON_SYS_STAT2               (AO_CTRL_BASE + 0x14C)
+#define AO_SC_ALWAYSON_SYS_STAT3               (AO_CTRL_BASE + 0x14C)
+#define AO_SC_PWUP_TIME0                       (AO_CTRL_BASE + 0x188)
+#define AO_SC_PWUP_TIME1                       (AO_CTRL_BASE + 0x188)
+#define AO_SC_PWUP_TIME2                       (AO_CTRL_BASE + 0x188)
+#define AO_SC_PWUP_TIME3                       (AO_CTRL_BASE + 0x188)
+#define AO_SC_PWUP_TIME4                       (AO_CTRL_BASE + 0x189)
+#define AO_SC_PWUP_TIME5                       (AO_CTRL_BASE + 0x189)
+#define AO_SC_PWUP_TIME6                       (AO_CTRL_BASE + 0x189)
+#define AO_SC_PWUP_TIME7                       (AO_CTRL_BASE + 0x189)
+#define AO_SC_SECURITY_CTRL1                   (AO_CTRL_BASE + 0x1C0)
+#define AO_SC_SYSTEST_SLICER_CNT0              (AO_CTRL_BASE + 0x890)
+#define AO_SC_SYSTEST_SLICER_CNT1              (AO_CTRL_BASE + 0x894)
+
+#define AO_SC_SYS_CTRL0_MODE_NORMAL                            0x004
+#define AO_SC_SYS_CTRL0_MODE_MASK                              0x007
+
+#define AO_SC_SYS_CTRL1_AARM_WD_RST_CFG                                (1 << 0)
+#define AO_SC_SYS_CTRL1_REMAP_SRAM_AARM                                (1 << 1)
+#define AO_SC_SYS_CTRL1_EFUSEC_REMAP                           (1 << 2)
+#define AO_SC_SYS_CTRL1_EXT_PLL_SEL                            (1 << 3)
+#define AO_SC_SYS_CTRL1_MCU_WDG0_RSTMCU_CFG                    (1 << 4)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_DE_BOUNCE_CFG                        (1 << 6)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_CFG                       (1 << 7)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_DE_BOUNCE_CFG                        (1 << 8)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_CFG                       (1 << 9)
+#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG                    (1 << 10)
+#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG1                   (1 << 11)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_SFT                       (1 << 12)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_SFT                       (1 << 13)
+#define AO_SC_SYS_CTRL1_MCU_CLKEN_HARDCFG                      (1 << 15)
+#define AO_SC_SYS_CTRL1_AARM_WD_RST_CFG_MSK                    (1 << 16)
+#define AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK                    (1 << 17)
+#define AO_SC_SYS_CTRL1_EFUSEC_REMAP_MSK                       (1 << 18)
+#define AO_SC_SYS_CTRL1_EXT_PLL_SEL_MSK                                (1 << 19)
+#define AO_SC_SYS_CTRL1_MCU_WDG0_RSTMCU_CFG_MSK                        (1 << 20)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_DE_BOUNCE_CFG_MSK            (1 << 22)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_CFG_MSK                   (1 << 23)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_DE_BOUNCE_CFG_MSK            (1 << 24)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_CFG_MSK                   (1 << 25)
+#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG_MSK                        (1 << 26)
+#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG1_MSK               (1 << 27)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_SFT_MSK                   (1 << 28)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_SFT_MSK                   (1 << 29)
+#define AO_SC_SYS_CTRL1_MCU_CLKEN_HARDCFG_MSK                  (1 << 31)
+
+#define AO_SC_SYS_CTRL2_MCU_SFT_RST_STAT_CLEAR                 (1 << 26)
+#define AO_SC_SYS_CTRL2_MCU_WDG0_RST_STAT_CLEAR                        (1 << 27)
+#define AO_SC_SYS_CTRL2_TSENSOR_RST_STAT_CLEAR                 (1 << 28)
+#define AO_SC_SYS_CTRL2_ACPU_WDG_RST_STAT_CLEAR                        (1 << 29)
+#define AO_SC_SYS_CTRL2_MCU_WDG1_RST_STAT_CLEAR                        (1 << 30)
+#define AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR                    (1 << 31)
+
+#define AO_SC_SYS_STAT0_MCU_RST_STAT                           (1 << 25)
+#define AO_SC_SYS_STAT0_MCU_SOFTRST_STAT                       (1 << 26)
+#define AO_SC_SYS_STAT0_MCU_WDGRST_STAT                                (1 << 27)
+#define AO_SC_SYS_STAT0_TSENSOR_HARDRST_STAT                   (1 << 28)
+#define AO_SC_SYS_STAT0_ACPU_WD_GLB_RST_STAT                   (1 << 29)
+#define AO_SC_SYS_STAT0_CM3_WDG1_RST_STAT                      (1 << 30)
+#define AO_SC_SYS_STAT0_GLB_SRST_STAT                          (1 << 31)
+
+#define AO_SC_SYS_STAT1_MODE_STATUS                            (1 << 0)
+#define AO_SC_SYS_STAT1_BOOT_SEL_LOCK                          (1 << 16)
+#define AO_SC_SYS_STAT1_FUNC_MODE_LOCK                         (1 << 17)
+#define AO_SC_SYS_STAT1_BOOT_MODE_LOCK                         (1 << 19)
+#define AO_SC_SYS_STAT1_FUN_JTAG_MODE_OUT                      (1 << 20)
+#define AO_SC_SYS_STAT1_SECURITY_BOOT_FLG                      (1 << 27)
+#define AO_SC_SYS_STAT1_EFUSE_NANDBOOT_MSK                     (1 << 28)
+#define AO_SC_SYS_STAT1_EFUSE_NAND_BITWIDE                     (1 << 29)
+
+#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N                  (1 << 0)
+#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N                   (1 << 1)
+#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N                   (1 << 2)
+#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N                   (1 << 3)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_TIMER0_N               (1 << 4)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_TIMER1_N               (1 << 5)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_WDT0_N                 (1 << 6)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_WDT1_N                 (1 << 7)
+#define AO_SC_PERIPH_RSTDIS4_HRESET_IPC_S_N                    (1 << 8)
+#define AO_SC_PERIPH_RSTDIS4_HRESET_IPC_NS_N                   (1 << 9)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_EFUSEC_N                   (1 << 10)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT0_N                     (1 << 12)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT1_N                     (1 << 13)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT2_N                     (1 << 14)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER0_N                   (1 << 15)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER1_N                   (1 << 16)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER2_N                   (1 << 17)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER3_N                   (1 << 18)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER4_N                   (1 << 19)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER5_N                   (1 << 20)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER6_N                   (1 << 21)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER7_N                   (1 << 22)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER8_N                   (1 << 23)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_UART0_N                    (1 << 24)
+#define AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N                      (1 << 25)
+#define AO_SC_PERIPH_RSTDIS4_RESET_RTC1_N                      (1 << 26)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N                   (1 << 27)
+#define AO_SC_PERIPH_RSTDIS4_RESET_JTAG_AUTH_N                 (1 << 28)
+#define AO_SC_PERIPH_RSTDIS4_RESET_CS_DAPB_ON_N                        (1 << 29)
+#define AO_SC_PERIPH_RSTDIS4_MDM_SUBSYS_GLB                    (1 << 30)
+
+#define AO_SC_PERIPH_CLKEN4_HCLK_MCU                           (1 << 0)
+#define AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP                                (1 << 3)
+#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_TIMER0                    (1 << 4)
+#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_TIMER1                    (1 << 5)
+#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_WDT0                      (1 << 6)
+#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_WDT1                      (1 << 7)
+#define AO_SC_PERIPH_CLKEN4_HCLK_IPC_S                         (1 << 8)
+#define AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS                                (1 << 9)
+#define AO_SC_PERIPH_CLKEN4_PCLK_EFUSEC                                (1 << 10)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TZPC                          (1 << 11)
+#define AO_SC_PERIPH_CLKEN4_PCLK_WDT0                          (1 << 12)
+#define AO_SC_PERIPH_CLKEN4_PCLK_WDT1                          (1 << 13)
+#define AO_SC_PERIPH_CLKEN4_PCLK_WDT2                          (1 << 14)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER0                                (1 << 15)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER1                                (1 << 16)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER2                                (1 << 17)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER3                                (1 << 18)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER4                                (1 << 19)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER5                                (1 << 20)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER6                                (1 << 21)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER7                                (1 << 22)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER8                                (1 << 23)
+#define AO_SC_PERIPH_CLKEN4_CLK_UART0                          (1 << 24)
+#define AO_SC_PERIPH_CLKEN4_CLK_RTC0                           (1 << 25)
+#define AO_SC_PERIPH_CLKEN4_CLK_RTC1                           (1 << 26)
+#define AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI                                (1 << 27)
+#define AO_SC_PERIPH_CLKEN4_CLK_JTAG_AUTH                      (1 << 28)
+#define AO_SC_PERIPH_CLKEN4_CLK_CS_DAPB_ON                     (1 << 29)
+#define AO_SC_PERIPH_CLKEN4_CLK_PDM                            (1 << 30)
+#define AO_SC_PERIPH_CLKEN4_CLK_SSI_PAD                                (1 << 31)
+
+#define AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU                   (1 << 0)
+#define AO_SC_PERIPH_CLKEN5_PCLK_EFUSEC_CCPU                   (1 << 1)
+#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_CCPU                      (1 << 2)
+#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_NS_CCPU                   (1 << 3)
+#define AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU                    (1 << 16)
+#define AO_SC_PERIPH_CLKEN5_PCLK_EFUSEC_MCU                    (1 << 17)
+#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_MCU                       (1 << 18)
+#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_NS_MCU                    (1 << 19)
+
+#define AO_SC_MCU_SUBSYS_CTRL3_RCLK_3                          0x003
+#define AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK                       0x007
+#define AO_SC_MCU_SUBSYS_CTRL3_CSSYS_CTRL_PROT                 (1 << 3)
+#define AO_SC_MCU_SUBSYS_CTRL3_TCXO_AFC_OEN_CRG                        (1 << 4)
+#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_USIM1              (1 << 8)
+#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_USIM0              (1 << 9)
+#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_SD                 (1 << 10)
+#define AO_SC_MCU_SUBSYS_CTRL3_MCU_SUBSYS_CTRL3_RESERVED       (1 << 11)
+
+#define PCLK_TIMER1                                            (1 << 16)
+#define PCLK_TIMER0                                            (1 << 15)
+
+#endif /* __HI6220_AO_H__ */
diff --git a/plat/hikey/include/hi6220_regs_peri.h b/plat/hikey/include/hi6220_regs_peri.h
new file mode 100644 (file)
index 0000000..9b79d5a
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HI6220_PERI_H__
+#define __HI6220_PERI_H__
+
+#define PERI_BASE                              0xF7030000
+
+#define PERI_SC_PERIPH_CTRL1                   (PERI_BASE + 0x000)
+#define PERI_SC_PERIPH_CTRL2                   (PERI_BASE + 0x004)
+#define PERI_SC_PERIPH_CTRL3                   (PERI_BASE + 0x008)
+#define PERI_SC_PERIPH_CTRL4                   (PERI_BASE + 0x00c)
+#define PERI_SC_PERIPH_CTRL5                   (PERI_BASE + 0x010)
+#define PERI_SC_PERIPH_CTRL6                   (PERI_BASE + 0x014)
+#define PERI_SC_PERIPH_CTRL8                   (PERI_BASE + 0x018)
+#define PERI_SC_PERIPH_CTRL9                   (PERI_BASE + 0x01c)
+#define PERI_SC_PERIPH_CTRL10                  (PERI_BASE + 0x020)
+#define PERI_SC_PERIPH_CTRL12                  (PERI_BASE + 0x024)
+#define PERI_SC_PERIPH_CTRL13                  (PERI_BASE + 0x028)
+#define PERI_SC_PERIPH_CTRL14                  (PERI_BASE + 0x02c)
+
+#define PERI_SC_DDR_CTRL0                      (PERI_BASE + 0x050)
+#define PERI_SC_PERIPH_STAT1                   (PERI_BASE + 0x094)
+
+#define PERI_SC_PERIPH_CLKEN0                  (PERI_BASE + 0x200)
+#define PERI_SC_PERIPH_CLKDIS0                 (PERI_BASE + 0x204)
+#define PERI_SC_PERIPH_CLKSTAT0                        (PERI_BASE + 0x208)
+#define PERI_SC_PERIPH_CLKEN1                  (PERI_BASE + 0x210)
+#define PERI_SC_PERIPH_CLKDIS1                 (PERI_BASE + 0x214)
+#define PERI_SC_PERIPH_CLKSTAT1                        (PERI_BASE + 0x218)
+#define PERI_SC_PERIPH_CLKEN2                  (PERI_BASE + 0x220)
+#define PERI_SC_PERIPH_CLKDIS2                 (PERI_BASE + 0x224)
+#define PERI_SC_PERIPH_CLKSTAT2                        (PERI_BASE + 0x228)
+#define PERI_SC_PERIPH_CLKEN3                  (PERI_BASE + 0x230)
+#define PERI_SC_PERIPH_CLKDIS3                 (PERI_BASE + 0x234)
+#define PERI_SC_PERIPH_CLKSTAT3                        (PERI_BASE + 0x238)
+#define PERI_SC_PERIPH_CLKEN8                  (PERI_BASE + 0x240)
+#define PERI_SC_PERIPH_CLKDIS8                 (PERI_BASE + 0x244)
+#define PERI_SC_PERIPH_CLKSTAT8                        (PERI_BASE + 0x248)
+#define PERI_SC_PERIPH_CLKEN9                  (PERI_BASE + 0x250)
+#define PERI_SC_PERIPH_CLKDIS9                 (PERI_BASE + 0x254)
+#define PERI_SC_PERIPH_CLKSTAT9                        (PERI_BASE + 0x258)
+#define PERI_SC_PERIPH_CLKEN10                 (PERI_BASE + 0x260)
+#define PERI_SC_PERIPH_CLKDIS10                        (PERI_BASE + 0x264)
+#define PERI_SC_PERIPH_CLKSTAT10               (PERI_BASE + 0x268)
+#define PERI_SC_PERIPH_CLKEN12                 (PERI_BASE + 0x270)
+#define PERI_SC_PERIPH_CLKDIS12                        (PERI_BASE + 0x274)
+#define PERI_SC_PERIPH_CLKSTAT12               (PERI_BASE + 0x278)
+
+#define PERI_SC_PERIPH_RSTEN0                  (PERI_BASE + 0x300)
+#define PERI_SC_PERIPH_RSTDIS0                 (PERI_BASE + 0x304)
+#define PERI_SC_PERIPH_RSTSTAT0                        (PERI_BASE + 0x308)
+#define PERI_SC_PERIPH_RSTEN1                  (PERI_BASE + 0x310)
+#define PERI_SC_PERIPH_RSTDIS1                 (PERI_BASE + 0x314)
+#define PERI_SC_PERIPH_RSTSTAT1                        (PERI_BASE + 0x318)
+#define PERI_SC_PERIPH_RSTEN2                  (PERI_BASE + 0x320)
+#define PERI_SC_PERIPH_RSTDIS2                 (PERI_BASE + 0x324)
+#define PERI_SC_PERIPH_RSTSTAT2                        (PERI_BASE + 0x328)
+#define PERI_SC_PERIPH_RSTEN3                  (PERI_BASE + 0x330)
+#define PERI_SC_PERIPH_RSTDIS3                 (PERI_BASE + 0x334)
+#define PERI_SC_PERIPH_RSTSTAT3                        (PERI_BASE + 0x338)
+#define PERI_SC_PERIPH_RSTEN8                  (PERI_BASE + 0x340)
+#define PERI_SC_PERIPH_RSTDIS8                 (PERI_BASE + 0x344)
+#define PERI_SC_PERIPH_RSTSTAT8                        (PERI_BASE + 0x338)
+
+#define PERI_SC_CLK_SEL0                       (PERI_BASE + 0x400)
+#define PERI_SC_CLKCFG8BIT1                    (PERI_BASE + 0x494)
+#define PERI_SC_CLKCFG8BIT2                    (PERI_BASE + 0x498)
+#define PERI_SC_RESERVED8_ADDR                 (PERI_BASE + 0xd04)
+
+/* PERI_SC_PERIPH_CTRL1 */
+#define PERI_CTRL1_ETR_AXI_CSYSREQ_N           (1 << 0)
+#define PERI_CTRL1_ETR_AXI_CSYSREQ_N           (1 << 0)
+#define PERI_CTRL1_HIFI_INT_MASK               (1 << 1)
+#define PERI_CTRL1_HIFI_ALL_INT_MASK           (1 << 2)
+#define PERI_CTRL1_ETR_AXI_CSYSREQ_N_MSK       (1 << 16)
+#define PERI_CTRL1_HIFI_INT_MASK_MSK           (1 << 17)
+#define PERI_CTRL1_HIFI_ALL_INT_MASK_MSK       (1 << 18)
+
+/* PERI_SC_PERIPH_CTRL2        */
+#define PERI_CTRL2_MMC_CLK_PHASE_BYPASS_EN_MMC0        (1 << 0)
+#define PERI_CTRL2_MMC_CLK_PHASE_BYPASS_EN_MMC1        (1 << 2)
+#define PERI_CTRL2_NAND_SYS_MEM_SEL            (1 << 6)
+#define PERI_CTRL2_G3D_DDRT_AXI_SEL            (1 << 7)
+#define PERI_CTRL2_GU_MDM_BBP_TESTPIN_SEL      (1 << 8)
+#define PERI_CTRL2_CODEC_SSI_MASTER_CHECK      (1 << 9)
+#define PERI_CTRL2_FUNC_TEST_SOFT              (1 << 12)
+#define PERI_CTRL2_CSSYS_TS_ENABLE             (1 << 15)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_EMA          (1 << 16)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_EMAW         (1 << 20)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_EMAS         (1 << 22)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_RET1N                (1 << 26)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_RET2N                (1 << 27)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_PGEN         (1 << 28)
+
+/* PERI_SC_PERIPH_CTRL3 */
+#define PERI_CTRL3_HIFI_DDR_HARQMEM_ADDR       (1 << 0)
+#define PERI_CTRL3_HIFI_HARQMEMRMP_EN          (1 << 12)
+#define PERI_CTRL3_HARQMEM_SYS_MED_SEL         (1 << 13)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP1          (1 << 14)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP2          (1 << 16)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP3          (1 << 18)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP4          (1 << 20)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP5          (1 << 22)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP6          (1 << 24)
+
+/* PERI_SC_PERIPH_CTRL4 */
+#define PERI_CTRL4_PICO_FSELV                  (1 << 0)
+#define PERI_CTRL4_FPGA_EXT_PHY_SEL            (1 << 3)
+#define PERI_CTRL4_PICO_REFCLKSEL              (1 << 4)
+#define PERI_CTRL4_PICO_SIDDQ                  (1 << 6)
+#define PERI_CTRL4_PICO_SUSPENDM_SLEEPM                (1 << 7)
+#define PERI_CTRL4_PICO_OGDISABLE              (1 << 8)
+#define PERI_CTRL4_PICO_COMMONONN              (1 << 9)
+#define PERI_CTRL4_PICO_VBUSVLDEXT             (1 << 10)
+#define PERI_CTRL4_PICO_VBUSVLDEXTSEL          (1 << 11)
+#define PERI_CTRL4_PICO_VATESTENB              (1 << 12)
+#define PERI_CTRL4_PICO_SUSPENDM               (1 << 14)
+#define PERI_CTRL4_PICO_SLEEPM                 (1 << 15)
+#define PERI_CTRL4_BC11_C                      (1 << 16)
+#define PERI_CTRL4_BC11_B                      (1 << 17)
+#define PERI_CTRL4_BC11_A                      (1 << 18)
+#define PERI_CTRL4_BC11_GND                    (1 << 19)
+#define PERI_CTRL4_BC11_FLOAT                  (1 << 20)
+#define PERI_CTRL4_OTG_PHY_SEL                 (1 << 21)
+#define PERI_CTRL4_USB_OTG_SS_SCALEDOWN_MODE   (1 << 22)
+#define PERI_CTRL4_OTG_DM_PULLDOWN             (1 << 24)
+#define PERI_CTRL4_OTG_DP_PULLDOWN             (1 << 25)
+#define PERI_CTRL4_OTG_IDPULLUP                        (1 << 26)
+#define PERI_CTRL4_OTG_DRVBUS                  (1 << 27)
+#define PERI_CTRL4_OTG_SESSEND                 (1 << 28)
+#define PERI_CTRL4_OTG_BVALID                  (1 << 29)
+#define PERI_CTRL4_OTG_AVALID                  (1 << 30)
+#define PERI_CTRL4_OTG_VBUSVALID               (1 << 31)
+
+/* PERI_SC_PERIPH_CTRL5 */
+#define PERI_CTRL5_USBOTG_RES_SEL              (1 << 3)
+#define PERI_CTRL5_PICOPHY_ACAENB              (1 << 4)
+#define PERI_CTRL5_PICOPHY_BC_MODE             (1 << 5)
+#define PERI_CTRL5_PICOPHY_CHRGSEL             (1 << 6)
+#define PERI_CTRL5_PICOPHY_VDATSRCEND          (1 << 7)
+#define PERI_CTRL5_PICOPHY_VDATDETENB          (1 << 8)
+#define PERI_CTRL5_PICOPHY_DCDENB              (1 << 9)
+#define PERI_CTRL5_PICOPHY_IDDIG               (1 << 10)
+#define PERI_CTRL5_DBG_MUX                     (1 << 11)
+
+/* PERI_SC_PERIPH_CTRL6 */
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMA      (1 << 0)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMAW     (1 << 4)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMAS     (1 << 6)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_RET1N    (1 << 10)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_RET2N    (1 << 11)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_PGEN     (1 << 12)
+
+/* PERI_SC_PERIPH_CTRL8 */
+#define PERI_CTRL8_PICOPHY_TXRISETUNE0         (1 << 0)
+#define PERI_CTRL8_PICOPHY_TXPREEMPAMPTUNE0    (1 << 2)
+#define PERI_CTRL8_PICOPHY_TXRESTUNE0          (1 << 4)
+#define PERI_CTRL8_PICOPHY_TXHSSVTUNE0         (1 << 6)
+#define PERI_CTRL8_PICOPHY_COMPDISTUNE0                (1 << 8)
+#define PERI_CTRL8_PICOPHY_TXPREEMPPULSETUNE0  (1 << 11)
+#define PERI_CTRL8_PICOPHY_OTGTUNE0            (1 << 12)
+#define PERI_CTRL8_PICOPHY_SQRXTUNE0           (1 << 16)
+#define PERI_CTRL8_PICOPHY_TXVREFTUNE0         (1 << 20)
+#define PERI_CTRL8_PICOPHY_TXFSLSTUNE0         (1 << 28)
+
+/* PERI_SC_PERIPH_CTRL9        */
+#define PERI_CTRL9_PICOPLY_TESTCLKEN           (1 << 0)
+#define PERI_CTRL9_PICOPLY_TESTDATAOUTSEL      (1 << 1)
+#define PERI_CTRL9_PICOPLY_TESTADDR            (1 << 4)
+#define PERI_CTRL9_PICOPLY_TESTDATAIN          (1 << 8)
+
+/*
+ * PERI_SC_PERIPH_CLKEN0
+ * PERI_SC_PERIPH_CLKDIS0
+ * PERI_SC_PERIPH_CLKSTAT0
+ */
+#define PERI_CLK0_MMC0                         (1 << 0)
+#define PERI_CLK0_MMC1                         (1 << 1)
+#define PERI_CLK0_MMC2                         (1 << 2)
+#define PERI_CLK0_NANDC                                (1 << 3)
+#define PERI_CLK0_USBOTG                       (1 << 4)
+#define PERI_CLK0_PICOPHY                      (1 << 5)
+#define PERI_CLK0_PLL                          (1 << 6)
+
+/*
+ * PERI_SC_PERIPH_CLKEN1
+ * PERI_SC_PERIPH_CLKDIS1
+ * PERI_SC_PERIPH_CLKSTAT1
+ */
+#define PERI_CLK1_HIFI                         (1 << 0)
+#define PERI_CLK1_DIGACODEC                    (1 << 5)
+
+/*
+ * PERI_SC_PERIPH_CLKEN2
+ * PERI_SC_PERIPH_CLKDIS2
+ * PERI_SC_PERIPH_CLKSTAT2
+ */
+#define PERI_CLK2_IPF                          (1 << 0)
+#define PERI_CLK2_SOCP                         (1 << 1)
+#define PERI_CLK2_DMAC                         (1 << 2)
+#define PERI_CLK2_SECENG                       (1 << 3)
+#define PERI_CLK2_HPM0                         (1 << 5)
+#define PERI_CLK2_HPM1                         (1 << 6)
+#define PERI_CLK2_HPM2                         (1 << 7)
+#define PERI_CLK2_HPM3                         (1 << 8)
+
+/*
+ * PERI_SC_PERIPH_CLKEN3
+ * PERI_SC_PERIPH_CLKDIS3
+ * PERI_SC_PERIPH_CLKSTAT3
+ */
+#define PERI_CLK3_CSSYS                                (1 << 0)
+#define PERI_CLK3_I2C0                         (1 << 1)
+#define PERI_CLK3_I2C1                         (1 << 2)
+#define PERI_CLK3_I2C2                         (1 << 3)
+#define PERI_CLK3_I2C3                         (1 << 4)
+#define PERI_CLK3_UART1                                (1 << 5)
+#define PERI_CLK3_UART2                                (1 << 6)
+#define PERI_CLK3_UART3                                (1 << 7)
+#define PERI_CLK3_UART4                                (1 << 8)
+#define PERI_CLK3_SSP                          (1 << 9)
+#define PERI_CLK3_PWM                          (1 << 10)
+#define PERI_CLK3_BLPWM                                (1 << 11)
+#define PERI_CLK3_TSENSOR                      (1 << 12)
+#define PERI_CLK3_GPS                          (1 << 15)
+#define PERI_CLK3_TCXO_PAD0                    (1 << 16)
+#define PERI_CLK3_TCXO_PAD1                    (1 << 17)
+#define PERI_CLK3_DAPB                         (1 << 18)
+#define PERI_CLK3_HKADC                                (1 << 19)
+#define PERI_CLK3_CODEC_SSI                    (1 << 20)
+#define PERI_CLK3_TZPC_DEP                     (1 << 21)
+
+/*
+ * PERI_SC_PERIPH_CLKEN8
+ * PERI_SC_PERIPH_CLKDIS8
+ * PERI_SC_PERIPH_CLKSTAT8
+ */
+#define PERI_CLK8_RS0                          (1 << 0)
+#define PERI_CLK8_RS2                          (1 << 1)
+#define PERI_CLK8_RS3                          (1 << 2)
+#define PERI_CLK8_MS0                          (1 << 3)
+#define PERI_CLK8_MS2                          (1 << 5)
+#define PERI_CLK8_XG2RAM0                      (1 << 6)
+#define PERI_CLK8_X2SRAM                       (1 << 7)
+#define PERI_CLK8_SRAM                         (1 << 8)
+#define PERI_CLK8_ROM                          (1 << 9)
+#define PERI_CLK8_HARQ                         (1 << 10)
+#define PERI_CLK8_MMU                          (1 << 11)
+#define PERI_CLK8_DDRC                         (1 << 12)
+#define PERI_CLK8_DDRPHY                       (1 << 13)
+#define PERI_CLK8_DDRPHY_REF                   (1 << 14)
+#define PERI_CLK8_X2X_SYSNOC                   (1 << 15)
+#define PERI_CLK8_X2X_CCPU                     (1 << 16)
+#define PERI_CLK8_DDRT                         (1 << 17)
+#define PERI_CLK8_DDRPACK_RS                   (1 << 18)
+
+/*
+ * PERI_SC_PERIPH_CLKEN9
+ * PERI_SC_PERIPH_CLKDIS9
+ * PERI_SC_PERIPH_CLKSTAT9
+ */
+#define PERI_CLK9_CARM_DAP                     (1 << 0)
+#define PERI_CLK9_CARM_ATB                     (1 << 1)
+#define PERI_CLK9_CARM_LBUS                    (1 << 2)
+#define PERI_CLK9_CARM_KERNEL                  (1 << 3)
+
+/*
+ * PERI_SC_PERIPH_CLKEN10
+ * PERI_SC_PERIPH_CLKDIS10
+ * PERI_SC_PERIPH_CLKSTAT10
+ */
+#define PERI_CLK10_IPF_CCPU                    (1 << 0)
+#define PERI_CLK10_SOCP_CCPU                   (1 << 1)
+#define PERI_CLK10_SECENG_CCPU                 (1 << 2)
+#define PERI_CLK10_HARQ_CCPU                   (1 << 3)
+#define PERI_CLK10_IPF_MCU                     (1 << 16)
+#define PERI_CLK10_SOCP_MCU                    (1 << 17)
+#define PERI_CLK10_SECENG_MCU                  (1 << 18)
+#define PERI_CLK10_HARQ_MCU                    (1 << 19)
+
+/*
+ * PERI_SC_PERIPH_CLKEN12
+ * PERI_SC_PERIPH_CLKDIS12
+ * PERI_SC_PERIPH_CLKSTAT12
+ */
+#define PERI_CLK12_HIFI_SRC                    (1 << 0)
+#define PERI_CLK12_MMC0_SRC                    (1 << 1)
+#define PERI_CLK12_MMC1_SRC                    (1 << 2)
+#define PERI_CLK12_MMC2_SRC                    (1 << 3)
+#define PERI_CLK12_SYSPLL_DIV                  (1 << 4)
+#define PERI_CLK12_TPIU_SRC                    (1 << 5)
+#define PERI_CLK12_MMC0_HF                     (1 << 6)
+#define PERI_CLK12_MMC1_HF                     (1 << 7)
+#define PERI_CLK12_PLL_TEST_SRC                        (1 << 8)
+#define PERI_CLK12_CODEC_SOC                   (1 << 9)
+#define PERI_CLK12_MEDIA                       (1 << 10)
+
+/*
+ * PERI_SC_PERIPH_RSTEN0
+ * PERI_SC_PERIPH_RSTDIS0
+ * PERI_SC_PERIPH_RSTSTAT0
+ */
+#define PERI_RST0_MMC0                         (1 << 0)
+#define PERI_RST0_MMC1                         (1 << 1)
+#define PERI_RST0_MMC2                         (1 << 2)
+#define PERI_RST0_NANDC                                (1 << 3)
+#define PERI_RST0_USBOTG_BUS                   (1 << 4)
+#define PERI_RST0_POR_PICOPHY                  (1 << 5)
+#define PERI_RST0_USBOTG                       (1 << 6)
+#define PERI_RST0_USBOTG_32K                   (1 << 7)
+
+/*
+ * PERI_SC_PERIPH_RSTEN1
+ * PERI_SC_PERIPH_RSTDIS1
+ * PERI_SC_PERIPH_RSTSTAT1
+ */
+#define PERI_RST1_HIFI                         (1 << 0)
+#define PERI_RST1_DIGACODEC                    (1 << 5)
+
+/*
+ * PERI_SC_PERIPH_RSTEN2
+ * PERI_SC_PERIPH_RSTDIS2
+ * PERI_SC_PERIPH_RSTSTAT2
+ */
+#define PERI_RST2_IPF                          (1 << 0)
+#define PERI_RST2_SOCP                         (1 << 1)
+#define PERI_RST2_DMAC                         (1 << 2)
+#define PERI_RST2_SECENG                       (1 << 3)
+#define PERI_RST2_ABB                          (1 << 4)
+#define PERI_RST2_HPM0                         (1 << 5)
+#define PERI_RST2_HPM1                         (1 << 6)
+#define PERI_RST2_HPM2                         (1 << 7)
+#define PERI_RST2_HPM3                         (1 << 8)
+
+/*
+ * PERI_SC_PERIPH_RSTEN3
+ * PERI_SC_PERIPH_RSTDIS3
+ * PERI_SC_PERIPH_RSTSTAT3
+ */
+#define PERI_RST3_CSSYS                                (1 << 0)
+#define PERI_RST3_I2C0                         (1 << 1)
+#define PERI_RST3_I2C1                         (1 << 2)
+#define PERI_RST3_I2C2                         (1 << 3)
+#define PERI_RST3_I2C3                         (1 << 4)
+#define PERI_RST3_UART1                                (1 << 5)
+#define PERI_RST3_UART2                                (1 << 6)
+#define PERI_RST3_UART3                                (1 << 7)
+#define PERI_RST3_UART4                                (1 << 8)
+#define PERI_RST3_SSP                          (1 << 9)
+#define PERI_RST3_PWM                          (1 << 10)
+#define PERI_RST3_BLPWM                                (1 << 11)
+#define PERI_RST3_TSENSOR                      (1 << 12)
+#define PERI_RST3_DAPB                         (1 << 18)
+#define PERI_RST3_HKADC                                (1 << 19)
+#define PERI_RST3_CODEC                                (1 << 20)
+
+/*
+ * PERI_SC_PERIPH_RSTEN8
+ * PERI_SC_PERIPH_RSTDIS8
+ * PERI_SC_PERIPH_RSTSTAT8
+ */
+#define PERI_RST8_RS0                          (1 << 0)
+#define PERI_RST8_RS2                          (1 << 1)
+#define PERI_RST8_RS3                          (1 << 2)
+#define PERI_RST8_MS0                          (1 << 3)
+#define PERI_RST8_MS2                          (1 << 5)
+#define PERI_RST8_XG2RAM0                      (1 << 6)
+#define PERI_RST8_X2SRAM_TZMA                  (1 << 7)
+#define PERI_RST8_SRAM                         (1 << 8)
+#define PERI_RST8_HARQ                         (1 << 10)
+#define PERI_RST8_DDRC                         (1 << 12)
+#define PERI_RST8_DDRC_APB                     (1 << 13)
+#define PERI_RST8_DDRPACK_APB                  (1 << 14)
+#define PERI_RST8_DDRT                         (1 << 17)
+
+#endif /* __HI6220_PERI_H__ */
diff --git a/plat/hikey/include/hi6220_regs_pmctrl.h b/plat/hikey/include/hi6220_regs_pmctrl.h
new file mode 100644 (file)
index 0000000..4a2e905
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HI6220_REGS_PMCTRL_H__
+#define __HI6220_REGS_PMCTRL_H__
+
+#define PMCTRL_BASE                            0xF7032000
+
+#define PMCTRL_ACPUPLLCTRL                     (PMCTRL_BASE + 0x000)
+#define PMCTRL_ACPUPLLFREQ                     (PMCTRL_BASE + 0x004)
+#define PMCTRL_DDRPLL1CTRL                     (PMCTRL_BASE + 0x010)
+#define PMCTRL_DDRPLL0CTRL                     (PMCTRL_BASE + 0x030)
+#define PMCTRL_MEDPLLCTRL                      (PMCTRL_BASE + 0x038)
+#define PMCTRL_ACPUPLLSEL                      (PMCTRL_BASE + 0x100)
+#define PMCTRL_ACPUCLKDIV                      (PMCTRL_BASE + 0x104)
+#define PMCTRL_ACPUSYSPLLCFG                   (PMCTRL_BASE + 0x110)
+#define PMCTRL_ACPUCLKOFFCFG                   (PMCTRL_BASE + 0x114)
+#define PMCTRL_ACPUPLLFRAC                     (PMCTRL_BASE + 0x134)
+#define PMCTRL_ACPUPMUVOLUPTIME                        (PMCTRL_BASE + 0x360)
+#define PMCTRL_ACPUPMUVOLDNTIME                        (PMCTRL_BASE + 0x364)
+#define PMCTRL_ACPUVOLPMUADDR                  (PMCTRL_BASE + 0x368)
+#define PMCTRL_ACPUVOLUPSTEP                   (PMCTRL_BASE + 0x36c)
+#define PMCTRL_ACPUVOLDNSTEP                   (PMCTRL_BASE + 0x370)
+#define PMCTRL_ACPUDFTVOL                      (PMCTRL_BASE + 0x374)
+#define PMCTRL_ACPUDESTVOL                     (PMCTRL_BASE + 0x378)
+#define PMCTRL_ACPUVOLTTIMEOUT                 (PMCTRL_BASE + 0x37c)
+
+#define PMCTRL_ACPUPLLCTRL_EN_CFG              (1 << 0)
+
+#define PMCTRL_ACPUCLKDIV_CPUEXT_CFG_MASK      (3 << 0)
+#define PMCTRL_ACPUCLKDIV_DDR_CFG_MASK         (3 << 8)
+#define PMCTRL_ACPUCLKDIV_CPUEXT_STAT_MASK     (3 << 16)
+#define PMCTRL_ACPUCLKDIV_DDR_STAT_MASK                (3 << 24)
+
+#define PMCTRL_ACPUPLLSEL_ACPUPLL_CFG          (1 << 0)
+#define PMCTRL_ACPUPLLSEL_ACPUPLL_STAT         (1 << 1)
+#define PMCTRL_ACPUPLLSEL_SYSPLL_STAT          (1 << 2)
+
+#define PMCTRL_ACPUSYSPLL_CLKDIV_CFG_MASK      0x7
+#define PMCTRL_ACPUSYSPLL_CLKEN_CFG            (1 << 4)
+#define PMCTRL_ACPUSYSPLL_CLKDIV_SW            (3 << 12)
+
+#define PMCTRL_ACPUSYSPLLCFG_SYSPLL_CLKEN      (1 << 4)
+#define PMCTRL_ACPUSYSPLLCFG_CLKDIV_MASK       (3 << 12)
+
+#define PMCTRL_ACPUDESTVOL_DEST_VOL_MASK       0x7f
+#define PMCTRL_ACPUDESTVOL_CURR_VOL_MASK       (0x7f << 8)
+
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START   (0)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_END     (0)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_rst_START      (2)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_rst_END        (2)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_time_START     (4)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_time_END       (27)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START  (28)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_END    (28)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_lock_START     (29)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_lock_END       (29)
+
+#define SOC_PMCTRL_ACPUPLLFRAC_ADDR(base)   ((base) + (0x134))
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START   (12)
+
+#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START   (0)
+#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_END     (0)
+#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START  (1)
+#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_END    (1)
+#define SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START   (2)
+#define SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_END     (2)
+
+#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START     (0)
+#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_END       (1)
+#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START   (8)
+#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_END     (9)
+#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START    (16)
+#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_END      (17)
+#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START  (24)
+#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_END    (25)
+
+#define SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START   (0)
+#define SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END     (6)
+#define SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START  (8)
+#define SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_END    (14)
+
+#define SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START  (0)
+#define SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_END    (0)
+
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_cfg_START      (0)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_cfg_END        (2)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START    (4)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_END      (4)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_cfg_START  (8)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_cfg_END    (9)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_stat_START     (16)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_stat_END       (19)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_stat_START   (20)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_stat_END     (20)
+
+#endif /* __HI6220_REGS_PMCTRL_H__ */
diff --git a/plat/hikey/include/hi6553.h b/plat/hikey/include/hi6553.h
new file mode 100644 (file)
index 0000000..9efc580
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HI6553_H__
+#define __HI6553_H__
+
+#define DISABLE6_XO_CLK                                0x036
+
+#define DISABLE6_XO_CLK_BB                     (1 << 0)
+#define DISABLE6_XO_CLK_CONN                   (1 << 1)
+#define DISABLE6_XO_CLK_NFC                    (1 << 2)
+#define DISABLE6_XO_CLK_RF1                    (1 << 3)
+#define DISABLE6_XO_CLK_RF2                    (1 << 4)
+
+#define VERSION_REG                            0x000
+#define ENABLE2_LDO1_8                         0x029
+#define DISABLE2_LDO1_8                                0x02a
+#define ONOFF_STATUS2_LDO1_8                   0x02b
+#define ENABLE3_LDO9_16                                0x02c
+#define DISABLE3_LDO9_16                       0x02d
+#define ONOFF_STATUS3_LDO9_16                  0x02e
+#define ENABLE4_LDO17_22                       0x02f
+#define DISABLE4_LDO17_22                      0x030
+#define ONOFF_STATUS4_LDO17_22                 0x031
+#define PERI_EN_MARK                           0x040
+#define BUCK2_REG1                             0x04a
+#define BUCK2_REG5                             0x04e
+#define BUCK2_REG6                             0x04f
+#define BUCK3_REG3                             0x054
+#define BUCK3_REG5                             0x056
+#define BUCK3_REG6                             0x057
+#define BUCK4_REG2                             0x05b
+#define BUCK4_REG5                             0x05e
+#define BUCK4_REG6                             0x05f
+#define CLK_TOP0                               0x063
+#define CLK_TOP3                               0x066
+#define CLK_TOP4                               0x067
+#define VSET_BUCK2_ADJ                         0x06d
+#define VSET_BUCK3_ADJ                         0x06e
+#define LDO7_REG_ADJ                           0x078
+#define LDO10_REG_ADJ                          0x07b
+#define LDO15_REG_ADJ                          0x080
+#define LDO19_REG_ADJ                          0x084
+#define LDO20_REG_ADJ                          0x085
+#define LDO22_REG_ADJ                          0x087
+#define DR_LED_CTRL                            0x098
+#define DR_OUT_CTRL                            0x099
+#define DR3_ISET                               0x09a
+#define DR3_START_DEL                          0x09b
+#define DR4_ISET                               0x09c
+#define DR4_START_DEL                          0x09d
+#define DR345_TIM_CONF0                                0x0a0
+#define NP_REG_ADJ1                            0x0be
+#define NP_REG_CHG                             0x0c0
+#define BUCK01_CTRL2                           0x0d9
+#define BUCK0_CTRL1                            0x0dd
+#define BUCK0_CTRL5                            0x0e1
+#define BUCK0_CTRL7                            0x0e3
+#define BUCK1_CTRL1                            0x0e8
+#define BUCK1_CTRL5                            0x0ec
+#define BUCK1_CTRL7                            0x0ef
+#define CLK19M2_600_586_EN                     0x0fe
+
+#define LED_START_DELAY_TIME                   0x00
+#define LED_ELEC_VALUE                         0x07
+#define LED_LIGHT_TIME                         0xf0
+#define LED_GREEN_ENABLE                       (1 << 1)
+#define LED_OUT_CTRL                           0x00
+
+#define PMU_HI6552_V300                                0x30
+#define PMU_HI6552_V310                                0x31
+
+extern unsigned char hi6553_read_8(unsigned int offset);
+extern void hi6553_write_8(unsigned int offset, unsigned int value);
+
+#endif /* __HI6553_H__ */
diff --git a/plat/hikey/include/hisi_ipc.h b/plat/hikey/include/hisi_ipc.h
new file mode 100644 (file)
index 0000000..0afe011
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __HISI_IPC_H__
+#define __HISI_IPC_H__
+
+#define HISI_IPC_CORE_ACPU             0x0
+
+#define HISI_IPC_MCU_INT_SRC_ACPU0_PD  10
+#define HISI_IPC_MCU_INT_SRC_ACPU1_PD  11
+#define HISI_IPC_MCU_INT_SRC_ACPU2_PD  12
+#define HISI_IPC_MCU_INT_SRC_ACPU3_PD  13
+#define HISI_IPC_MCU_INT_SRC_ACPU_PD   16
+#define HISI_IPC_MCU_INT_SRC_ACPU4_PD  26
+#define HISI_IPC_MCU_INT_SRC_ACPU5_PD  27
+#define HISI_IPC_MCU_INT_SRC_ACPU6_PD  28
+#define HISI_IPC_MCU_INT_SRC_ACPU7_PD  29
+
+#define HISI_IPC_SEM_CPUIDLE           27
+#define HISI_IPC_INT_SRC_NUM           32
+
+#define HISI_IPC_PM_ON                 0
+#define HISI_IPC_PM_OFF                        1
+
+#define HISI_IPC_OK                    (0)
+#define HISI_IPC_ERROR                 (-1)
+
+#define HISI_IPC_BASE_ADDR             (0xF7510000)
+#define HISI_IPC_CPU_RAW_INT_ADDR      (0xF7510420)
+#define HISI_IPC_ACPU_CTRL(i)          (0xF7510800 + (i << 3))
+
+void hisi_ipc_spin_lock(unsigned int signal);
+void hisi_ipc_spin_unlock(unsigned int signal);
+void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_psci_system_off(void);
+int hisi_ipc_init(void);
+
+#endif
diff --git a/plat/hikey/include/hisi_mcu.h b/plat/hikey/include/hisi_mcu.h
new file mode 100644 (file)
index 0000000..74dbf17
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef        __MCU_H__
+#define        __MCU_H__
+
+#include <stdint.h>
+
+extern void hisi_mcu_enable_sram(void);
+extern void hisi_mcu_start_run(void);
+extern int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size);
+
+#endif /* __MCU_H__ */
diff --git a/plat/hikey/include/hisi_pwrc.h b/plat/hikey/include/hisi_pwrc.h
new file mode 100644 (file)
index 0000000..d7907fb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HISI_PWRC_H__
+#define __HISI_PWRC_H__
+
+#ifndef __ASSEMBLY__
+
+void hisi_pwrc_set_cluster_wfi(unsigned int id);
+void hisi_pwrc_set_core_bx_addr(unsigned int core,
+                               unsigned int cluster,
+                               uintptr_t entry_point);
+int hisi_pwrc_setup(void);
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* __HISI_PWRC_H__ */
diff --git a/plat/hikey/include/hisi_sram_map.h b/plat/hikey/include/hisi_sram_map.h
new file mode 100644 (file)
index 0000000..dc4425d
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SRAM_MAP_H__
+#define __SRAM_MAP_H__
+
+/*
+ * SRAM Memory Region Layout
+ *
+ *  +-----------------------+
+ *  |  Low Power Mode       | 7KB
+ *  +-----------------------+
+ *  |  Secure OS            | 64KB
+ *  +-----------------------+
+ *  |  Software Flag        | 1KB
+ *  +-----------------------+
+ *
+ */
+
+#define SOC_SRAM_OFF_BASE_ADDR         (0xFFF80000)
+
+/* PM Section: 7KB */
+#define SRAM_PM_ADDR                   (SOC_SRAM_OFF_BASE_ADDR)
+#define SRAM_PM_SIZE                   (0x00001C00)
+
+/* TEE OS Section: 64KB */
+#define SRAM_TEEOS_ADDR                        (SRAM_PM_ADDR + SRAM_PM_SIZE)
+#define SRAM_TEEOS_SIZE                        (0x00010000)
+
+/* General Use Section: 1KB */
+#define SRAM_GENERAL_ADDR              (SRAM_TEEOS_ADDR + SRAM_TEEOS_SIZE)
+#define SRAM_GENERAL_SIZE              (0x00000400)
+
+/*
+ * General Usage Section Layout:
+ *
+ *  +-----------------------+
+ *  |  AP boot flag         | 64B
+ *  +-----------------------+
+ *  |  DICC flag            | 32B
+ *  +-----------------------+
+ *  |  Soft flag            | 256B
+ *  +-----------------------+
+ *  |  Thermal flag         | 128B
+ *  +-----------------------+
+ *  |  CSHELL               | 4B
+ *  +-----------------------+
+ *  |  Uart Switching       | 4B
+ *  +-----------------------+
+ *  |  ICC                  | 1024B
+ *  +-----------------------+
+ *  |  Memory Management    | 1024B
+ *  +-----------------------+
+ *  |  IFC                  | 32B
+ *  +-----------------------+
+ *  |  HIFI                 | 32B
+ *  +-----------------------+
+ *  |  DDR capacity         | 4B
+ *  +-----------------------+
+ *  |  Reserved             |
+ *  +-----------------------+
+ *
+ */
+
+/* App Core Boot Flags */
+#define MEMORY_AXI_ACPU_START_ADDR             (SRAM_GENERAL_ADDR)
+#define MEMORY_AXI_ACPU_START_SIZE             (64)
+
+#define MEMORY_AXI_SRESET_FLAG_ADDR            (MEMORY_AXI_ACPU_START_ADDR + 0x0000)
+#define MEMORY_AXI_SECOND_CPU_BOOT_ADDR                (MEMORY_AXI_ACPU_START_ADDR + 0x0004)
+#define MEMORY_AXI_READY_FLAG_ADDR             (MEMORY_AXI_ACPU_START_ADDR + 0x0008)
+#define MEMORY_AXI_FASTBOOT_ENTRY_ADDR         (MEMORY_AXI_ACPU_START_ADDR + 0x000C)
+#define MEMORY_AXI_PD_CHARGE_ADDR              (MEMORY_AXI_ACPU_START_ADDR + 0x0010)
+#define MEMORY_AXI_DBG_ALARM_ADDR              (MEMORY_AXI_ACPU_START_ADDR + 0x0014)
+#define MEMORY_AXI_CHIP_ADDR                   (MEMORY_AXI_ACPU_START_ADDR + 0x0018)
+#define MEMORY_AXI_BOARD_TYPE_ADDR             (MEMORY_AXI_ACPU_START_ADDR + 0x001C)
+#define MEMORY_AXI_BOARD_ID_ADDR               (MEMORY_AXI_ACPU_START_ADDR + 0x0020)
+#define MEMORY_AXI_CHARGETYPE_FLAG_ADDR                (MEMORY_AXI_ACPU_START_ADDR + 0x0024)
+#define MEMORY_AXI_COLD_START_ADDR             (MEMORY_AXI_ACPU_START_ADDR + 0x0028)
+#define MEMORY_AXI_ANDROID_REBOOT_FLAG_ADDR    (MEMORY_AXI_ACPU_START_ADDR + 0x002C)
+#define MEMORY_AXI_ACPU_WDTRST_REBOOT_FLAG_ADDR        (MEMORY_AXI_ACPU_START_ADDR + 0x0030)
+#define MEMORY_AXI_ABNRST_BITMAP_ADDR          (MEMORY_AXI_ACPU_START_ADDR + 0x0034)
+#define MEMORY_AXI_32K_CLK_TYPE_ADDR           (MEMORY_AXI_ACPU_START_ADDR + 0x0038)
+#define AXI_MODEM_PANIC_FLAG_ADDR              (MEMORY_AXI_ACPU_START_ADDR + 0x003C)
+#define AXI_MODEM_PANIC_FLAG                   (0x68697369)
+#define MEMORY_AXI_ACPU_END_ADDR               (AXI_MODEM_PANIC_FLAG_ADDR + 4)
+
+/* DICC Flags */
+#define MEMORY_AXI_DICC_ADDR                   (MEMORY_AXI_ACPU_START_ADDR + MEMORY_AXI_ACPU_START_SIZE)
+#define MEMORY_AXI_DICC_SIZE                   (32)
+
+#define MEMORY_AXI_SOFT_FLAG_ADDR              (MEMORY_AXI_DICC_ADDR + MEMORY_AXI_DICC_SIZE)
+#define MEMORY_AXI_SOFT_FLAG_SIZE              (256)
+
+/* Thermal Flags */
+#define MEMORY_AXI_TEMP_PROTECT_ADDR           (MEMORY_AXI_SOFT_FLAG_ADDR + MEMORY_AXI_SOFT_FLAG_SIZE)
+#define MEMORY_AXI_TEMP_PROTECT_SIZE           (128)
+
+/* CSHELL */
+#define MEMORY_AXI_USB_CSHELL_ADDR             (MEMORY_AXI_TEMP_PROTECT_ADDR + MEMORY_AXI_TEMP_PROTECT_SIZE)
+#define MEMORY_AXI_USB_CSHELL_SIZE             (4)
+
+/* Uart and A/C Shell Switch Flags */
+#define MEMORY_AXI_UART_INOUT_ADDR             (MEMORY_AXI_USB_CSHELL_ADDR + MEMORY_AXI_USB_CSHELL_SIZE)
+#define MEMORY_AXI_UART_INOUT_SIZE             (4)
+
+/* IFC Flags */
+#define MEMORY_AXI_IFC_ADDR                    (MEMORY_AXI_UART_INOUT_ADDR + MEMORY_AXI_UART_INOUT_SIZE)
+#define MEMORY_AXI_IFC_SIZE                    (32)
+
+/* HIFI Data */
+#define MEMORY_AXI_HIFI_ADDR                   (MEMORY_AXI_IFC_ADDR + MEMORY_AXI_IFC_SIZE)
+#define MEMORY_AXI_HIFI_SIZE                   (32)
+
+/* CONFIG Flags */
+#define MEMORY_AXI_CONFIG_ADDR                 (MEMORY_AXI_HIFI_ADDR + MEMORY_AXI_HIFI_SIZE)
+#define MEMORY_AXI_CONFIG_SIZE                 (32)
+
+/* DDR Capacity Flags */
+#define MEMORY_AXI_DDR_CAPACITY_ADDR           (MEMORY_AXI_CONFIG_ADDR + MEMORY_AXI_CONFIG_SIZE)
+#define MEMORY_AXI_DDR_CAPACITY_SIZE           (4)
+
+/* USB Shell Flags */
+#define MEMORY_AXI_USB_SHELL_FLAG_ADDR         (MEMORY_AXI_DDR_CAPACITY_ADDR + MEMORY_AXI_DDR_CAPACITY_SIZE )
+#define MEMORY_AXI_USB_SHELL_FLAG_SIZE         (4)
+
+/* MCU WDT Switch Flag */
+#define MEMORY_AXI_MCU_WDT_FLAG_ADDR           (MEMORY_AXI_USB_SHELL_FLAG_ADDR + MEMORY_AXI_USB_SHELL_FLAG_SIZE)
+#define MEMORY_AXI_MCU_WDT_FLAG_SIZE           (4)
+
+/* TLDSP Mailbox MNTN */
+#define SRAM_DSP_MNTN_INFO_ADDR                        (MEMORY_AXI_MCU_WDT_FLAG_ADDR + MEMORY_AXI_MCU_WDT_FLAG_SIZE)
+#define SRAM_DSP_MNTN_SIZE                     (32)
+
+/* TLDSP ARM Mailbox Protect Flag */
+#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR (SRAM_DSP_MNTN_INFO_ADDR + SRAM_DSP_MNTN_SIZE)
+#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE (4)
+
+/* RTT Sleep Flag */
+#define SRAM_RTT_SLEEP_FLAG_ADDR                (SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR + SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE)
+#define SRAM_RTT_SLEEP_FLAG_SIZE                (32)
+
+/* LDSP Awake Flag */
+#define MEMORY_AXI_LDSP_AWAKE_ADDR              (SRAM_RTT_SLEEP_FLAG_ADDR + SRAM_RTT_SLEEP_FLAG_SIZE)
+#define MEMORY_AXI_LDSP_AWAKE_SIZE              (4)
+
+#define NVUPDATE_SUCCESS                       0x5555AAAA
+#define NVUPDATE_FAILURE                       0xAAAA5555
+
+/*
+ * Low Power Mode Region
+ */
+#define PWRCTRL_ACPU_ASM_SPACE_ADDR            (SRAM_PM_ADDR)
+#define PWRCTRL_ACPU_ASM_SPACE_SIZE            (SRAM_PM_SIZE)
+
+#define PWRCTRL_ACPU_ASM_MEM_BASE              (PWRCTRL_ACPU_ASM_SPACE_ADDR)
+#define PWRCTRL_ACPU_ASM_MEM_SIZE              (PWRCTRL_ACPU_ASM_SPACE_SIZE)
+#define PWRCTRL_ACPU_ASM_CODE_BASE             (PWRCTRL_ACPU_ASM_MEM_BASE + 0x200)
+#define PWRCTRL_ACPU_ASM_DATA_BASE             (PWRCTRL_ACPU_ASM_MEM_BASE + 0xE00)
+#define PWRCTRL_ACPU_ASM_DATA_SIZE             (0xE00)
+
+#define PWRCTRL_ACPU_ASM_D_C0_ADDR             (PWRCTRL_ACPU_ASM_DATA_BASE)
+#define PWRCTRL_ACPU_ASM_D_C0_MMU_PARA_AD      (PWRCTRL_ACPU_ASM_DATA_BASE + 0)
+#define PWRCTRL_ACPU_ASM_D_ARM_PARA_AD         (PWRCTRL_ACPU_ASM_DATA_BASE + 0x20)
+
+#define PWRCTRL_ACPU_ASM_D_COMM_ADDR           (PWRCTRL_ACPU_ASM_DATA_BASE + 0x700)
+
+#define PWRCTRL_ACPU_REBOOT                    (PWRCTRL_ACPU_ASM_D_COMM_ADDR)
+#define PWRCTRL_ACPU_REBOOT_SIZE               (0x200)
+#define PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR                (PWRCTRL_ACPU_REBOOT + PWRCTRL_ACPU_REBOOT_SIZE)
+#define PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE                (4)
+#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR       (PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR + PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE)
+#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE       (4)
+#define EXCH_A_CORE_POWRCTRL_CONV_ADDR         (PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR + PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE)
+#define EXCH_A_CORE_POWRCTRL_CONV_SIZE         (4)
+
+/*
+ * Below region memory mapping is:
+ * 4 + 12 + 16 + 28 + 28 + 16 + 28 + 12 + 24 + 20 + 64 +
+ * 4 + 4 + 4 + 4 + 12 + 4 + 4 + 4 + 4 + 16 + 4 + 0x2BC +
+ * 24 + 20 + 12 + 16
+ */
+
+#define MEMORY_AXI_CPU_IDLE_ADDR               (EXCH_A_CORE_POWRCTRL_CONV_ADDR + EXCH_A_CORE_POWRCTRL_CONV_SIZE)
+#define MEMORY_AXI_CPU_IDLE_SIZE               (4)
+
+#define MEMORY_AXI_CUR_FREQ_ADDR               (MEMORY_AXI_CPU_IDLE_ADDR + MEMORY_AXI_CPU_IDLE_SIZE)
+#define MEMORY_AXI_CUR_FREQ_SIZE               (12)
+
+#define MEMORY_AXI_ACPU_FREQ_VOL_ADDR          (MEMORY_AXI_CUR_FREQ_ADDR + MEMORY_AXI_CUR_FREQ_SIZE)
+#define MEMORY_AXI_ACPU_FREQ_VOL_SIZE          (16 + 28 + 28)
+
+#define MEMORY_AXI_DDR_FREQ_VOL_ADDR           (MEMORY_AXI_ACPU_FREQ_VOL_ADDR + MEMORY_AXI_ACPU_FREQ_VOL_SIZE)
+#define MEMORY_AXI_DDR_FREQ_VOL_SIZE           (16 + 28)
+
+#define MEMORY_AXI_ACPU_FIQ_TEST_ADDR          (MEMORY_AXI_DDR_FREQ_VOL_ADDR + MEMORY_AXI_DDR_FREQ_VOL_SIZE)
+#define MEMORY_AXI_ACPU_FIQ_TEST_SIZE          (12)
+
+#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR      (MEMORY_AXI_ACPU_FIQ_TEST_ADDR + MEMORY_AXI_ACPU_FIQ_TEST_SIZE)
+#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE      (24)
+
+#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR    (MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE)
+#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE    (20)
+
+#define MEMORY_FREQDUMP_ADDR                   (MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE)
+#define MEMORY_FREQDUMP_SIZE                   (64)
+
+#define MEMORY_AXI_CCPU_LOG_ADDR               (MEMORY_FREQDUMP_ADDR + MEMORY_FREQDUMP_SIZE)
+#define MEMORY_AXI_CCPU_LOG_SIZE               (4)
+
+#define MEMORY_AXI_MCU_LOG_ADDR                        (MEMORY_AXI_CCPU_LOG_ADDR + MEMORY_AXI_CCPU_LOG_SIZE)
+#define MEMORY_AXI_MCU_LOG_SIZE                        (4)
+
+#define MEMORY_AXI_SEC_CORE_BOOT_ADDR          (MEMORY_AXI_MCU_LOG_ADDR + MEMORY_AXI_MCU_LOG_SIZE)
+#define MEMORY_AXI_SEC_CORE_BOOT_SIZE          (4)
+
+#define MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR       (MEMORY_AXI_SEC_CORE_BOOT_ADDR + MEMORY_AXI_SEC_CORE_BOOT_SIZE)
+#define MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE       (0x4)
+
+#define POLICY_AREA_RESERVED                   (MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR + MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE)
+#define POLICY_AREA_RESERVED_SIZE              (12)
+
+#define DDR_POLICY_VALID_MAGIC                 (POLICY_AREA_RESERVED + POLICY_AREA_RESERVED_SIZE)
+#define DDR_POLICY_VALID_MAGIC_SIZE            (4)
+
+#define DDR_POLICY_MAX_NUM                     (DDR_POLICY_VALID_MAGIC + DDR_POLICY_VALID_MAGIC_SIZE)
+#define DDR_POLICY_MAX_NUM_SIZE                        (4)
+
+#define DDR_POLICY_SUPPORT_NUM                 (DDR_POLICY_MAX_NUM + DDR_POLICY_MAX_NUM_SIZE)
+#define DDR_POLICY_SUPPORT_NUM_SIZE            (4)
+
+#define DDR_POLICY_CUR_POLICY                  (DDR_POLICY_SUPPORT_NUM + DDR_POLICY_SUPPORT_NUM_SIZE)
+#define DDR_POLICY_CUR_POLICY_SIZE             (4)
+
+#define ACPU_POLICY_VALID_MAGIC                        (DDR_POLICY_CUR_POLICY + DDR_POLICY_CUR_POLICY_SIZE)
+#define ACPU_POLICY_VALID_MAGIC_SIZE           (4)
+
+#define ACPU_POLICY_MAX_NUM                    (ACPU_POLICY_VALID_MAGIC + ACPU_POLICY_VALID_MAGIC_SIZE)
+#define ACPU_POLICY_MAX_NUM_SIZE               (4)
+
+#define ACPU_POLICY_SUPPORT_NUM                        (ACPU_POLICY_MAX_NUM + ACPU_POLICY_MAX_NUM_SIZE)
+#define ACPU_POLICY_SUPPORT_NUM_SIZE           (4)
+
+#define ACPU_POLICY_CUR_POLICY                 (ACPU_POLICY_SUPPORT_NUM + ACPU_POLICY_SUPPORT_NUM_SIZE)
+#define ACPU_POLICY_CUR_POLICY_SIZE            (4)
+
+#define LPDDR_OPTION_ADDR                      (ACPU_POLICY_CUR_POLICY + ACPU_POLICY_CUR_POLICY_SIZE)
+#define LPDDR_OPTION_SIZE                      (4)
+
+#define MEMORY_AXI_DDR_DDL_ADDR                        (LPDDR_OPTION_ADDR + LPDDR_OPTION_SIZE)
+#define MEMORY_AXI_DDR_DDL_SIZE                        (0x2BC)
+
+#define DDR_TEST_DFS_ADDR                      (MEMORY_AXI_DDR_DDL_ADDR + MEMORY_AXI_DDR_DDL_SIZE)
+#define DDR_TEST_DFS_ADDR_SIZE                 (4)
+
+#define DDR_TEST_DFS_TIMES_ADDR                        (DDR_TEST_DFS_ADDR + DDR_TEST_DFS_ADDR_SIZE)
+#define DDR_TEST_DFS_TIMES_ADDR_SIZE           (4)
+
+#define DDR_TEST_QOS_ADDR                      (DDR_TEST_DFS_TIMES_ADDR + DDR_TEST_DFS_TIMES_ADDR_SIZE)
+#define DDR_TEST_QOS_ADDR_SIZE                 (4)
+
+#define DDR_TEST_FUN_ADDR                      (DDR_TEST_QOS_ADDR + DDR_TEST_QOS_ADDR_SIZE)
+#define DDR_TEST_FUN_ADDR_SIZE                 (4)
+
+#define BOARD_TYPE_ADDR                                (DDR_TEST_FUN_ADDR + DDR_TEST_FUN_ADDR_SIZE)
+#define BOARD_ADDR_SIZE                                (4)
+#define DDR_DFS_FREQ_ADDR                      (BOARD_TYPE_ADDR + BOARD_ADDR_SIZE)
+#define DDR_DFS_FREQ_SIZE                      (4)
+
+#define DDR_PASR_ADDR                          (DDR_DFS_FREQ_ADDR + DDR_DFS_FREQ_SIZE)
+#define DDR_PASR_SIZE                          (20)
+
+#define ACPU_DFS_FREQ_ADDR                     (DDR_PASR_ADDR + DDR_PASR_SIZE)
+#define ACPU_DFS_FREQ_ADDR_SIZE                        (12)
+
+#define ACPU_CHIP_MAX_FREQ                     (ACPU_DFS_FREQ_ADDR + ACPU_DFS_FREQ_ADDR_SIZE)
+#define ACPU_CHIP_MAX_FREQ_SIZE                        (4)
+
+#define MEMORY_MEDPLL_STATE_ADDR               (ACPU_CHIP_MAX_FREQ + ACPU_CHIP_MAX_FREQ_SIZE)
+#define MEMORY_MEDPLL_STATE_SIZE               (8)
+
+#define MEMORY_CCPU_LOAD_FLAG_ADDR             (MEMORY_MEDPLL_STATE_ADDR + MEMORY_MEDPLL_STATE_SIZE)
+#define MEMORY_CCPU_LOAD_FLAG_SIZE             (4)
+
+
+#define ACPU_CORE_BITS_ADDR                    (MEMORY_CCPU_LOAD_FLAG_ADDR + MEMORY_CCPU_LOAD_FLAG_SIZE)
+#define ACPU_CORE_BITS_SIZE                    (4)
+
+#define ACPU_CLUSTER_IDLE_ADDR                 (ACPU_CORE_BITS_ADDR + ACPU_CORE_BITS_SIZE)
+#define ACPU_CLUSTER_IDLE_SIZE                 (4)
+
+#define ACPU_A53_FLAGS_ADDR                    (ACPU_CLUSTER_IDLE_ADDR + ACPU_CLUSTER_IDLE_SIZE)
+#define ACPU_A53_FLAGS_SIZE                    (4)
+
+#define ACPU_POWER_STATE_QOS_ADDR              (ACPU_A53_FLAGS_ADDR+ACPU_A53_FLAGS_SIZE)
+#define ACPU_POWER_STATE_QOS_SIZE              (4)
+
+#define ACPU_UNLOCK_CORE_FLAGS_ADDR            (ACPU_POWER_STATE_QOS_ADDR+ACPU_POWER_STATE_QOS_SIZE)
+#define ACPU_UNLOCK_CORE_FLAGS_SIZE            (8)
+
+#define ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR       (ACPU_UNLOCK_CORE_FLAGS_ADDR + ACPU_UNLOCK_CORE_FLAGS_SIZE)
+#define ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE       (4)
+
+#define ACPU_CORE_POWERDOWN_FLAGS_ADDR         (ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR + ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE)
+#define ACPU_CORE_POWERDOWN_FLAGS_SIZE         (4)
+
+#define ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR      (ACPU_CORE_POWERDOWN_FLAGS_ADDR + ACPU_CORE_POWERDOWN_FLAGS_SIZE)
+#define ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE      (4)
+
+#define ACPU_ARM64_FLAGA                       (ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR + ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE)
+#define ACPU_ARM64_FLAGA_SIZE                  (4)
+
+#define ACPU_ARM64_FLAGB                       (ACPU_ARM64_FLAGA + ACPU_ARM64_FLAGA_SIZE)
+#define ACPU_ARM64_FLAGB_SIZE                  (4)
+
+#define MCU_EXCEPTION_FLAGS_ADDR               (ACPU_ARM64_FLAGB + ACPU_ARM64_FLAGB_SIZE)
+#define MCU_EXCEPTION_FLAGS_SIZE               (4)
+
+#define ACPU_MASTER_CORE_STATE_ADDR            (MCU_EXCEPTION_FLAGS_ADDR + MCU_EXCEPTION_FLAGS_SIZE)
+#define ACPU_MASTER_CORE_STATE_SIZE            (4)
+
+#define PWRCTRL_AXI_RESERVED_ADDR              (ACPU_MASTER_CORE_STATE_ADDR + ACPU_MASTER_CORE_STATE_SIZE)
+
+#endif /* __SRAM_MAP_H__ */
diff --git a/plat/hikey/include/partitions.h b/plat/hikey/include/partitions.h
new file mode 100644 (file)
index 0000000..b386186
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PARTITIONS_H__
+#define __PARTITIONS_H__
+
+#define MAX_PARTITION_NUM              128
+#define EFI_NAMELEN                    36
+
+struct ptentry {
+       uint64_t        start;
+       uint64_t        length;
+       unsigned int    flags;
+       unsigned int    loadaddr;
+       unsigned int    loadsize;
+       int             id;
+       char            name[EFI_NAMELEN];
+};
+
+extern int get_partition(void);
+extern struct ptentry *find_ptn(const char *str);
+extern int update_fip_spec(void);
+
+#endif /* __PARTITIONS_H__ */
+
diff --git a/plat/hikey/include/plat_macros.S b/plat/hikey/include/plat_macros.S
new file mode 100644 (file)
index 0000000..624c49f
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cci400.h>
+#include <gic_v2.h>
+#include "platform_def.h"
+#include "../hikey_def.h"
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+       .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+       .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+       .asciz "\n"
+spacer:
+       .asciz ":\t\t0x"
+
+
+       /* ---------------------------------------------
+        * The below macro prints out relevant GIC
+        * registers whenever an unhandled exception is
+        * taken in BL3-1.
+        * Clobbers: x0 - x10, x16, sp
+        * ---------------------------------------------
+        */
+       .macro plat_print_gic_regs
+       mov_imm x16, GICD_BASE
+       mov_imm x17, GICC_BASE
+       /* Load the gicc reg list to x6 */
+       adr     x6, gicc_regs
+       /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+       ldr     w8, [x17, #GICC_HPPIR]
+       ldr     w9, [x17, #GICC_AHPPIR]
+       ldr     w10, [x17, #GICC_CTLR]
+       /* Store to the crash buf and print to console */
+       bl      str_in_crash_buf_print
+
+       /* Print the GICD_ISPENDR regs */
+       add     x7, x16, #GICD_ISPENDR
+       adr     x4, gicd_pend_reg
+       bl      asm_print_str
+gicd_ispendr_loop:
+       sub     x4, x7, x16
+       cmp     x4, #0x280
+       b.eq    exit_print_gic_regs
+       bl      asm_print_hex
+
+       adr     x4, spacer
+       bl      asm_print_str
+
+       ldr     x4, [x7], #8
+       bl      asm_print_hex
+
+       adr     x4, newline
+       bl      asm_print_str
+       b       gicd_ispendr_loop
+exit_print_gic_regs:
+       .endm
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+       .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+       /* ------------------------------------------------
+        * The below macro prints out relevant interconnect
+        * registers whenever an unhandled exception is
+        * taken in BL3-1.
+        * Clobbers: x0 - x9, sp
+        * ------------------------------------------------
+        */
+       .macro plat_print_interconnect_regs
+       adr     x6, cci_iface_regs
+       /* Store in x7 the base address of the first interface */
+       mov_imm x7, (CCI400_BASE + SLAVE_IFACE3_OFFSET)
+       ldr     w8, [x7, #SNOOP_CTRL_REG]
+       /* Store in x7 the base address of the second interface */
+       mov_imm x7, (CCI400_BASE + SLAVE_IFACE4_OFFSET)
+       ldr     w9, [x7, #SNOOP_CTRL_REG]
+       /* Store to the crash buf and print to console */
+       bl      str_in_crash_buf_print
+       .endm
diff --git a/plat/hikey/include/platform_def.h b/plat/hikey/include/platform_def.h
new file mode 100644 (file)
index 0000000..d8694da
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include "../hikey_def.h"
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT          "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH            aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE            0x800
+
+#define FIRMWARE_WELCOME_STR           "Booting Trusted Firmware\n"
+
+#define LOADER_MEM_NAME                        "loader_mem"
+
+#define BOOT_EMMC_NAME                 "l-loader.bin"
+
+#define NORMAL_EMMC_NAME               "normal emmc"
+
+/* Trusted Boot Firmware BL2 */
+#define BL2_IMAGE_NAME                 "bl2.bin"
+
+/* EL3 Runtime Firmware BL3-1 */
+#define BL31_IMAGE_NAME                        "bl31.bin"
+
+/* SCP Firmware BL3-0 */
+#define BL30_IMAGE_NAME                        "bl30.bin"
+
+/* Secure Payload BL3-2 (Trusted OS) */
+#define BL32_IMAGE_NAME                        "bl32.bin"
+
+/* Non-Trusted Firmware BL3-3 */
+#define BL33_IMAGE_NAME                        "bl33.bin" /* e.g. UEFI */
+
+/* Firmware Image Package */
+#define FIP_IMAGE_NAME                 "fip.bin"
+
+#define PLATFORM_CACHE_LINE_SIZE       64
+#define PLATFORM_CLUSTER_COUNT         2
+#define PLATFORM_CORE_COUNT_PER_CLUSTER        4
+#define PLATFORM_CORE_COUNT             8
+#define PLATFORM_NUM_AFFS              (PLATFORM_CLUSTER_COUNT + \
+                                        PLATFORM_CORE_COUNT)
+#define PLATFORM_MAX_AFFLVL             MPIDR_AFFLVL1
+
+#define MAX_IO_DEVICES                 3
+#define MAX_IO_HANDLES                 4
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+
+/*******************************************************************************
+ * BL1 is stored in XG2RAM0_HIRQ that is 784KB large. Could we use 8MB size?
+ * The first part is BL1_RAM, and the second part is TZRAM. The name isn't good
+ * enough. We need to update it later.
+ ******************************************************************************/
+#define MMC_BASE                       0x00000000
+#define MMC_SIZE                       0x80000000
+#define MMC_LOADER_BASE                        MMC_BASE                /* boot */
+#define MMC_BL1_SIZE                   0x00200000
+
+#define ONCHIPROM_PARAM_BASE           (XG2RAM0_BASE + 0x700)
+#define LOADER_RAM_BASE                        (XG2RAM0_BASE + 0x800)
+#define BL1_XG2RAM0_OFFSET             0x1000
+
+#define DDR_BASE                       0x00000000
+
+#define MMC_DESC_BASE                  (DDR_BASE + 0x0080000)
+#define MMC_DESC_SIZE                  0x00080000
+#define MMC_DATA_BASE                  (MMC_DESC_BASE + MMC_DESC_SIZE)
+#define MMC_DATA_SIZE                  0x00800000
+
+/*******************************************************************************
+ * BL1 specific defines.
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 base
+ * addresses.
+ ******************************************************************************/
+#define BL1_RO_BASE                    (XG2RAM0_BASE + BL1_XG2RAM0_OFFSET)
+#define BL1_RO_LIMIT                   (XG2RAM0_BASE + 0x10000)
+#define BL1_RW_BASE                    (BL1_RO_LIMIT)  /* 0xf981_0000 */
+#define BL1_RW_SIZE                    (BL31_LIMIT - BL1_RW_BASE)
+#define BL1_RW_LIMIT                   (BL31_LIMIT)
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+/* Set it in DDR first. If necessary, we can set them into SRAM again. */
+#define BL2_BASE                       (BL1_RW_BASE + 0x8000)  /* 0xf981_8000 */
+#define BL2_LIMIT                      (BL2_BASE + 0x40000)
+
+/*******************************************************************************
+ * BL3-1 specific defines.
+ ******************************************************************************/
+#define BL31_BASE                      (BL2_LIMIT)     /* 0xf985_8000 */
+#define BL31_LIMIT                     (BL31_BASE + 0x40000)
+
+/*******************************************************************************
+ * BL3-2 specific defines.
+ ******************************************************************************/
+
+/*
+ * The TSP can execute either from Trusted SRAM or Trusted DRAM.
+ */
+#define BL32_SRAM_BASE                  BL31_LIMIT
+#define BL32_SRAM_LIMIT                 (BL31_LIMIT+0x00080000) /* 512K */
+
+#define BL32_DRAM_BASE                  DRAM_SEC_BASE
+#define BL32_DRAM_LIMIT                 (DRAM_SEC_BASE+DRAM_SEC_SIZE)
+
+#if (PLAT_TSP_LOCATION_ID == PLAT_TRUSTED_SRAM_ID)
+#define TSP_SEC_MEM_BASE               BL32_SRAM_BASE
+#define TSP_SEC_MEM_SIZE               (BL32_SRAM_LIMIT - BL32_SRAM_BASE)
+#define BL32_BASE                      BL32_SRAM_BASE
+#define BL32_LIMIT                     BL32_SRAM_LIMIT
+#elif (PLAT_TSP_LOCATION_ID == PLAT_TRUSTED_DRAM_ID)
+#define TSP_SEC_MEM_BASE               BL32_DRAM_BASE
+#define TSP_SEC_MEM_SIZE               (BL32_DRAM_LIMIT - BL32_DRAM_BASE)
+#define BL32_BASE                      BL32_DRAM_BASE
+#define BL32_LIMIT                     BL32_DRAM_LIMIT
+#else
+#error "Unsupported PLAT_TSP_LOCATION_ID value"
+#endif
+
+/*******************************************************************************
+ * BL3-0 specific defines:
+ *
+ * BL3-0 is loaded for mcu firmware, firstly load it into temperary buffer
+ * into 0x0100_0000; then BL2 will parse the sections and load then into
+ * seperated buffers as needed.
+ *
+ ******************************************************************************/
+#define BL30_BASE                      (DRAM_NS_BASE + 0x01000000)
+#define BL30_LIMIT                     (DRAM_NS_BASE + 0x01100000)
+#define BL30_SIZE                      (BL30_LIMIT - BL30_BASE)
+
+/*******************************************************************************
+ * Load address of BL3-3 in the HiKey port
+ ******************************************************************************/
+#define NS_IMAGE_OFFSET                        (DRAM_BASE + 0x35000000)  /* 848MB */
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE                        (1ull << 32)
+
+#if IMAGE_BL1 || IMAGE_BL32
+# define MAX_XLAT_TABLES               3
+#endif
+
+#if IMAGE_BL2
+# define MAX_XLAT_TABLES               4
+#endif
+
+#if IMAGE_BL31
+# define MAX_XLAT_TABLES               4
+#endif
+
+#define MAX_MMAP_REGIONS               16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT   6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/hikey/include/sp804_timer.h b/plat/hikey/include/sp804_timer.h
new file mode 100644 (file)
index 0000000..6d1b664
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef        __SP804_TIMER_H__
+#define        __SP804_TIMER_H__
+
+extern void hi6220_timer_init(void);
+extern void udelay(int);
+extern void mdelay(int);
+
+#endif /* __SP804_TIMER_H__ */
diff --git a/plat/hikey/include/usb.h b/plat/hikey/include/usb.h
new file mode 100644 (file)
index 0000000..8fdcc6c
--- /dev/null
@@ -0,0 +1,878 @@
+/*
+ * Copyright (c) 2014, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DWC_USB_H__
+#define __DWC_USB_H__
+
+#define USB_DMA
+
+#define DWC_OTG_BASE                   0xF72C0000
+
+#define USB_NUM_ENDPOINTS              2
+#define MAX_EPS_CHANNELS               16
+
+#define BULK_OUT_EP                    1
+#define BULK_IN_EP                     1
+
+#define RX_REQ_LEN                     512
+#define MAX_PACKET_LEN                 512
+
+#define DATA_FIFO_CONFIG               (0x780 << GDFIFOCFG_EPINFOBASE_SHIFT |\
+                                        0x800 << GDFIFOCFG_GDFIFOCFG_SHIFT)
+/* RX FIFO: 2048 bytes */
+#define RX_SIZE                                0x00000200
+/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */
+#define ENDPOINT_TX_SIZE               0x00200200
+
+/* EP1  TX FIFO: 1024 bytes. start address: 0x220 * 4. */
+/* EP2  TX FIFO: 1024 bytes. start address: 0x320 * 4. */
+/* EP3  TX FIFO: 1024 bytes. start address: 0x420 * 4. */
+/* EP4  TX FIFO: 1024 bytes. start address: 0x520 * 4. */
+/* EP5  TX FIFO: 128  bytes. start address: 0x620 * 4. */
+/* EP6  TX FIFO: 128  bytes. start address: 0x640 * 4. */
+/* EP7  TX FIFO: 128  bytes. start address: 0x660 * 4. */
+/* EP8  TX FIFO: 128  bytes. start address: 0x680 * 4. */
+/* EP9  TX FIFO: 128  bytes. start address: 0x6a0 * 4. */
+/* EP10 TX FIFO: 128  bytes. start address: 0x6c0 * 4. */
+/* EP11 TX FIFO: 128  bytes. start address: 0x6e0 * 4. */
+/* EP12 TX FIFO: 128  bytes. start address: 0x700 * 4. */
+/* EP13 TX FIFO: 128  bytes. start address: 0x720 * 4. */
+/* EP14 TX FIFO: 128  bytes. start address: 0x740 * 4. */
+/* EP15 TX FIFO: 128  bytes. start address: 0x760 * 4. */
+
+#define DATA_IN_ENDPOINT_TX_FIFO1      0x01000220
+#define DATA_IN_ENDPOINT_TX_FIFO2      0x01000320
+#define DATA_IN_ENDPOINT_TX_FIFO3      0x01000420
+#define DATA_IN_ENDPOINT_TX_FIFO4      0x01000520
+#define DATA_IN_ENDPOINT_TX_FIFO5      0x00200620
+#define DATA_IN_ENDPOINT_TX_FIFO6      0x00200640
+#define DATA_IN_ENDPOINT_TX_FIFO7      0x00200660
+#define DATA_IN_ENDPOINT_TX_FIFO8      0x00200680
+#define DATA_IN_ENDPOINT_TX_FIFO9      0x002006a0
+#define DATA_IN_ENDPOINT_TX_FIFO10     0x002006c0
+#define DATA_IN_ENDPOINT_TX_FIFO11     0x002006e0
+#define DATA_IN_ENDPOINT_TX_FIFO12     0x00200700
+#define DATA_IN_ENDPOINT_TX_FIFO13     0x00200720
+#define DATA_IN_ENDPOINT_TX_FIFO14     0x00200740
+#define DATA_IN_ENDPOINT_TX_FIFO15     0x00200760
+
+typedef struct {
+       unsigned char           type;
+       unsigned char           request;
+       unsigned short          value;
+       unsigned short          index;
+       unsigned short          length;
+} setup_packet;
+
+struct ept_queue_item {
+       unsigned int            next;
+       unsigned int            info;
+};
+
+struct usb_request {
+       struct ept_queue_item   *item;
+       void                    *buf;
+       unsigned int            length;
+       void (*complete)(unsigned int actual, int status);
+       void                    *context;
+};
+
+/*DWC_OTG regsiter descriptor*/
+/*Global CSR MAP*/
+#define GLOBAL_CSR_BASE                (DWC_OTG_BASE)
+/*Device mode CSR MAP*/
+#define DEVICE_CSR_BASE                (DWC_OTG_BASE+0x800)
+/*Device mode CSR MAP*/
+#define DEVICE_INEP_BASE       (DWC_OTG_BASE+0x900)
+/*Device mode CSR MAP*/
+#define DEVICE_OUTEP_BASE      (DWC_OTG_BASE+0xB00)
+
+/*** OTG LINK CORE REGISTERS ***/
+/* Core Global Registers */
+#define GOTGCTL                        (DWC_OTG_BASE + 0x000)
+#define GOTGINT                        (DWC_OTG_BASE + 0x004)
+#define GOTGINT_DBNCE_DONE             (1 << 19)
+#define GOTGINT_A_DEV_TOUT_CHG         (1 << 18)
+#define GOTGINT_HST_NEG_DET            (1 << 17)
+#define GOTGINT_HST_NEG_SUC_STS_CHNG   (1 << 9)
+#define GOTGINT_SES_REQ_SUC_STS_CHNG   (1 << 8)
+#define GOTGINT_SES_END_DET            (1 << 2)
+
+#define GAHBCFG                        (DWC_OTG_BASE + 0x008)
+#define GAHBCFG_P_TXF_EMP_LVL           (1 << 8)
+#define GAHBCFG_NP_TXF_EMP_LVL          (1 << 7)
+#define GAHBCFG_DMA_EN                  (1 << 5)
+#define GAHBCFG_GLBL_INTR_EN            (1 << 0)
+#define GAHBCFG_CTRL_MASK               (GAHBCFG_P_TXF_EMP_LVL | \
+                                        GAHBCFG_NP_TXF_EMP_LVL | \
+                                        GAHBCFG_DMA_EN | \
+                                        GAHBCFG_GLBL_INTR_EN)
+
+#define GUSBCFG                        (DWC_OTG_BASE + 0x00C)
+#define GRSTCTL                        (DWC_OTG_BASE + 0x010)
+#define GRSTCTL_AHBIDLE                (1 << 31)
+#define GRSTCTL_CSFTRST                (1 << 0)
+
+#define GINTSTS                        (DWC_OTG_BASE + 0x014)
+#define GINTMSK                        (DWC_OTG_BASE + 0x018)
+#define GINTSTS_WKUPINT                        (1 << 31)
+#define GINTSTS_SESSREQINT             (1 << 30)
+#define GINTSTS_DISCONNINT             (1 << 29)
+#define GINTSTS_CONIDSTSCHNG           (1 << 28)
+#define GINTSTS_LPMTRANRCVD            (1 << 27)
+#define GINTSTS_PTXFEMP                        (1 << 26)
+#define GINTSTS_HCHINT                 (1 << 25)
+#define GINTSTS_PRTINT                 (1 << 24)
+#define GINTSTS_RESETDET               (1 << 23)
+#define GINTSTS_FET_SUSP               (1 << 22)
+#define GINTSTS_INCOMPL_IP             (1 << 21)
+#define GINTSTS_INCOMPL_SOIN           (1 << 20)
+#define GINTSTS_OEPINT                 (1 << 19)
+#define GINTSTS_IEPINT                 (1 << 18)
+#define GINTSTS_EPMIS                  (1 << 17)
+#define GINTSTS_RESTOREDONE            (1 << 16)
+#define GINTSTS_EOPF                   (1 << 15)
+#define GINTSTS_ISOUTDROP              (1 << 14)
+#define GINTSTS_ENUMDONE               (1 << 13)
+#define GINTSTS_USBRST                 (1 << 12)
+#define GINTSTS_USBSUSP                        (1 << 11)
+#define GINTSTS_ERLYSUSP               (1 << 10)
+#define GINTSTS_I2CINT                 (1 << 9)
+#define GINTSTS_ULPI_CK_INT            (1 << 8)
+#define GINTSTS_GOUTNAKEFF             (1 << 7)
+#define GINTSTS_GINNAKEFF              (1 << 6)
+#define GINTSTS_NPTXFEMP               (1 << 5)
+#define GINTSTS_RXFLVL                 (1 << 4)
+#define GINTSTS_SOF                    (1 << 3)
+#define GINTSTS_OTGINT                 (1 << 2)
+#define GINTSTS_MODEMIS                        (1 << 1)
+#define GINTSTS_CURMODE_HOST           (1 << 0)
+
+#define GRXSTSR                        (DWC_OTG_BASE + 0x01C)
+#define GRXSTSP                        (DWC_OTG_BASE + 0x020)
+#define GRXFSIZ                        (DWC_OTG_BASE + 0x024)
+#define GNPTXFSIZ              (DWC_OTG_BASE + 0x028)
+#define GNPTXSTS               (DWC_OTG_BASE + 0x02C)
+
+#define GHWCFG1                        (DWC_OTG_BASE + 0x044)
+#define GHWCFG2                        (DWC_OTG_BASE + 0x048)
+#define GHWCFG3                        (DWC_OTG_BASE + 0x04c)
+#define GHWCFG4                        (DWC_OTG_BASE + 0x050)
+#define GLPMCFG                        (DWC_OTG_BASE + 0x054)
+
+#define GDFIFOCFG              (DWC_OTG_BASE + 0x05c)
+#define GDFIFOCFG_EPINFOBASE_MASK      (0xffff << 16)
+#define GDFIFOCFG_EPINFOBASE_SHIFT     16
+#define GDFIFOCFG_GDFIFOCFG_MASK       (0xffff << 0)
+#define GDFIFOCFG_GDFIFOCFG_SHIFT      0
+
+
+#define HPTXFSIZ               (DWC_OTG_BASE + 0x100)
+#define DIEPTXF(x)             (DWC_OTG_BASE + 0x100 + 4 * (x))
+#define DIEPTXF1               (DWC_OTG_BASE + 0x104)
+#define DIEPTXF2               (DWC_OTG_BASE + 0x108)
+#define DIEPTXF3               (DWC_OTG_BASE + 0x10C)
+#define DIEPTXF4               (DWC_OTG_BASE + 0x110)
+#define DIEPTXF5               (DWC_OTG_BASE + 0x114)
+#define DIEPTXF6               (DWC_OTG_BASE + 0x118)
+#define DIEPTXF7               (DWC_OTG_BASE + 0x11C)
+#define DIEPTXF8               (DWC_OTG_BASE + 0x120)
+#define DIEPTXF9               (DWC_OTG_BASE + 0x124)
+#define DIEPTXF10              (DWC_OTG_BASE + 0x128)
+#define DIEPTXF11              (DWC_OTG_BASE + 0x12C)
+#define DIEPTXF12              (DWC_OTG_BASE + 0x130)
+#define DIEPTXF13              (DWC_OTG_BASE + 0x134)
+#define DIEPTXF14              (DWC_OTG_BASE + 0x138)
+#define DIEPTXF15              (DWC_OTG_BASE + 0x13C)
+
+/*** HOST MODE REGISTERS ***/
+/* Host Global Registers */
+#define HCFG                   (DWC_OTG_BASE + 0x400)
+#define HFIR                   (DWC_OTG_BASE + 0x404)
+#define HFNUM                  (DWC_OTG_BASE + 0x408)
+#define HPTXSTS                        (DWC_OTG_BASE + 0x410)
+#define HAINT                  (DWC_OTG_BASE + 0x414)
+#define HAINTMSK               (DWC_OTG_BASE + 0x418)
+
+/* Host Port Control and Status Registers */
+#define HPRT                   (DWC_OTG_BASE + 0x440)
+
+/* Host Channel-Specific Registers */
+#define HCCHAR(x)              (DWC_OTG_BASE + 0x500 + 0x20 * (x))
+#define HCSPLT(x)              (DWC_OTG_BASE + 0x504 + 0x20 * (x))
+#define HCINT(x)               (DWC_OTG_BASE + 0x508 + 0x20 * (x))
+#define HCINTMSK(x)            (DWC_OTG_BASE + 0x50C + 0x20 * (x))
+#define HCTSIZ(x)              (DWC_OTG_BASE + 0x510 + 0x20 * (x))
+#define HCDMA(x)               (DWC_OTG_BASE + 0x514 + 0x20 * (x))
+#define HCCHAR0                        (DWC_OTG_BASE + 0x500)
+#define HCSPLT0                        (DWC_OTG_BASE + 0x504)
+#define HCINT0                 (DWC_OTG_BASE + 0x508)
+#define HCINTMSK0              (DWC_OTG_BASE + 0x50C)
+#define HCTSIZ0                        (DWC_OTG_BASE + 0x510)
+#define HCDMA0                 (DWC_OTG_BASE + 0x514)
+#define HCCHAR1                        (DWC_OTG_BASE + 0x520)
+#define HCSPLT1                        (DWC_OTG_BASE + 0x524)
+#define HCINT1                 (DWC_OTG_BASE + 0x528)
+#define HCINTMSK1              (DWC_OTG_BASE + 0x52C)
+#define HCTSIZ1                        (DWC_OTG_BASE + 0x530)
+#define HCDMA1                 (DWC_OTG_BASE + 0x534)
+#define HCCHAR2                        (DWC_OTG_BASE + 0x540)
+#define HCSPLT2                        (DWC_OTG_BASE + 0x544)
+#define HCINT2                 (DWC_OTG_BASE + 0x548)
+#define HCINTMSK2              (DWC_OTG_BASE + 0x54C)
+#define HCTSIZ2                        (DWC_OTG_BASE + 0x550)
+#define HCDMA2                 (DWC_OTG_BASE + 0x554)
+#define HCCHAR3                        (DWC_OTG_BASE + 0x560)
+#define HCSPLT3                        (DWC_OTG_BASE + 0x564)
+#define HCINT3                 (DWC_OTG_BASE + 0x568)
+#define HCINTMSK3              (DWC_OTG_BASE + 0x56C)
+#define HCTSIZ3                (DWC_OTG_BASE + 0x570)
+#define HCDMA3                 (DWC_OTG_BASE + 0x574)
+#define HCCHAR4                (DWC_OTG_BASE + 0x580)
+#define HCSPLT4                (DWC_OTG_BASE + 0x584)
+#define HCINT4                 (DWC_OTG_BASE + 0x588)
+#define HCINTMSK4              (DWC_OTG_BASE + 0x58C)
+#define HCTSIZ4                (DWC_OTG_BASE + 0x590)
+#define HCDMA4                 (DWC_OTG_BASE + 0x594)
+#define HCCHAR5                (DWC_OTG_BASE + 0x5A0)
+#define HCSPLT5                (DWC_OTG_BASE + 0x5A4)
+#define HCINT5                 (DWC_OTG_BASE + 0x5A8)
+#define HCINTMSK5              (DWC_OTG_BASE + 0x5AC)
+#define HCTSIZ5                (DWC_OTG_BASE + 0x5B0)
+#define HCDMA5                 (DWC_OTG_BASE + 0x5B4)
+#define HCCHAR6                (DWC_OTG_BASE + 0x5C0)
+#define HCSPLT6                (DWC_OTG_BASE + 0x5C4)
+#define HCINT6                 (DWC_OTG_BASE + 0x5C8)
+#define HCINTMSK6              (DWC_OTG_BASE + 0x5CC)
+#define HCTSIZ6                (DWC_OTG_BASE + 0x5D0)
+#define HCDMA6                 (DWC_OTG_BASE + 0x5D4)
+#define HCCHAR7                (DWC_OTG_BASE + 0x5E0)
+#define HCSPLT7                (DWC_OTG_BASE + 0x5E4)
+#define HCINT7                 (DWC_OTG_BASE + 0x5E8)
+#define HCINTMSK7              (DWC_OTG_BASE + 0x5EC)
+#define HCTSIZ7                (DWC_OTG_BASE + 0x5F0)
+#define HCDMA7                 (DWC_OTG_BASE + 0x5F4)
+#define HCCHAR8                (DWC_OTG_BASE + 0x600)
+#define HCSPLT8                (DWC_OTG_BASE + 0x604)
+#define HCINT8                 (DWC_OTG_BASE + 0x608)
+#define HCINTMSK8              (DWC_OTG_BASE + 0x60C)
+#define HCTSIZ8                (DWC_OTG_BASE + 0x610)
+#define HCDMA8                 (DWC_OTG_BASE + 0x614)
+#define HCCHAR9                (DWC_OTG_BASE + 0x620)
+#define HCSPLT9                (DWC_OTG_BASE + 0x624)
+#define HCINT9                 (DWC_OTG_BASE + 0x628)
+#define HCINTMSK9              (DWC_OTG_BASE + 0x62C)
+#define HCTSIZ9                (DWC_OTG_BASE + 0x630)
+#define HCDMA9                 (DWC_OTG_BASE + 0x634)
+#define HCCHAR10               (DWC_OTG_BASE + 0x640)
+#define HCSPLT10               (DWC_OTG_BASE + 0x644)
+#define HCINT10                (DWC_OTG_BASE + 0x648)
+#define HCINTMSK10             (DWC_OTG_BASE + 0x64C)
+#define HCTSIZ10               (DWC_OTG_BASE + 0x650)
+#define HCDMA10                (DWC_OTG_BASE + 0x654)
+#define HCCHAR11               (DWC_OTG_BASE + 0x660)
+#define HCSPLT11               (DWC_OTG_BASE + 0x664)
+#define HCINT11                (DWC_OTG_BASE + 0x668)
+#define HCINTMSK11             (DWC_OTG_BASE + 0x66C)
+#define HCTSIZ11               (DWC_OTG_BASE + 0x670)
+#define HCDMA11                (DWC_OTG_BASE + 0x674)
+#define HCCHAR12               (DWC_OTG_BASE + 0x680)
+#define HCSPLT12               (DWC_OTG_BASE + 0x684)
+#define HCINT12                (DWC_OTG_BASE + 0x688)
+#define HCINTMSK12             (DWC_OTG_BASE + 0x68C)
+#define HCTSIZ12               (DWC_OTG_BASE + 0x690)
+#define HCDMA12                (DWC_OTG_BASE + 0x694)
+#define HCCHAR13               (DWC_OTG_BASE + 0x6A0)
+#define HCSPLT13               (DWC_OTG_BASE + 0x6A4)
+#define HCINT13                (DWC_OTG_BASE + 0x6A8)
+#define HCINTMSK13             (DWC_OTG_BASE + 0x6AC)
+#define HCTSIZ13               (DWC_OTG_BASE + 0x6B0)
+#define HCDMA13                (DWC_OTG_BASE + 0x6B4)
+#define HCCHAR14               (DWC_OTG_BASE + 0x6C0)
+#define HCSPLT14               (DWC_OTG_BASE + 0x6C4)
+#define HCINT14                (DWC_OTG_BASE + 0x6C8)
+#define HCINTMSK14             (DWC_OTG_BASE + 0x6CC)
+#define HCTSIZ14               (DWC_OTG_BASE + 0x6D0)
+#define HCDMA14                (DWC_OTG_BASE + 0x6D4)
+#define HCCHAR15               (DWC_OTG_BASE + 0x6E0)
+#define HCSPLT15               (DWC_OTG_BASE + 0x6E4)
+#define HCINT15                (DWC_OTG_BASE + 0x6E8)
+#define HCINTMSK15             (DWC_OTG_BASE + 0x6EC)
+#define HCTSIZ15               (DWC_OTG_BASE + 0x6F0)
+#define HCDMA15                (DWC_OTG_BASE + 0x6F4)
+
+/*** DEVICE MODE REGISTERS ***/
+/* Device Global Registers */
+#define DCFG                   (DWC_OTG_BASE + 0x800)
+#define DCFG_EPMISCNT_MASK             (0x1f << 18)
+#define DCFG_EPMISCNT_SHIFT            18
+#define DCFG_NZ_STS_OUT_HSHK           (1 << 2)
+
+#define DCTL                   (DWC_OTG_BASE + 0x804)
+#define DSTS                   (DWC_OTG_BASE + 0x808)
+#define DIEPMSK                (DWC_OTG_BASE + 0x810)
+#define DOEPMSK                (DWC_OTG_BASE + 0x814)
+#define DAINT                  (DWC_OTG_BASE + 0x818)
+#define DAINTMSK               (DWC_OTG_BASE + 0x81C)
+#define DAINT_OUTEP_SHIFT              16
+#define DAINT_OUTEP(_x)                        (1 << ((_x) + 16))
+#define DAINT_INEP(_x)                 (1 << (_x))
+
+#define DTKNQR1                (DWC_OTG_BASE + 0x820)
+#define DTKNQR2                (DWC_OTG_BASE + 0x824)
+#define DVBUSDIS               (DWC_OTG_BASE + 0x828)
+#define DVBUSPULSE             (DWC_OTG_BASE + 0x82C)
+#define DTHRCTL                (DWC_OTG_BASE + 0x830)
+
+/* Device Logical IN Endpoint-Specific Registers */
+#define DIEPCTL(x)             (DWC_OTG_BASE + 0x900 + 0x20 * (x))
+#define DIEPINT(x)             (DWC_OTG_BASE + 0x908 + 0x20 * (x))
+#define DIEPTSIZ(x)            (DWC_OTG_BASE + 0x910 + 0x20 * (x))
+#define DIEPDMA(x)             (DWC_OTG_BASE + 0x914 + 0x20 * (x))
+#define DTXFSTS(x)             (DWC_OTG_BASE + 0x918 + 0x20 * (x))
+
+#define DIEPCTL0               (DWC_OTG_BASE + 0x900)
+#define DIEPINT0               (DWC_OTG_BASE + 0x908)
+#define DIEPTSIZ0              (DWC_OTG_BASE + 0x910)
+#define DIEPDMA0               (DWC_OTG_BASE + 0x914)
+#define DIEPCTL1               (DWC_OTG_BASE + 0x920)
+#define DIEPINT1               (DWC_OTG_BASE + 0x928)
+#define DIEPTSIZ1              (DWC_OTG_BASE + 0x930)
+#define DIEPDMA1               (DWC_OTG_BASE + 0x934)
+#define DIEPCTL2               (DWC_OTG_BASE + 0x940)
+#define DIEPINT2               (DWC_OTG_BASE + 0x948)
+#define DIEPTSIZ2              (DWC_OTG_BASE + 0x950)
+#define DIEPDMA2               (DWC_OTG_BASE + 0x954)
+#define DIEPCTL3               (DWC_OTG_BASE + 0x960)
+#define DIEPINT3               (DWC_OTG_BASE + 0x968)
+#define DIEPTSIZ3              (DWC_OTG_BASE + 0x970)
+#define DIEPDMA3               (DWC_OTG_BASE + 0x974)
+#define DIEPCTL4               (DWC_OTG_BASE + 0x980)
+#define DIEPINT4               (DWC_OTG_BASE + 0x988)
+#define DIEPTSIZ4              (DWC_OTG_BASE + 0x990)
+#define DIEPDMA4               (DWC_OTG_BASE + 0x994)
+#define DIEPCTL5               (DWC_OTG_BASE + 0x9A0)
+#define DIEPINT5               (DWC_OTG_BASE + 0x9A8)
+#define DIEPTSIZ5              (DWC_OTG_BASE + 0x9B0)
+#define DIEPDMA5               (DWC_OTG_BASE + 0x9B4)
+#define DIEPCTL6               (DWC_OTG_BASE + 0x9C0)
+#define DIEPINT6               (DWC_OTG_BASE + 0x9C8)
+#define DIEPTSIZ6              (DWC_OTG_BASE + 0x9D0)
+#define DIEPDMA6               (DWC_OTG_BASE + 0x9D4)
+#define DIEPCTL7               (DWC_OTG_BASE + 0x9E0)
+#define DIEPINT7               (DWC_OTG_BASE + 0x9E8)
+#define DIEPTSIZ7              (DWC_OTG_BASE + 0x9F0)
+#define DIEPDMA7               (DWC_OTG_BASE + 0x9F4)
+#define DIEPCTL8               (DWC_OTG_BASE + 0xA00)
+#define DIEPINT8               (DWC_OTG_BASE + 0xA08)
+#define DIEPTSIZ8              (DWC_OTG_BASE + 0xA10)
+#define DIEPDMA8               (DWC_OTG_BASE + 0xA14)
+#define DIEPCTL9               (DWC_OTG_BASE + 0xA20)
+#define DIEPINT9               (DWC_OTG_BASE + 0xA28)
+#define DIEPTSIZ9              (DWC_OTG_BASE + 0xA30)
+#define DIEPDMA9               (DWC_OTG_BASE + 0xA34)
+#define DIEPCTL10              (DWC_OTG_BASE + 0xA40)
+#define DIEPINT10              (DWC_OTG_BASE + 0xA48)
+#define DIEPTSIZ10             (DWC_OTG_BASE + 0xA50)
+#define DIEPDMA10              (DWC_OTG_BASE + 0xA54)
+#define DIEPCTL11              (DWC_OTG_BASE + 0xA60)
+#define DIEPINT11              (DWC_OTG_BASE + 0xA68)
+#define DIEPTSIZ11             (DWC_OTG_BASE + 0xA70)
+#define DIEPDMA11              (DWC_OTG_BASE + 0xA74)
+#define DIEPCTL12              (DWC_OTG_BASE + 0xA80)
+#define DIEPINT12              (DWC_OTG_BASE + 0xA88)
+#define DIEPTSIZ12             (DWC_OTG_BASE + 0xA90)
+#define DIEPDMA12              (DWC_OTG_BASE + 0xA94)
+#define DIEPCTL13              (DWC_OTG_BASE + 0xAA0)
+#define DIEPINT13              (DWC_OTG_BASE + 0xAA8)
+#define DIEPTSIZ13             (DWC_OTG_BASE + 0xAB0)
+#define DIEPDMA13              (DWC_OTG_BASE + 0xAB4)
+#define DIEPCTL14              (DWC_OTG_BASE + 0xAC0)
+#define DIEPINT14              (DWC_OTG_BASE + 0xAC8)
+#define DIEPTSIZ14             (DWC_OTG_BASE + 0xAD0)
+#define DIEPDMA14              (DWC_OTG_BASE + 0xAD4)
+#define DIEPCTL15              (DWC_OTG_BASE + 0xAE0)
+#define DIEPINT15              (DWC_OTG_BASE + 0xAE8)
+#define DIEPTSIZ15             (DWC_OTG_BASE + 0xAF0)
+#define DIEPDMA15              (DWC_OTG_BASE + 0xAF4)
+
+/* Device Logical OUT Endpoint-Specific Registers */
+#define DOEPCTL(x)             (DWC_OTG_BASE + 0xB00 + 0x20 * (x))
+#define DXEPCTL_EPENA                  (1 << 31)
+#define DXEPCTL_EPDIS                  (1 << 30)
+#define DXEPCTL_SETD1PID               (1 << 29)
+#define DXEPCTL_SETODDFR               (1 << 29)
+#define DXEPCTL_SETD0PID               (1 << 28)
+#define DXEPCTL_SETEVENFR              (1 << 28)
+#define DXEPCTL_SNAK                   (1 << 27)
+#define DXEPCTL_CNAK                   (1 << 26)
+#define DXEPCTL_NAKSTS                 (1 << 17)
+#define DXEPCTL_DPID                   (1 << 16)
+#define DXEPCTL_EOFRNUM                        (1 << 16)
+#define DXEPCTL_USBACTEP               (1 << 15)
+#define DXEPCTL_NEXTEP_MASK            (0xf << 11)
+#define DXEPCTL_NEXTEP_SHIFT           11
+#define DXEPCTL_NEXTEP_LIMIT           0xf
+#define DXEPCTL_NEXTEP(_x)             ((_x) << 11)
+
+
+#define DOEPINT(x)             (DWC_OTG_BASE + 0xB08 + 0x20 * (x))
+#define DXEPINT_INEPNAKEFF              (1 << 6)
+#define DXEPINT_BACK2BACKSETUP          (1 << 6)
+#define DXEPINT_INTKNEPMIS              (1 << 5)
+#define DXEPINT_INTKNTXFEMP             (1 << 4)
+#define DXEPINT_OUTTKNEPDIS             (1 << 4)
+#define DXEPINT_TIMEOUT                 (1 << 3)
+#define DXEPINT_SETUP                   (1 << 3)
+#define DXEPINT_AHBERR                  (1 << 2)
+#define DXEPINT_EPDISBLD                (1 << 1)
+#define DXEPINT_XFERCOMPL               (1 << 0)
+
+#define DOEPTSIZ(x)            (DWC_OTG_BASE + 0xB10 + 0x20 * (x))
+#define DXEPTSIZ_MC_MASK               (0x3 << 29)
+#define DXEPTSIZ_MC_SHIFT              29
+#define DXEPTSIZ_MC_LIMIT              0x3
+#define DXEPTSIZ_MC(_x)                        ((_x) << 29)
+#define DXEPTSIZ_PKTCNT_MASK           (0x3ff << 19)
+#define DXEPTSIZ_PKTCNT_SHIFT          19
+#define DXEPTSIZ_PKTCNT_LIMIT          0x3ff
+#define DXEPTSIZ_PKTCNT_GET(_v)                (((_v) >> 19) & 0x3ff)
+#define DXEPTSIZ_PKTCNT(_x)            ((_x) << 19)
+#define DXEPTSIZ_XFERSIZE_MASK         (0x7ffff << 0)
+#define DXEPTSIZ_XFERSIZE_SHIFT                0
+#define DXEPTSIZ_XFERSIZE_LIMIT                0x7ffff
+#define DXEPTSIZ_XFERSIZE_GET(_v)      (((_v) >> 0) & 0x7ffff)
+#define DXEPTSIZ_XFERSIZE(_x)          ((_x) << 0)
+
+#define DOEPDMA(x)             (DWC_OTG_BASE + 0xB14 + 0x20 * (x))
+#define DOEPCTL0               (DWC_OTG_BASE + 0xB00)
+#define DOEPINT0               (DWC_OTG_BASE + 0xB08)
+#define DOEPTSIZ0              (DWC_OTG_BASE + 0xB10)
+#define DOEPTSIZ0_SUPCNT_MASK          (0x3 << 29)
+#define DOEPTSIZ0_SUPCNT_SHIFT         29
+#define DOEPTSIZ0_SUPCNT_LIMIT         0x3
+#define DOEPTSIZ0_SUPCNT(_x)           ((_x) << 29)
+#define DOEPTSIZ0_PKTCNT               (1 << 19)
+#define DOEPTSIZ0_XFERSIZE_MASK                (0x7f << 0)
+#define DOEPTSIZ0_XFERSIZE_SHIFT       0
+
+#define DOEPDMA0               (DWC_OTG_BASE + 0xB14)
+#define DOEPCTL1               (DWC_OTG_BASE + 0xB20)
+#define DOEPINT1               (DWC_OTG_BASE + 0xB28)
+#define DOEPTSIZ1              (DWC_OTG_BASE + 0xB30)
+#define DOEPDMA1               (DWC_OTG_BASE + 0xB34)
+#define DOEPCTL2               (DWC_OTG_BASE + 0xB40)
+#define DOEPINT2               (DWC_OTG_BASE + 0xB48)
+#define DOEPTSIZ2              (DWC_OTG_BASE + 0xB50)
+#define DOEPDMA2               (DWC_OTG_BASE + 0xB54)
+#define DOEPCTL3               (DWC_OTG_BASE + 0xB60)
+#define DOEPINT3               (DWC_OTG_BASE + 0xB68)
+#define DOEPTSIZ3              (DWC_OTG_BASE + 0xB70)
+#define DOEPDMA3               (DWC_OTG_BASE + 0xB74)
+#define DOEPCTL4               (DWC_OTG_BASE + 0xB80)
+#define DOEPINT4               (DWC_OTG_BASE + 0xB88)
+#define DOEPTSIZ4              (DWC_OTG_BASE + 0xB90)
+#define DOEPDMA4               (DWC_OTG_BASE + 0xB94)
+#define DOEPCTL5               (DWC_OTG_BASE + 0xBA0)
+#define DOEPINT5               (DWC_OTG_BASE + 0xBA8)
+#define DOEPTSIZ5              (DWC_OTG_BASE + 0xBB0)
+#define DOEPDMA5               (DWC_OTG_BASE + 0xBB4)
+#define DOEPCTL6               (DWC_OTG_BASE + 0xBC0)
+#define DOEPINT6               (DWC_OTG_BASE + 0xBC8)
+#define DOEPTSIZ6              (DWC_OTG_BASE + 0xBD0)
+#define DOEPDMA6               (DWC_OTG_BASE + 0xBD4)
+#define DOEPCTL7               (DWC_OTG_BASE + 0xBE0)
+#define DOEPINT7               (DWC_OTG_BASE + 0xBE8)
+#define DOEPTSIZ7              (DWC_OTG_BASE + 0xBF0)
+#define DOEPDMA7               (DWC_OTG_BASE + 0xBF4)
+#define DOEPCTL8               (DWC_OTG_BASE + 0xC00)
+#define DOEPINT8               (DWC_OTG_BASE + 0xC08)
+#define DOEPTSIZ8              (DWC_OTG_BASE + 0xC10)
+#define DOEPDMA8               (DWC_OTG_BASE + 0xC14)
+#define DOEPCTL9               (DWC_OTG_BASE + 0xC20)
+#define DOEPINT9               (DWC_OTG_BASE + 0xC28)
+#define DOEPTSIZ9              (DWC_OTG_BASE + 0xC30)
+#define DOEPDMA9               (DWC_OTG_BASE + 0xC34)
+#define DOEPCTL10              (DWC_OTG_BASE + 0xC40)
+#define DOEPINT10              (DWC_OTG_BASE + 0xC48)
+#define DOEPTSIZ10             (DWC_OTG_BASE + 0xC50)
+#define DOEPDMA10              (DWC_OTG_BASE + 0xC54)
+#define DOEPCTL11              (DWC_OTG_BASE + 0xC60)
+#define DOEPINT11              (DWC_OTG_BASE + 0xC68)
+#define DOEPTSIZ11             (DWC_OTG_BASE + 0xC70)
+#define DOEPDMA11              (DWC_OTG_BASE + 0xC74)
+#define DOEPCTL12              (DWC_OTG_BASE + 0xC80)
+#define DOEPINT12              (DWC_OTG_BASE + 0xC88)
+#define DOEPTSIZ12             (DWC_OTG_BASE + 0xC90)
+#define DOEPDMA12              (DWC_OTG_BASE + 0xC94)
+#define DOEPCTL13              (DWC_OTG_BASE + 0xCA0)
+#define DOEPINT13              (DWC_OTG_BASE + 0xCA8)
+#define DOEPTSIZ13             (DWC_OTG_BASE + 0xCB0)
+#define DOEPDMA13              (DWC_OTG_BASE + 0xCB4)
+#define DOEPCTL14              (DWC_OTG_BASE + 0xCC0)
+#define DOEPINT14              (DWC_OTG_BASE + 0xCC8)
+#define DOEPTSIZ14             (DWC_OTG_BASE + 0xCD0)
+#define DOEPDMA14              (DWC_OTG_BASE + 0xCD4)
+#define DOEPCTL15              (DWC_OTG_BASE + 0xCE0)
+#define DOEPINT15              (DWC_OTG_BASE + 0xCE8)
+#define DOEPTSIZ15             (DWC_OTG_BASE + 0xCF0)
+#define DOEPDMA15              (DWC_OTG_BASE + 0xCF4)
+
+/* Power and Clock Gating Register */
+#define PCGCCTL                        (DWC_OTG_BASE + 0xE00)
+
+#define EP0FIFO                        (DWC_OTG_BASE + 0x1000)
+
+#define PERI_CTRL16_PICOPHY_SIDDQ_BIT          (1<<0)
+#define PERI_CTRL16_PICOPHY_TXPREEMPHASISTUNE  (1<<31)
+#define PERI_CTRL15_HSICPHY_SIDDQ_BIT          (1<<16)
+#define PERI_CTRL14_NANOPHY_SIDDQ_BIT          (1<<0)
+#define PERI_CTRL0_USB2DVC_NANOPHY_BIT         (1<<7)
+#define NANOPHY_DMPULLDOWN    (1 << 6)    /* bit[6]:nanophy_dmpulldown;为1'b0 */
+#define NANOPHY_DPPULLDOWN    (1 << 5)    /* bit[5]:nanophy_dppulldown;为1'b0 */
+
+#define EN_LDO4_INT (1 << 4)
+#define EN_LDO8_INT (1 << 4)
+
+/* SCPEREN1/DIS1 */
+#define GT_CLK_USBHSICPHY480            (1<<26)
+#define GT_CLK_USBHSICPHY               (1<<25)
+#define GT_CLK_USBPICOPHY               (1<<24)
+#define GT_CLK_USBNANOPHY               (1<<23)
+/* SCPEREN3/DIS3 */
+#define GT_CLK_USB2HST                  (1<<18)
+#define GT_CLK_USB2DVC                  (1<<17)
+/* SCPERRSTEN3 */
+#define IP_RST_PICOPHY_POR              (1<<31)
+#define IP_RST_HSICPHY_POR              (1<<30)
+#define IP_RST_NANOPHY_POR              (1<<29)
+#define IP_RST_USB2DVC_PHY              (1<<28)
+#define IP_RST_USB2H_UTMI1              (1<<21)
+#define IP_RST_USB2H_UTMI0              (1<<20)
+#define IP_RST_USB2H_PHY                (1<<19)
+#define IP_RST_USB2HST                  (1<<18)
+#define IP_RST_USB2DVC                  (1<<17)
+/* SCPERRSTEN1 */
+#define IP_RST_HSICPHY                  (1<<25)
+#define IP_RST_PICOPHY                  (1<<24)
+#define IP_RST_NANOPHY                  (1<<23)
+
+/*
+ * USB directions
+ *
+ * This bit flag is used in endpoint descriptors' bEndpointAddress field.
+ * It's also one of three fields in control requests bRequestType.
+ */
+#define USB_DIR_OUT                     0               /* to device */
+#define USB_DIR_IN                      0x80            /* to host */
+
+/*
+ * Descriptor types ... USB 2.0 spec table 9.5
+ */
+#define USB_DT_DEVICE                   0x01
+#define USB_DT_CONFIG                   0x02
+#define USB_DT_STRING                   0x03
+#define USB_DT_INTERFACE                0x04
+#define USB_DT_ENDPOINT                 0x05
+#define USB_DT_DEVICE_QUALIFIER         0x06
+#define USB_DT_OTHER_SPEED_CONFIG       0x07
+#define USB_DT_INTERFACE_POWER          0x08
+/* these are from a minor usb 2.0 revision (ECN) */
+#define USB_DT_OTG                      0x09
+#define USB_DT_DEBUG                    0x0a
+#define USB_DT_INTERFACE_ASSOCIATION    0x0b
+/* these are from the Wireless USB spec */
+#define USB_DT_SECURITY                 0x0c
+#define USB_DT_KEY                      0x0d
+#define USB_DT_ENCRYPTION_TYPE          0x0e
+#define USB_DT_BOS                      0x0f
+#define USB_DT_DEVICE_CAPABILITY        0x10
+#define USB_DT_WIRELESS_ENDPOINT_COMP   0x11
+#define USB_DT_WIRE_ADAPTER             0x21
+#define USB_DT_RPIPE                    0x22
+#define USB_DT_CS_RADIO_CONTROL         0x23
+
+/*
+ * USB recipients, the third of three bRequestType fields
+ */
+#define USB_RECIP_MASK                  0x1f
+#define USB_RECIP_DEVICE                0x00
+#define USB_RECIP_INTERFACE             0x01
+#define USB_RECIP_ENDPOINT              0x02
+#define USB_RECIP_OTHER                 0x03
+
+/* IN/OUT will STALL */
+#define USB_ENDPOINT_HALT                              0
+
+/*
+ * Endpoints
+ */
+#define USB_ENDPOINT_NUMBER_MASK        0x0f    /* in bEndpointAddress */
+#define USB_ENDPOINT_DIR_MASK           0x80
+
+#define USB_ENDPOINT_XFERTYPE_MASK      0x03    /* in bmAttributes */
+#define USB_ENDPOINT_XFER_CONTROL       0
+#define USB_ENDPOINT_XFER_ISOC          1
+#define USB_ENDPOINT_XFER_BULK          2
+#define USB_ENDPOINT_XFER_INT           3
+#define USB_ENDPOINT_MAX_ADJUSTABLE     0x80
+
+/*
+ * Standard requests, for the bRequest field of a SETUP packet.
+ *
+ * These are qualified by the bRequestType field, so that for example
+ * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
+ * by a GET_STATUS request.
+ */
+#define USB_REQ_GET_STATUS              0x00
+#define USB_REQ_CLEAR_FEATURE           0x01
+#define USB_REQ_SET_FEATURE             0x03
+#define USB_REQ_SET_ADDRESS             0x05
+#define USB_REQ_GET_DESCRIPTOR          0x06
+#define USB_REQ_SET_DESCRIPTOR          0x07
+#define USB_REQ_GET_CONFIGURATION       0x08
+#define USB_REQ_SET_CONFIGURATION       0x09
+#define USB_REQ_GET_INTERFACE           0x0A
+#define USB_REQ_SET_INTERFACE           0x0B
+#define USB_REQ_SYNCH_FRAME             0x0C
+
+/* USB_DT_DEVICE: Device descriptor */
+struct usb_device_descriptor {
+        unsigned char  bLength;
+        unsigned char  bDescriptorType;
+
+        unsigned short bcdUSB;
+        unsigned char  bDeviceClass;
+        unsigned char  bDeviceSubClass;
+        unsigned char  bDeviceProtocol;
+        unsigned char  bMaxPacketSize0;
+        unsigned short idVendor;
+        unsigned short idProduct;
+        unsigned short bcdDevice;
+        unsigned char  iManufacturer;
+        unsigned char  iProduct;
+        unsigned char  iSerialNumber;
+        unsigned char  bNumConfigurations;
+} __attribute__ ((packed));
+
+#define USB_DT_DEVICE_SIZE              18
+
+/*
+ * Device and/or Interface Class codes
+ * as found in bDeviceClass or bInterfaceClass
+ * and defined by www.usb.org documents
+ */
+#define USB_CLASS_PER_INTERFACE         0       /* for DeviceClass */
+#define USB_CLASS_AUDIO                 1
+#define USB_CLASS_COMM                  2
+#define USB_CLASS_HID                   3
+#define USB_CLASS_PHYSICAL              5
+#define USB_CLASS_STILL_IMAGE           6
+#define USB_CLASS_PRINTER               7
+#define USB_CLASS_MASS_STORAGE          8
+#define USB_CLASS_HUB                   9
+#define USB_CLASS_CDC_DATA              0x0a
+#define USB_CLASS_CSCID                 0x0b    /* chip+ smart card */
+#define USB_CLASS_CONTENT_SEC           0x0d    /* content security */
+#define USB_CLASS_VIDEO                 0x0e
+#define USB_CLASS_WIRELESS_CONTROLLER   0xe0
+#define USB_CLASS_MISC                  0xef
+#define USB_CLASS_APP_SPEC              0xfe
+#define USB_CLASS_VENDOR_SPEC           0xff
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_CONFIG: Configuration descriptor information.
+ *
+ * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
+ * descriptor type is different.  Highspeed-capable devices can look
+ * different depending on what speed they're currently running.  Only
+ * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
+ * descriptors.
+ */
+struct usb_config_descriptor {
+       unsigned char  bLength;
+       unsigned char  bDescriptorType;
+
+       unsigned short wTotalLength;
+       unsigned char  bNumInterfaces;
+       unsigned char  bConfigurationValue;
+       unsigned char  iConfiguration;
+       unsigned char  bmAttributes;
+       unsigned char  bMaxPower;
+} __attribute__((packed));
+
+#define USB_DT_CONFIG_SIZE              9
+
+/* from config descriptor bmAttributes */
+#define USB_CONFIG_ATT_ONE              (1 << 7)        /* must be set */
+#define USB_CONFIG_ATT_SELFPOWER        (1 << 6)        /* self powered */
+#define USB_CONFIG_ATT_WAKEUP           (1 << 5)        /* can wakeup */
+#define USB_CONFIG_ATT_BATTERY          (1 << 4)        /* battery powered */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_STRING: String descriptor */
+struct usb_string_descriptor {
+        unsigned char  bLength;
+        unsigned char  bDescriptorType;
+
+        unsigned short wString[16];             /* UTF-16LE encoded */
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+/* USB_DT_INTERFACE: Interface descriptor */
+struct usb_interface_descriptor {
+        unsigned char  bLength;
+        unsigned char  bDescriptorType;
+
+        unsigned char  bInterfaceNumber;
+        unsigned char  bAlternateSetting;
+        unsigned char  bNumEndpoints;
+        unsigned char  bInterfaceClass;
+        unsigned char  bInterfaceSubClass;
+        unsigned char  bInterfaceProtocol;
+        unsigned char  iInterface;
+};
+
+#define USB_DT_INTERFACE_SIZE           9
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_ENDPOINT: Endpoint descriptor */
+struct usb_endpoint_descriptor {
+        unsigned char  bLength;
+        unsigned char  bDescriptorType;
+
+        unsigned char  bEndpointAddress;
+        unsigned char  bmAttributes;
+        unsigned short wMaxPacketSize;
+        unsigned char  bInterval;
+} __attribute__ ((packed));
+
+#define USB_DT_ENDPOINT_SIZE            7
+#define USB_DT_ENDPOINT_AUDIO_SIZE      9       /* Audio extension */
+
+extern int usb_need_reset;
+
+/**
+ * This union represents the bit fields in the DMA Descriptor
+ * status quadlet. Read the quadlet into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
+ * <i>b_iso_in</i> elements.
+ */
+typedef union dev_dma_desc_sts {
+               /** raw register data */
+       unsigned int d32;
+               /** quadlet bits */
+       struct {
+               /** Received number of bytes */
+               unsigned bytes:16;
+               /** NAK bit - only for OUT EPs */
+               unsigned nak:1;
+               unsigned reserved17_22:6;
+               /** Multiple Transfer - only for OUT EPs */
+               unsigned mtrf:1;
+               /** Setup Packet received - only for OUT EPs */
+               unsigned sr:1;
+               /** Interrupt On Complete */
+               unsigned ioc:1;
+               /** Short Packet */
+               unsigned sp:1;
+               /** Last */
+               unsigned l:1;
+               /** Receive Status */
+               unsigned sts:2;
+               /** Buffer Status */
+               unsigned bs:2;
+       } b;
+
+//#ifdef DWC_EN_ISOC
+               /** iso out quadlet bits */
+       struct {
+               /** Received number of bytes */
+               unsigned rxbytes:11;
+
+               unsigned reserved11:1;
+               /** Frame Number */
+               unsigned framenum:11;
+               /** Received ISO Data PID */
+               unsigned pid:2;
+               /** Interrupt On Complete */
+               unsigned ioc:1;
+               /** Short Packet */
+               unsigned sp:1;
+               /** Last */
+               unsigned l:1;
+               /** Receive Status */
+               unsigned rxsts:2;
+               /** Buffer Status */
+               unsigned bs:2;
+       } b_iso_out;
+
+               /** iso in quadlet bits */
+       struct {
+               /** Transmited number of bytes */
+               unsigned txbytes:12;
+               /** Frame Number */
+               unsigned framenum:11;
+               /** Transmited ISO Data PID */
+               unsigned pid:2;
+               /** Interrupt On Complete */
+               unsigned ioc:1;
+               /** Short Packet */
+               unsigned sp:1;
+               /** Last */
+               unsigned l:1;
+               /** Transmit Status */
+               unsigned txsts:2;
+               /** Buffer Status */
+               unsigned bs:2;
+       } b_iso_in;
+//#endif                                /* DWC_EN_ISOC */
+} dev_dma_desc_sts_t;
+
+/**
+ * DMA Descriptor structure
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+typedef struct dwc_otg_dev_dma_desc {
+       /** DMA Descriptor status quadlet */
+       dev_dma_desc_sts_t status;
+       /** DMA Descriptor data buffer pointer */
+       unsigned int buf;
+} dwc_otg_dev_dma_desc_t;
+
+extern void usb_reinit(void);
+
+#endif /* __DWC_USB_H__*/
diff --git a/plat/hikey/partitions.c b/plat/hikey/partitions.c
new file mode 100644 (file)
index 0000000..e4d303c
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <dw_mmc.h>
+#include <errno.h>
+#include <io_storage.h>
+#include <mmio.h>
+#include <partitions.h>
+#include <platform_def.h>
+#include <string.h>
+#include "hikey_private.h"
+
+#define EFI_ENTRIES            128
+#define EFI_ENTRY_SIZE         (sizeof(struct efi_entry))
+#define EFI_MBR_SIZE           512
+#define EFI_HEADER_SIZE                512
+#define EFI_TOTAL_SIZE         (EFI_MBR_SIZE + EFI_HEADER_SIZE +       \
+                               EFI_ENTRY_SIZE * EFI_ENTRIES)
+
+struct efi_header {
+       char            signature[8];
+       uint32_t        revision;
+       uint32_t        size;
+       uint32_t        header_crc;
+       uint32_t        reserved;
+       uint64_t        current_lba;
+       uint64_t        backup_lba;
+       uint64_t        first_lba;
+       uint64_t        last_lba;
+       uint8_t         disk_uuid[16];
+       /* starting LBA of array of partition entries */
+       uint64_t        part_lba;
+       /* number of partition entries in array */
+       uint32_t        part_num;
+       /* size of a single partition entry (usually 128) */
+       uint32_t        part_size;
+       uint32_t        part_crc;
+};
+
+struct efi_entry {
+       uint8_t         type_uuid[16];
+       uint8_t         uniq_uuid[16];
+       uint64_t        first_lba;
+       uint64_t        last_lba;
+       uint64_t        attr;
+       uint16_t        name[EFI_NAMELEN];
+};
+
+/* the first entry is dummy for ptable (covers both primary & secondary) */
+static struct ptentry ptable[EFI_ENTRIES + 1];
+static int entries;    /* partition entry entries */
+
+static void dump_entries(void)
+{
+       int i;
+
+       VERBOSE("Partition table with %d entries:\n", entries);
+       for (i = 0; i < entries; i++) {
+               VERBOSE("%s %llx-%llx\n", ptable[i].name,
+                       ptable[i].start,
+                       ptable[i].start + ptable[i].length - 4);
+       }
+}
+
+static int convert_ascii_string(uint16_t *str_in, uint8_t *str_out)
+{
+       uint8_t *name = (uint8_t *)str_in;
+       int i;
+
+       if (name[0] == '\0' || !str_in || !str_out)
+               return -EINVAL;
+       for (i = 1; i < (EFI_NAMELEN << 1); i += 2) {
+               if (name[i] != '\0')
+                       return -EINVAL;
+       }
+       for (i = 0; i < (EFI_NAMELEN << 1); i += 2) {
+               str_out[i >> 1] = name[i];
+               if (name[i] == '\0')
+                       break;
+       }
+       return 0;
+}
+
+static int parse_entry(uintptr_t buf)
+{
+       struct efi_entry *entry = (struct efi_entry *)buf;
+       int ret;
+
+       /* exhaused partition entry */
+       if ((entry->first_lba == 0) && (entry->last_lba == 0))
+               return 1;
+       ret = convert_ascii_string(entry->name, (uint8_t *)ptable[entries].name);
+       if (ret < 0)
+               return ret;
+       ptable[entries].start = (uint64_t)entry->first_lba * 512;
+       ptable[entries].length = (uint64_t)(entry->last_lba - entry->first_lba + 1) * 512;
+       entries++;
+       return 0;
+}
+
+/* create dummy entry for ptable */
+static void create_dummy_entry(void)
+{
+       int bytes;
+       ptable[entries].start = 0;
+       ptable[entries].length = 0;
+       bytes = sprintf(ptable[entries].name, "ptable");
+       ptable[entries].name[bytes] = '\0';
+       entries++;
+}
+
+struct ptentry *find_ptn(const char *str)
+{
+       struct ptentry *ptn = NULL;
+       int i;
+
+       for (i = 0; i < entries; i++) {
+               if (!strcmp(ptable[i].name, str)) {
+                       ptn = &ptable[i];
+                       break;
+               }
+       }
+       return ptn;
+}
+
+int get_partition(void)
+{
+       int result = IO_FAIL;
+       int i, ret, num_entries;
+       size_t bytes_read;
+       uintptr_t emmc_dev_handle, spec, img_handle;
+       unsigned int buf[MMC_BLOCK_SIZE >> 2];
+       struct efi_header *hd = NULL;
+
+       create_dummy_entry();
+       result = plat_get_image_source(NORMAL_EMMC_NAME, &emmc_dev_handle,
+                                      &spec);
+       if (result) {
+               WARN("failed to open eMMC normal partition\n");
+               return result;
+       }
+       result = io_open(emmc_dev_handle, spec, &img_handle);
+       if (result != IO_SUCCESS) {
+               WARN("Failed to open eMMC device\n");
+               return result;
+       }
+       result = io_seek(img_handle, IO_SEEK_SET, 0);
+       if (result)
+               goto exit;
+       result = io_read(img_handle, (uintptr_t)buf, EFI_MBR_SIZE,
+                        &bytes_read);
+       if ((result != IO_SUCCESS) || (bytes_read < EFI_MBR_SIZE)) {
+               WARN("Failed to read eMMC (%i)\n", result);
+               goto exit;
+       }
+       /* check the magic number in last word */
+       if (buf[(MMC_BLOCK_SIZE >> 2) - 1] != 0xaa550000) {
+               WARN("Can't find MBR protection information\n");
+               goto exit;
+       }
+
+       result = io_read(img_handle, (uintptr_t)buf, EFI_HEADER_SIZE,
+                        &bytes_read);
+       if ((result != IO_SUCCESS) || (bytes_read < EFI_HEADER_SIZE)) {
+               WARN("Failed to read eMMC (%i)\n", result);
+               goto exit;
+       }
+       hd = (struct efi_header *)((uintptr_t)buf);
+       if (strncmp(hd->signature, "EFI PART", 8)) {
+               WARN("Failed to find partition table\n");
+               goto exit;
+       }
+       num_entries = hd->part_num;
+       for (i = 0; i < num_entries; i++) {
+               result = io_read(img_handle, (uintptr_t)buf, EFI_HEADER_SIZE,
+                                &bytes_read);
+               if ((result != IO_SUCCESS) || (bytes_read < EFI_HEADER_SIZE)) {
+                       WARN("Failed to read eMMC (%i)\n", result);
+                       goto exit;
+               }
+               /* each header contains four partition entries */
+               ret = parse_entry((uintptr_t)buf);
+               if (ret)
+                       break;
+               ret = parse_entry((uintptr_t)buf + EFI_ENTRY_SIZE);
+               if (ret)
+                       break;
+               ret = parse_entry((uintptr_t)buf + EFI_ENTRY_SIZE * 2);
+               if (ret)
+                       break;
+               ret = parse_entry((uintptr_t)buf + EFI_ENTRY_SIZE * 3);
+               if (ret)
+                       break;
+       }
+exit:
+       io_close(img_handle);
+       update_fip_spec();
+       dump_entries();
+       return result;
+}
diff --git a/plat/hikey/plat_io_storage.c b/plat/hikey/plat_io_storage.c
new file mode 100644 (file)
index 0000000..6158710
--- /dev/null
@@ -0,0 +1,694 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <dw_mmc.h>
+#include <fastboot.h>
+#include <io_block.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <mmio.h>
+#include <partitions.h>
+#include <platform_def.h>
+#include <semihosting.h>       /* For FOPEN_MODE_... */
+#include <string.h>
+#include "hikey_private.h"
+
+#define LOADER_MAX_ENTRIES             2
+#define PTABLE_MAX_ENTRIES             3
+#define USER_MAX_ENTRIES               2
+
+#define FLUSH_BASE                     (DDR_BASE + 0x100000)
+
+struct entry_head {
+       unsigned char   magic[8];
+       unsigned char   name[8];
+       unsigned int    start;  /* lba */
+       unsigned int    count;  /* lba */
+       unsigned int    flag;
+};
+
+static const io_dev_connector_t *bl1_mem_dev_con;
+static uintptr_t bl1_mem_dev_spec;
+static uintptr_t loader_mem_dev_handle;
+static uintptr_t bl1_mem_init_params;
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_spec;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *dw_mmc_dev_con;
+static struct block_ops dw_mmc_ops;
+static uintptr_t emmc_dev_handle;
+
+#define SPARSE_FILL_BUFFER_ADDRESS     0x18000000
+#define SPARSE_FILL_BUFFER_SIZE                0x08000000
+
+/* Page 1024, since only a few pages before 2048 are used as partition table */
+#define SERIALNO_OFFSET                        (1024 * 512)
+
+static const io_block_spec_t loader_mem_spec = {
+       /* l-loader.bin that contains bl1.bin */
+       .offset = LOADER_RAM_BASE,
+       .length = BL1_RO_LIMIT - LOADER_RAM_BASE,
+};
+
+static const io_block_spec_t boot_emmc_spec = {
+       .offset = MMC_LOADER_BASE,
+       .length = BL1_RO_LIMIT - LOADER_RAM_BASE,
+};
+
+static const io_block_spec_t normal_emmc_spec = {
+       .offset = MMC_BASE,
+       .length = MMC_SIZE,
+};
+
+static io_block_spec_t fip_block_spec = {
+       .offset = 0,
+       .length = 0,
+};
+
+static const io_file_spec_t bl2_file_spec = {
+       .path = BL2_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_file_spec = {
+       .path = BL30_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_file_spec = {
+       .path = BL31_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_file_spec = {
+       .path = BL32_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_file_spec = {
+       .path = BL33_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static int open_loader_mem(const uintptr_t spec);
+static int open_fip(const uintptr_t spec);
+static int open_dw_mmc(const uintptr_t spec);
+static int open_dw_mmc_boot(const uintptr_t spec);
+
+struct plat_io_policy {
+       const char      *image_name;
+       uintptr_t       *dev_handle;
+       uintptr_t       image_spec;
+       int             (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+       {
+               LOADER_MEM_NAME,
+               &loader_mem_dev_handle,
+               (uintptr_t)&loader_mem_spec,
+               open_loader_mem
+       }, {
+               BOOT_EMMC_NAME,
+               &emmc_dev_handle,
+               (uintptr_t)&boot_emmc_spec,
+               open_dw_mmc_boot
+       }, {
+               NORMAL_EMMC_NAME,
+               &emmc_dev_handle,
+               (uintptr_t)&normal_emmc_spec,
+               open_dw_mmc
+       }, {
+               FIP_IMAGE_NAME,
+               &emmc_dev_handle,
+               (uintptr_t)&fip_block_spec,
+               open_dw_mmc
+       }, {
+               BL2_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl2_file_spec,
+               open_fip
+       }, {
+               BL30_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl30_file_spec,
+               open_fip
+       }, {
+               BL31_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl31_file_spec,
+               open_fip
+       }, {
+               BL32_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl32_file_spec,
+               open_fip
+       }, {
+               BL33_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl33_file_spec,
+               open_fip
+       }, {
+               0, 0, 0, 0
+       }
+};
+
+static int open_loader_mem(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+       uintptr_t image_handle;
+
+       result = io_dev_init(loader_mem_dev_handle, bl1_mem_init_params);
+       if (result == IO_SUCCESS) {
+               result = io_open(loader_mem_dev_handle, spec, &image_handle);
+               if (result == IO_SUCCESS) {
+                       io_close(image_handle);
+               }
+       }
+       return result;
+}
+
+static int open_fip(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+
+       /* See if a Firmware Image Package is available */
+       result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_NAME);
+       if (result == IO_SUCCESS) {
+               INFO("Using FIP\n");
+               /*TODO: Check image defined in spec is present in FIP. */
+       }
+       return result;
+}
+
+
+static int open_dw_mmc(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+       uintptr_t image_handle;
+
+       /* indicate to select normal partition in eMMC */
+       result = io_dev_init(emmc_dev_handle, 0);
+       if (result == IO_SUCCESS) {
+               result = io_open(emmc_dev_handle, spec, &image_handle);
+               if (result == IO_SUCCESS) {
+                       /* INFO("Using DW MMC IO\n"); */
+                       io_close(image_handle);
+               }
+       }
+       return result;
+}
+
+static int open_dw_mmc_boot(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+       uintptr_t image_handle;
+
+       /* indicate to select boot partition in eMMC */
+       result = io_dev_init(emmc_dev_handle, 1);
+       if (result == IO_SUCCESS) {
+               result = io_open(emmc_dev_handle, spec, &image_handle);
+               if (result == IO_SUCCESS) {
+                       /* INFO("Using DW MMC IO\n"); */
+                       io_close(image_handle);
+               }
+       }
+       return result;
+}
+
+void io_setup(void)
+{
+       int io_result = IO_FAIL;
+
+       /* Register the IO devices on this platform */
+       io_result = register_io_dev_fip(&fip_dev_con);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = register_io_dev_block(&dw_mmc_dev_con);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = register_io_dev_memmap(&bl1_mem_dev_con);
+       assert(io_result == IO_SUCCESS);
+
+       /* Open connections to devices and cache the handles */
+       io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle);
+       assert(io_result == IO_SUCCESS);
+
+       dw_mmc_ops.init = init_mmc;
+       dw_mmc_ops.read = mmc0_read;
+       dw_mmc_ops.write = mmc0_write;
+       io_result = io_dev_open(dw_mmc_dev_con, (uintptr_t)&dw_mmc_ops,
+                               &emmc_dev_handle);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = io_dev_open(bl1_mem_dev_con, bl1_mem_dev_spec,
+                               &loader_mem_dev_handle);
+       assert(io_result == IO_SUCCESS);
+
+       /* Ignore improbable errors in release builds */
+       (void)io_result;
+}
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy */
+int plat_get_image_source(const char *image_name, uintptr_t *dev_handle,
+                         uintptr_t *image_spec)
+{
+       int result = IO_FAIL;
+       const struct plat_io_policy *policy;
+
+       if ((image_name != NULL) && (dev_handle != NULL) &&
+           (image_spec != NULL)) {
+               policy = policies;
+               while (policy->image_name != NULL) {
+                       if (strcmp(policy->image_name, image_name) == 0) {
+                               result = policy->check(policy->image_spec);
+                               if (result == IO_SUCCESS) {
+                                       *image_spec = policy->image_spec;
+                                       *dev_handle = *(policy->dev_handle);
+                                       break;
+                               }
+                       }
+                       policy++;
+               }
+       } else {
+               result = IO_FAIL;
+       }
+       return result;
+}
+
+int update_fip_spec(void)
+{
+       struct ptentry *ptn;
+
+       ptn = find_ptn("fastboot");
+       if (!ptn) {
+               WARN("failed to find partition fastboot\n");
+               ptn = find_ptn("bios");
+               if (!ptn) {
+                       WARN("failed to find partition bios\n");
+                       return IO_FAIL;
+               }
+       }
+       VERBOSE("%s: name:%s, start:%llx, length:%llx\n",
+               __func__, ptn->name, ptn->start, ptn->length);
+       fip_block_spec.offset = ptn->start;
+       fip_block_spec.length = ptn->length;
+       return IO_SUCCESS;
+}
+
+static int fetch_entry_head(void *buf, int num, struct entry_head *hd)
+{
+       unsigned char magic[8] = "ENTRYHDR";
+       if (hd == NULL)
+               return IO_FAIL;
+       memcpy((void *)hd, buf, sizeof(struct entry_head) * num);
+       if (!strncmp((void *)hd->magic, (void *)magic, 8))
+               return IO_SUCCESS;
+       return IO_NOT_SUPPORTED;
+}
+
+static int flush_loader(void)
+{
+       struct entry_head entries[5];
+       uintptr_t img_handle, spec;
+       int result = IO_FAIL;
+       size_t bytes_read, length;
+       ssize_t offset;
+       int i, fp;
+
+       result = fetch_entry_head((void *)(FLUSH_BASE + 28),
+                                 LOADER_MAX_ENTRIES, entries);
+       if (result) {
+               WARN("failed to parse entries in loader image\n");
+               return result;
+       }
+
+       spec = 0;
+       for (i = 0, fp = 0; i < LOADER_MAX_ENTRIES; i++) {
+               if (entries[i].flag != 1) {
+                       WARN("Invalid flag in entry:0x%x\n", entries[i].flag);
+                       return IO_NOT_SUPPORTED;
+               }
+               result = plat_get_image_source(BOOT_EMMC_NAME, &emmc_dev_handle,
+                                              &spec);
+               if (result) {
+                       WARN("failed to open emmc boot area\n");
+                       return result;
+               }
+               /* offset in Boot Area1 */
+               offset = MMC_LOADER_BASE + entries[i].start * 512;
+
+               result = io_open(emmc_dev_handle, spec, &img_handle);
+               if (result != IO_SUCCESS) {
+                       WARN("Failed to open memmap device\n");
+                       return result;
+               }
+               length = entries[i].count * 512;
+
+               result = io_seek(img_handle, IO_SEEK_SET, offset);
+               if (result)
+                       goto exit;
+
+               if (i == 1)
+                       fp = (entries[1].start - entries[0].start) * 512;
+               result = io_write(img_handle, FLUSH_BASE + fp, length,
+                                 &bytes_read);
+               if ((result != IO_SUCCESS) || (bytes_read < length)) {
+                       WARN("Failed to write '%s' file (%i)\n",
+                            LOADER_MEM_NAME, result);
+                       goto exit;
+               }
+               io_close(img_handle);
+       }
+       return result;
+exit:
+       io_close(img_handle);
+       return result;
+}
+
+/*
+ * Flush l-loader.bin (loader & bl1.bin) into Boot Area1 of eMMC.
+ */
+int flush_loader_image(void)
+{
+       uintptr_t bl1_image_spec;
+       int result = IO_FAIL;
+       size_t bytes_read, length;
+       uintptr_t img_handle;
+
+       result = plat_get_image_source(LOADER_MEM_NAME, &loader_mem_dev_handle,
+                                      &bl1_image_spec);
+
+       result = io_open(loader_mem_dev_handle, bl1_image_spec, &img_handle);
+       if (result != IO_SUCCESS) {
+               WARN("Failed to open memmap device\n");
+               goto exit;
+       }
+       length = loader_mem_spec.length;
+       result = io_read(img_handle, FLUSH_BASE, length, &bytes_read);
+       if ((result != IO_SUCCESS) || (bytes_read < length)) {
+               WARN("Failed to load '%s' file (%i)\n", LOADER_MEM_NAME, result);
+               goto exit;
+       }
+       io_close(img_handle);
+
+       result = flush_loader();
+       if (result != IO_SUCCESS) {
+               io_dev_close(loader_mem_dev_handle);
+               return result;
+       }
+exit:
+       io_close(img_handle);
+       io_dev_close(loader_mem_dev_handle);
+       return result;
+}
+
+static int flush_single_image(const char *mmc_name, unsigned long img_addr,
+                               ssize_t offset, size_t length)
+{
+       uintptr_t img_handle, spec = 0;
+       size_t bytes_read;
+       int result = IO_FAIL;
+
+       result = plat_get_image_source(mmc_name, &emmc_dev_handle,
+                                      &spec);
+       if (result) {
+               NOTICE("failed to open emmc user data area\n");
+               return result;
+       }
+
+       result = io_open(emmc_dev_handle, spec, &img_handle);
+       if (result != IO_SUCCESS) {
+               NOTICE("Failed to open memmap device\n");
+               return result;
+       }
+
+       result = io_seek(img_handle, IO_SEEK_SET, offset);
+       if (result) {
+               NOTICE("Failed to seek at offset:0x%x\n", offset);
+               goto exit;
+       }
+
+       result = io_write(img_handle, img_addr, length,
+                         &bytes_read);
+       if ((result != IO_SUCCESS) || (bytes_read < length)) {
+               NOTICE("Failed to write file (%i)\n", result);
+               goto exit;
+       }
+exit:
+       io_close(img_handle);
+       return result;
+}
+
+static int is_sparse_image(unsigned long img_addr)
+{
+       if (*(uint32_t *)img_addr == SPARSE_HEADER_MAGIC)
+               return 1;
+       return 0;
+}
+
+static int do_unsparse(char *cmdbuf, unsigned long img_addr, unsigned long img_length)
+{
+       sparse_header_t *header = (sparse_header_t *)img_addr;
+       chunk_header_t *chunk = NULL;
+       struct ptentry *ptn;
+       void *data = (void *)img_addr;
+       uint64_t out_blks = 0, out_length = 0;
+       uint64_t length;
+       uint32_t fill_value;
+       uint64_t left, count;
+       int i, result;
+
+       ptn = find_ptn(cmdbuf);
+       if (!ptn) {
+               NOTICE("failed to find partition %s\n", cmdbuf);
+               return IO_FAIL;
+       }
+       length = (uint64_t)(header->total_blks) * (uint64_t)(header->blk_sz);
+       if (length > ptn->length) {
+               NOTICE("Unsparsed image length is %lld, pentry length is %lld.\n",
+                       length, ptn->length);
+               return IO_FAIL;
+       }
+
+       data = (void *)((unsigned long)data + header->file_hdr_sz);
+       for (i = 0; i < header->total_chunks; i++) {
+               chunk = (chunk_header_t *)data;
+               data = (void *)((unsigned long)data + sizeof(chunk_header_t));
+               length = (uint64_t)chunk->chunk_sz * (uint64_t)header->blk_sz;
+
+               switch (chunk->chunk_type) {
+               case CHUNK_TYPE_RAW:
+                       result = flush_single_image(NORMAL_EMMC_NAME,
+                                                   (unsigned long)data,
+                                                   ptn->start + out_length, length);
+                       if (result < 0) {
+                               NOTICE("sparse: failed to flush raw chunk\n");
+                               return result;
+                       }
+                       out_blks += length / 512;
+                       out_length += length;
+                       /* next chunk is just after the raw data */
+                       data = (void *)((unsigned long)data + length);
+                       break;
+               case CHUNK_TYPE_FILL:
+                       if (chunk->total_sz != (sizeof(unsigned int) + sizeof(chunk_header_t))) {
+                               NOTICE("sparse: bad chunk size\n");
+                               return IO_FAIL;
+                       }
+                       fill_value = *(unsigned int *)data;
+                       if (fill_value != 0) {
+                               NOTICE("sparse: filled value shouldn't be zero.\n");
+                       }
+                       memset((void *)SPARSE_FILL_BUFFER_ADDRESS,
+                               0, SPARSE_FILL_BUFFER_SIZE);
+                       left = length;
+                       while (left > 0) {
+                               if (left < SPARSE_FILL_BUFFER_SIZE)
+                                       count = left;
+                               else
+                                       count = SPARSE_FILL_BUFFER_SIZE;
+                               result = flush_single_image(NORMAL_EMMC_NAME,
+                                                           SPARSE_FILL_BUFFER_ADDRESS,
+                                                           ptn->start + out_length, count);
+                               if (result < 0) {
+                                       WARN("sparse: failed to flush fill chunk\n");
+                                       return result;
+                               }
+                               out_blks += count / 512;
+                               out_length += count;
+                               left = left - count;
+                       }
+                       /* next chunk is just after the filled data */
+                       data = (void *)((unsigned long)data + sizeof(unsigned int));
+                       break;
+               case CHUNK_TYPE_DONT_CARE:
+                       if (chunk->total_sz != sizeof(chunk_header_t)) {
+                               NOTICE("sparse: unmatched chunk size\n");
+                               return IO_FAIL;
+                       }
+                       out_blks += length / 512;
+                       out_length += length;
+                       break;
+               default:
+                       NOTICE("sparse: unrecognized type 0x%x\n", chunk->chunk_type);
+                       break;
+               }
+       }
+       return 0;
+}
+
+/* Page 1024 is used to store serial number */
+int flush_random_serialno(unsigned long addr, unsigned long length)
+{
+       int result;
+
+       memset((void *)SPARSE_FILL_BUFFER_ADDRESS, 0, 512);
+       memcpy((void *)SPARSE_FILL_BUFFER_ADDRESS, (void *)addr, length);
+       result = flush_single_image(NORMAL_EMMC_NAME, SPARSE_FILL_BUFFER_ADDRESS,
+                                   SERIALNO_OFFSET, 512);
+       return result;
+}
+
+char *load_serialno(void)
+{
+       uintptr_t img_handle, spec = 0;
+       size_t bytes_read;
+       struct random_serial_num *random = NULL;
+       int result;
+
+       result = plat_get_image_source(NORMAL_EMMC_NAME, &emmc_dev_handle,
+                                      &spec);
+       if (result) {
+               NOTICE("failed to open emmc user data area\n");
+               return NULL;
+       }
+
+       result = io_open(emmc_dev_handle, spec, &img_handle);
+       if (result != IO_SUCCESS) {
+               NOTICE("Failed to open memmap device\n");
+               return NULL;
+       }
+
+       result = io_seek(img_handle, IO_SEEK_SET, SERIALNO_OFFSET);
+       if (result) {
+               NOTICE("Failed to seek at offset 0\n");
+               goto exit;
+       }
+       result = io_read(img_handle, SPARSE_FILL_BUFFER_ADDRESS, 512, &bytes_read);
+       if ((result != IO_SUCCESS) || (bytes_read < 512)) {
+               NOTICE("Failed to load '%s' file (%i)\n", LOADER_MEM_NAME, result);
+               goto exit;
+       }
+       io_close(img_handle);
+
+       random = (struct random_serial_num *)SPARSE_FILL_BUFFER_ADDRESS;
+       if (random->magic != RANDOM_MAGIC)
+               return NULL;
+
+       return random->serialno;
+exit:
+       io_close(img_handle);
+       return NULL;
+}
+
+/*
+ * Flush bios.bin into User Data Area in eMMC
+ */
+int flush_user_images(char *cmdbuf, unsigned long img_addr,
+                     unsigned long img_length)
+{
+       struct entry_head entries[5];
+       struct ptentry *ptn;
+       size_t length;
+       ssize_t offset;
+       int result = IO_FAIL;
+       int i, fp;
+
+       result = fetch_entry_head((void *)img_addr, USER_MAX_ENTRIES, entries);
+       switch (result) {
+       case IO_NOT_SUPPORTED:
+               if (!strncmp(cmdbuf, "fastboot", 8) ||
+                   !strncmp(cmdbuf, "bios", 4)) {
+                       update_fip_spec();
+               }
+               if (is_sparse_image(img_addr)) {
+                       result = do_unsparse(cmdbuf, img_addr, img_length);
+               } else {
+                       ptn = find_ptn(cmdbuf);
+                       if (!ptn) {
+                               WARN("failed to find partition %s\n", cmdbuf);
+                               return IO_FAIL;
+                       }
+                       img_length = (img_length + 512 - 1) / 512 * 512;
+                       result = flush_single_image(NORMAL_EMMC_NAME, img_addr,
+                                                   ptn->start, img_length);
+               }
+               break;
+       case IO_SUCCESS:
+               if (strncmp(cmdbuf, "ptable", 6)) {
+                       WARN("it's not for ptable\n");
+                       return IO_FAIL;
+               }
+               /* currently it's for partition table */
+               /* the first block is for entry headers */
+               fp = 512;
+
+               for (i = 0; i < USER_MAX_ENTRIES; i++) {
+                       if (entries[i].flag != 0) {
+                               WARN("Invalid flag in entry:0x%x\n",
+                                       entries[i].flag);
+                               return IO_NOT_SUPPORTED;
+                       }
+                       if (entries[i].count == 0)
+                               continue;
+                       length = entries[i].count * 512;
+                       offset = MMC_BASE + entries[i].start * 512;
+                       VERBOSE("i:%d, start:%x, count:%x\n",
+                               i, entries[i].start, entries[i].count);
+                       result = flush_single_image(NORMAL_EMMC_NAME,
+                                               img_addr + fp, offset, length);
+                       fp += entries[i].count * 512;
+               }
+               get_partition();
+               break;
+       case IO_FAIL:
+               WARN("failed to parse entries in user image.\n");
+               return result;
+       }
+       return result;
+}
diff --git a/plat/hikey/plat_pm.c b/plat/hikey/plat_pm.c
new file mode 100644 (file)
index 0000000..0347cec
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <debug.h>
+#include <cci400.h>
+#include <errno.h>
+#include <gic_v2.h>
+#include <gpio.h>
+#include <hi6220.h>
+#include <hisi_ipc.h>
+#include <hisi_pwrc.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <sp804_timer.h>
+
+#include "hikey_def.h"
+#include "hikey_private.h"
+
+#define PLAT_SOC_SUSPEND_STATE 0x4
+
+static int32_t hikey_do_plat_actions(uint32_t afflvl, uint32_t state)
+{
+       assert(afflvl <= MPIDR_AFFLVL1);
+
+       if (state != PSCI_STATE_OFF)
+               return -EAGAIN;
+
+       return 0;
+}
+
+int32_t hikey_affinst_on(uint64_t mpidr,
+                        uint64_t sec_entrypoint,
+                        uint32_t afflvl,
+                        uint32_t state)
+{
+       int cpu, cluster;
+
+       cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT;
+       cpu = mpidr & MPIDR_CPU_MASK;
+
+       VERBOSE("#%s, mpidr:%llx, afflvl:%x, state:%x\n", __func__, mpidr, afflvl, state);
+
+       /* directly return for power on */
+       if (state == PSCI_STATE_ON)
+               return PSCI_E_SUCCESS;
+
+       switch (afflvl) {
+       case MPIDR_AFFLVL0:
+               hisi_pwrc_set_core_bx_addr(cpu, cluster, sec_entrypoint);
+               hisi_ipc_cpu_on(cpu, cluster);
+               break;
+
+       case MPIDR_AFFLVL1:
+               hisi_ipc_cluster_on(cpu, cluster);
+               break;
+       }
+
+       return PSCI_E_SUCCESS;
+}
+
+
+static void hikey_affinst_off(uint32_t afflvl, uint32_t state)
+{
+       unsigned int mpidr = read_mpidr_el1();
+       int cpu, cluster;
+
+       cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT;
+       cpu = mpidr & MPIDR_CPU_MASK;
+
+       if (hikey_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       switch (afflvl) {
+       case MPIDR_AFFLVL1:
+               hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+               cci_disable_cluster_coherency(mpidr);
+               hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+               hisi_ipc_cluster_off(cpu, cluster);
+               break;
+
+       case MPIDR_AFFLVL0:
+               arm_gic_cpuif_deactivate();
+               hisi_ipc_cpu_off(cpu, cluster);
+               break;
+       }
+
+       return;
+}
+
+static void hikey_affinst_suspend(uint64_t sec_entrypoint,
+                                 uint32_t afflvl,
+                                 uint32_t state)
+{
+       unsigned int mpidr = read_mpidr_el1();
+       int cpu, cluster;
+
+       cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT;
+       cpu = mpidr & MPIDR_CPU_MASK;
+
+       if (hikey_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       switch (afflvl) {
+       case MPIDR_AFFLVL1:
+
+               hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+               cci_disable_cluster_coherency(mpidr);
+               hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+               if (psci_get_suspend_stateid() == PLAT_SOC_SUSPEND_STATE) {
+                       hisi_pwrc_set_cluster_wfi(1);
+                       hisi_pwrc_set_cluster_wfi(0);
+                       hisi_ipc_psci_system_off();
+               } else
+                       hisi_ipc_cluster_suspend(cpu, cluster);
+
+               break;
+
+       case MPIDR_AFFLVL0:
+
+               /* Program the jump address for the target cpu */
+               hisi_pwrc_set_core_bx_addr(cpu, cluster, sec_entrypoint);
+
+               arm_gic_cpuif_deactivate();
+
+               if (psci_get_suspend_stateid() != PLAT_SOC_SUSPEND_STATE)
+                       hisi_ipc_cpu_suspend(cpu, cluster);
+               break;
+       }
+
+       return;
+}
+
+void hikey_affinst_on_finish(uint32_t afflvl, uint32_t state)
+{
+       unsigned long mpidr;
+       int cpu, cluster;
+
+       if (hikey_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       /* Get the mpidr for this cpu */
+       mpidr = read_mpidr_el1();
+       cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT;
+       cpu = mpidr & MPIDR_CPU_MASK;
+
+       /* Perform the common cluster specific operations */
+       if (afflvl != MPIDR_AFFLVL0)
+               cci_enable_cluster_coherency(mpidr);
+
+       /* Zero the jump address in the mailbox for this cpu */
+       hisi_pwrc_set_core_bx_addr(cpu, cluster, 0);
+
+       if (psci_get_suspend_stateid() == PLAT_SOC_SUSPEND_STATE) {
+               arm_gic_setup();
+       } else {
+               /* Enable the gic cpu interface */
+               arm_gic_cpuif_setup();
+
+               /* TODO: This setup is needed only after a cold boot */
+               arm_gic_pcpu_distif_setup();
+       }
+
+       return;
+}
+
+static void hikey_affinst_suspend_finish(uint32_t afflvl,
+                                        uint32_t state)
+{
+       hikey_affinst_on_finish(afflvl, state);
+       return;
+}
+
+static void __dead2 hikey_system_off(void)
+{
+       unsigned int start, cnt, delta, delta_ms;
+       unsigned int show = 1;
+
+       NOTICE("%s: off system\n", __func__);
+
+       /* pulling GPIO_0_0 low to trigger PMIC shutdown */
+       /* setting pinmux */
+       mmio_write_32(0xF8001810, 0x2);
+       /* setting pin direction */
+       mmio_write_8(0xF8011400, 1);
+       /* setting pin output value */
+       mmio_write_8(0xF8011004, 0);
+
+       /* PMIC shutdown depends on two conditions: GPIO_0_0 (PWR_HOLD) low,
+        * and VBUS_DET < 3.6V. For HiKey, VBUS_DET is connected to VDD_4V2
+        * through Jumper 1-2. So, to complete shutdown, user needs to manually
+        * remove Jumper 1-2.
+        */
+       /* init timer00 */
+       mmio_write_32(TIMER00_CONTROL, 0);
+       mmio_write_32(TIMER00_LOAD, 0xffffffff);
+       /* free running */
+       mmio_write_32(TIMER00_CONTROL, 0x82);
+
+       /* adding delays */
+       start = mmio_read_32(TIMER00_VALUE);
+       do {
+               cnt = mmio_read_32(TIMER00_VALUE);
+               if (cnt > start) {
+                       delta = 0xffffffff - cnt;
+                       delta += start;
+               } else
+                       delta = start - cnt;
+               delta_ms = delta / 19200;
+               if (delta_ms > 1000 && show) { /* after 1 second */
+                       /* if we are still alive, that means Jumper
+                        * 1-2 is mounted. Need to warn and reboot
+                        */
+                       NOTICE("..........................................\n");
+                       NOTICE(" IMPORTANT: Remove Jumper 1-2 to shutdown\n");
+                       NOTICE(" DANGER:    SoC is still burning. DANGER!\n");
+                       NOTICE(" Board will be reboot to avoid overheat\n");
+                       NOTICE("..........................................\n");
+                       show = 0;
+               }
+       } while (delta_ms < 5000); /* no. of delay in ms */
+
+       /* Send the system reset request */
+       mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
+
+       wfi();
+       panic();
+}
+
+static void __dead2 hikey_system_reset(void)
+{
+       VERBOSE("%s: reset system\n", __func__);
+
+       /* Send the system reset request */
+       mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
+
+       wfi();
+       panic();
+}
+
+unsigned int hikey_get_sys_suspend_power_state(void)
+{
+       unsigned int power_state;
+
+       power_state = psci_make_powerstate(PLAT_SOC_SUSPEND_STATE,
+                       PSTATE_TYPE_POWERDOWN, MPIDR_AFFLVL1);
+
+       return power_state;
+}
+
+static const plat_pm_ops_t hikey_plat_pm_ops = {
+       .affinst_on                  = hikey_affinst_on,
+       .affinst_on_finish           = hikey_affinst_on_finish,
+       .affinst_off                 = hikey_affinst_off,
+       .affinst_standby             = NULL,
+       .affinst_suspend             = hikey_affinst_suspend,
+       .affinst_suspend_finish      = hikey_affinst_suspend_finish,
+       .system_off                  = hikey_system_off,
+       .system_reset                = hikey_system_reset,
+       .get_sys_suspend_power_state = hikey_get_sys_suspend_power_state,
+};
+
+int platform_setup_pm(const plat_pm_ops_t **plat_ops)
+{
+       *plat_ops = &hikey_plat_pm_ops;
+       return 0;
+}
diff --git a/plat/hikey/plat_security.c b/plat/hikey/plat_security.c
new file mode 100644 (file)
index 0000000..b2cd602
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <stdint.h>
+#include <strings.h>
+#include <platform_def.h>
+
+#define PORTNUM_MAX            5
+
+#define MDDRC_SECURITY_BASE    0xF7121000
+
+struct int_en_reg {
+       unsigned in_en:1;
+       unsigned reserved:31;
+};
+
+struct rgn_map_reg {
+       unsigned rgn_base_addr:24;
+       unsigned rgn_size:6;
+       unsigned reserved:1;
+       unsigned rgn_en:1;
+};
+
+struct rgn_attr_reg {
+       unsigned sp:4;
+       unsigned security_inv:1;
+       unsigned reserved_0:3;
+       unsigned mid_en:1;
+       unsigned mid_inv:1;
+       unsigned reserved_1:6;
+       unsigned rgn_en:1;
+       unsigned subrgn_disable:16;
+};
+
+static volatile struct int_en_reg *get_int_en_reg(uint32_t base)
+{
+       uint64_t addr = base + 0x20;
+       return (struct int_en_reg *)addr;
+}
+
+static volatile struct rgn_map_reg *get_rgn_map_reg(uint32_t base, int region, int port)
+{
+       uint64_t addr = base + 0x100 + 0x10 * region + 0x400 * port;
+       return (struct rgn_map_reg *)addr;
+}
+
+static volatile struct rgn_attr_reg *get_rgn_attr_reg(uint32_t base, int region,
+                                            int port)
+{
+       uint64_t addr = base + 0x104 + 0x10 * region + 0x400 * port;
+       return (struct rgn_attr_reg *)addr;
+}
+
+static int is_power_of_two(uint32_t x)
+{
+       return ((x != 0) && !(x & (x - 1)));
+}
+
+/*
+ * Configure secure memory region
+ * region_size must be a power of 2 and at least 64KB
+ * region_base must be region_size aligned
+ */
+static void sec_protect(uint32_t region_base, uint32_t region_size)
+{
+       volatile struct int_en_reg *int_en_reg ;
+       volatile struct rgn_map_reg *rgn_map_reg;
+       volatile struct rgn_attr_reg *rgn_attr_reg;
+       uint32_t i = 0;
+
+       if (!is_power_of_two(region_size) || region_size < 0x10000) {
+               ERROR("Secure region size is not a power of 2 >= 64KB\n");
+               return;
+       }
+       if (region_base & (region_size - 1)) {
+               ERROR("Secure region address is not aligned to region size\n");
+               return;
+       }
+
+       INFO("BL2: TrustZone: protecting %u bytes of memory at 0x%x\n", region_size,
+            region_base);
+
+       int_en_reg = get_int_en_reg(MDDRC_SECURITY_BASE);
+       int_en_reg->in_en = 0x1;
+
+       for (i = 0; i < PORTNUM_MAX; i++) {
+               rgn_map_reg = get_rgn_map_reg(MDDRC_SECURITY_BASE, 1, i);
+               rgn_attr_reg = get_rgn_attr_reg(MDDRC_SECURITY_BASE, 1, i);
+               rgn_map_reg->rgn_base_addr = region_base >> 16;
+               rgn_attr_reg->subrgn_disable = 0x0;
+               rgn_attr_reg->sp = (i == 3) ? 0xC : 0x0;
+               rgn_map_reg->rgn_size = __builtin_ffs(region_size) - 2;
+               rgn_map_reg->rgn_en = 0x1;
+       }
+}
+
+/*******************************************************************************
+ * Initialize the secure environment.
+ ******************************************************************************/
+void plat_security_setup(void)
+{
+       sec_protect(DRAM_SEC_BASE, DRAM_SEC_SIZE);
+}
diff --git a/plat/hikey/plat_topology.c b/plat/hikey/plat_topology.c
new file mode 100644 (file)
index 0000000..1e9fa90
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.h>
+#include <psci.h>
+
+unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr)
+{
+       /* Report 1 (absent) instance at levels higher that the cluster level */
+       if (aff_lvl > MPIDR_AFFLVL1)
+               return 1;
+
+       if (aff_lvl == MPIDR_AFFLVL1)
+               return 2; /* We have two clusters */
+
+       return 4; /* 4 cpus in cluster 1 or cluster 0 */
+}
+
+unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr)
+{
+       return aff_lvl <= MPIDR_AFFLVL1 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT;
+}
+
+int plat_get_max_afflvl()
+{
+       return MPIDR_AFFLVL1;
+}
+
+int plat_setup_topology()
+{
+       /* Juno todo: Make topology configurable via SCC */
+       return 0;
+}
diff --git a/plat/hikey/platform.mk b/plat/hikey/platform.mk
new file mode 100644 (file)
index 0000000..fd32307
--- /dev/null
@@ -0,0 +1,105 @@
+#
+# Copyright (c) 2014-2015, Linaro Ltd. All rights reserved.
+# Copyright (c) 2014-2015, Hisilicon Ltd.
+#
+# 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.
+#
+
+# On Hikey, the TSP can execute either from Trusted SRAM or Trusted DRAM.
+# Trusted DRAM is the default.
+#
+PLAT_TSP_LOCATION      :=      tdram
+ifeq (${PLAT_TSP_LOCATION}, tsram)
+  PLAT_TSP_LOCATION_ID := PLAT_TRUSTED_SRAM_ID
+else ifeq (${PLAT_TSP_LOCATION}, tdram)
+  PLAT_TSP_LOCATION_ID := PLAT_TRUSTED_DRAM_ID
+else
+  $(error "Unsupported PLAT_TSP_LOCATION value")
+endif
+
+CONSOLE_BASE           :=      PL011_UART3_BASE
+CRASH_CONSOLE_BASE     :=      PL011_UART3_BASE
+
+# Process flags
+$(eval $(call add_define,PLAT_TSP_LOCATION_ID))
+$(eval $(call add_define,CONSOLE_BASE))
+$(eval $(call add_define,CRASH_CONSOLE_BASE))
+
+
+PLAT_INCLUDES          :=      -Iplat/hikey/include/
+
+PLAT_BL_COMMON_SOURCES :=      drivers/arm/pl011/pl011_console.S       \
+                               drivers/io/io_block.c                   \
+                               drivers/io/io_fip.c                     \
+                               drivers/io/io_memmap.c                  \
+                               drivers/io/io_storage.c                 \
+                               lib/aarch64/xlat_tables.c               \
+                               plat/common/aarch64/plat_common.c       \
+                               plat/common/plat_gic.c                  \
+                               plat/hikey/aarch64/hikey_common.c       \
+                               plat/hikey/aarch64/plat_helpers.S       \
+                               plat/hikey/plat_io_storage.c
+
+BL1_SOURCES            +=      drivers/arm/cci400/cci400.c             \
+                               drivers/arm/gpio/gpio.c                 \
+                               lib/cpus/aarch64/cortex_a53.S           \
+                               plat/common/aarch64/platform_up_stack.S \
+                               plat/hikey/aarch64/bl1_plat_helpers.S   \
+                               plat/hikey/bl1_plat_setup.c             \
+                               plat/hikey/drivers/dw_mmc.c             \
+                               plat/hikey/drivers/hi6553.c             \
+                               plat/hikey/drivers/sp804_timer.c        \
+                               plat/hikey/partitions.c                 \
+                               plat/hikey/pll.c                        \
+                               plat/hikey/usb.c
+
+BL2_SOURCES            +=      plat/common/aarch64/platform_up_stack.S \
+                               plat/hikey/bl2_plat_setup.c             \
+                               plat/hikey/plat_security.c              \
+                               plat/hikey/drivers/dw_mmc.c             \
+                               plat/hikey/drivers/hi6553.c             \
+                               plat/hikey/drivers/hisi_dvfs.c          \
+                               plat/hikey/drivers/hisi_mcu.c           \
+                               plat/hikey/drivers/sp804_timer.c        \
+                               plat/hikey/partitions.c
+
+BL31_SOURCES           +=      drivers/arm/cci400/cci400.c             \
+                               drivers/arm/gic/arm_gic.c               \
+                               drivers/arm/gic/gic_v2.c                \
+                               drivers/arm/gic/gic_v3.c                \
+                               drivers/arm/gpio/gpio.c                 \
+                               lib/cpus/aarch64/cortex_a53.S           \
+                               plat/common/aarch64/platform_mp_stack.S \
+                               plat/hikey/bl31_plat_setup.c            \
+                               plat/hikey/drivers/hisi_pwrc.c          \
+                               plat/hikey/drivers/hisi_pwrc_sram.S     \
+                               plat/hikey/drivers/hisi_ipc.c           \
+                               plat/hikey/drivers/sp804_timer.c        \
+                               plat/hikey/plat_pm.c                    \
+                               plat/hikey/plat_topology.c
+
+NEED_BL30              :=      yes
diff --git a/plat/hikey/pll.c b/plat/hikey/pll.c
new file mode 100644 (file)
index 0000000..0a5dd28
--- /dev/null
@@ -0,0 +1,1166 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <hi6220.h>
+#include <hi6553.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <sp804_timer.h>
+
+static void init_pll(void)
+{
+       unsigned int data;
+
+       data = mmio_read_32((0xf7032000 + 0x000));
+       data |= 0x1;
+       mmio_write_32((0xf7032000 + 0x000), data);
+       dsb();
+       do {
+               data = mmio_read_32((0xf7032000 + 0x000));
+       } while (!(data & (1 << 28)));
+
+       data = mmio_read_32((0xf7800000 + 0x000));
+       data &= ~0x007;
+       data |= 0x004;
+       mmio_write_32((0xf7800000 + 0x000), data);
+       dsb();
+       do {
+               data = mmio_read_32((0xf7800000 + 0x014));
+               data &= 0x007;
+       } while (data != 0x004);
+
+       mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101);
+       data = mmio_read_32(PERI_SC_PERIPH_STAT1);
+       mmio_write_32(0xf7032000 + 0x02c, 0x5110103e);
+       data = mmio_read_32(0xf7032000 + 0x050);
+       data |= 1 << 28;
+       mmio_write_32(0xf7032000 + 0x050, data);
+       mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101);
+       mdelay(1);
+       data = mmio_read_32(PERI_SC_PERIPH_STAT1);
+       NOTICE("syspll frequency:%dHz\n", data);
+}
+
+static void init_freq(void)
+{
+       unsigned int data, tmp;
+       unsigned int cpuext_cfg, ddr_cfg;
+
+       mmio_write_32((0xf7032000 + 0x374), 0x4a);
+       mmio_write_32((0xf7032000 + 0x368), 0xda);
+       mmio_write_32((0xf7032000 + 0x36c), 0x01);
+       mmio_write_32((0xf7032000 + 0x370), 0x01);
+       mmio_write_32((0xf7032000 + 0x360), 0x60);
+       mmio_write_32((0xf7032000 + 0x364), 0x60);
+
+       mmio_write_32((0xf7032000 + 0x114), 0x1000);
+
+       data = mmio_read_32((0xf7032000 + 0x110));
+       data |= (3 << 12);
+       mmio_write_32((0xf7032000 + 0x110), data);
+
+       data = mmio_read_32((0xf7032000 + 0x110));
+       data |= (1 << 4);
+       mmio_write_32((0xf7032000 + 0x110), data);
+
+
+       data = mmio_read_32((0xf7032000 + 0x110));
+       data &= ~0x7;
+       data |= 0x5;
+       mmio_write_32((0xf7032000 + 0x110), data);
+       dsb();
+       mdelay(10);
+
+
+       do {
+               data = mmio_read_32((0xf6504000 + 0x008));
+               data &= (3 << 20);
+       } while (data != (3 << 20));
+       dsb();
+       mdelay(10);
+
+
+       data = mmio_read_32((0xf6504000 + 0x054));
+       data &= ~((1 << 0) | (1 << 11));
+       mmio_write_32((0xf6504000 + 0x054), data);
+       mdelay(10);
+
+       data = mmio_read_32((0xf7032000 + 0x104));
+       data &= ~(3 << 8);
+       data |= (1 << 8);
+       mmio_write_32((0xf7032000 + 0x104), data);
+
+       data = mmio_read_32((0xf7032000 + 0x100));
+       data |= (1 << 0);
+       mmio_write_32((0xf7032000 + 0x100), data);
+       dsb();
+
+       do {
+               data = mmio_read_32((0xf7032000 + 0x100));
+               data &= (1 << 2);
+       } while (data != (1 << 2));
+
+       data = mmio_read_32((0xf6504000 + 0x06c));
+       data &= ~0xffff;
+       data |= 0x56;
+       mmio_write_32((0xf6504000 + 0x06c), data);
+
+       data = mmio_read_32((0xf6504000 + 0x06c));
+       data &= ~(0xffffff << 8);
+       data |= 0xc7a << 8;
+       mmio_write_32((0xf6504000 + 0x06c), data);
+
+       data = mmio_read_32((0xf6504000 + 0x058));
+       data &= ((1 << 13) - 1);
+       data |= 0xccb;
+       mmio_write_32((0xf6504000 + 0x058), data);
+
+       mmio_write_32((0xf6504000 + 0x060), 0x1fff);
+       mmio_write_32((0xf6504000 + 0x064), 0x1ffffff);
+       mmio_write_32((0xf6504000 + 0x068), 0x7fffffff);
+       mmio_write_32((0xf6504000 + 0x05c), 0x1);
+
+       data = mmio_read_32((0xf6504000 + 0x054));
+       data &= ~(0xf << 12);
+       data |= 1 << 12;
+       mmio_write_32((0xf6504000 + 0x054), data);
+       dsb();
+
+
+       data = mmio_read_32((0xf7032000 + 0x000));
+       data &= ~(1 << 0);
+       mmio_write_32((0xf7032000 + 0x000), data);
+
+       mmio_write_32((0xf7032000 + 0x004), 0x5110207d);
+       mmio_write_32((0xf7032000 + 0x134), 0x10000005);
+       data = mmio_read_32((0xf7032000 + 0x134));
+
+
+       data = mmio_read_32((0xf7032000 + 0x000));
+       data |= (1 << 0);
+       mmio_write_32((0xf7032000 + 0x000), data);
+
+       mmio_write_32((0xf7032000 + 0x368), 0x100da);
+       data = mmio_read_32((0xf7032000 + 0x378));
+       data &= ~((1 << 7) - 1);
+       data |= 0x6b;
+       mmio_write_32((0xf7032000 + 0x378), data);
+       dsb();
+       do {
+               data = mmio_read_32((0xf7032000 + 0x378));
+               tmp = data & 0x7f;
+               data = (data & (0x7f << 8)) >> 8;
+               if (data != tmp)
+                       continue;
+               data = mmio_read_32((0xf7032000 + 0x37c));
+       } while (!(data & 1));
+
+       data = mmio_read_32((0xf7032000 + 0x104));
+       data &= ~((3 << 0) |
+                       (3 << 8));
+       cpuext_cfg = 1;
+       ddr_cfg = 1;
+       data |= cpuext_cfg | (ddr_cfg << 8);
+       mmio_write_32((0xf7032000 + 0x104), data);
+       dsb();
+
+       do {
+               data = mmio_read_32((0xf7032000 + 0x104));
+               tmp = (data & (3 << 16)) >> 16;
+               if (cpuext_cfg != tmp)
+                       continue;
+               tmp = (data & (3 << 24)) >> 24;
+               if (ddr_cfg != tmp)
+                       continue;
+               data = mmio_read_32((0xf7032000 + 0x000));
+               data &= 1 << 28;
+       } while (!data);
+
+       data = mmio_read_32((0xf7032000 + 0x100));
+       data &= ~(1 << 0);
+       mmio_write_32((0xf7032000 + 0x100), data);
+       dsb();
+       do {
+               data = mmio_read_32((0xf7032000 + 0x100));
+               data &= (1 << 1);
+       } while (data != (1 << 1));
+       mdelay(1000);
+
+       data = mmio_read_32((0xf6504000 + 0x054));
+       data &= ~(1 << 28);
+       mmio_write_32((0xf6504000 + 0x054), data);
+       dsb();
+
+       data = mmio_read_32((0xf7032000 + 0x110));
+       data &= ~((1 << 4) |
+                       (3 << 12));
+       mmio_write_32((0xf7032000 + 0x110), data);
+}
+
+int cat_533mhz_800mhz(void)
+{
+       unsigned int data, i;
+       unsigned int bdl[5];
+
+
+       data = mmio_read_32((0xf712c000 + 0x1c8));
+       data &= 0xfffff0f0;
+       data |= 0x100f0f;
+       mmio_write_32((0xf712c000 + 0x1c8), data);
+
+       for (i = 0; i < 0x20; i++) {
+               mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+               data = (i << 0x10) + i;
+               mmio_write_32((0xf712c000 + 0x140), data);
+               mmio_write_32((0xf712c000 + 0x144), data);
+               mmio_write_32((0xf712c000 + 0x148), data);
+               mmio_write_32((0xf712c000 + 0x14c), data);
+               mmio_write_32((0xf712c000 + 0x150), data);
+
+
+               data = mmio_read_32((0xf712c000 + 0x070));
+               data |= 0x80000;
+               mmio_write_32((0xf712c000 + 0x070), data);
+               data = mmio_read_32((0xf712c000 + 0x070));
+               data &= 0xfff7ffff;
+               mmio_write_32((0xf712c000 + 0x070), data);
+
+
+               mmio_write_32((0xf712c000 + 0x004), 0x8000);
+               mmio_write_32((0xf712c000 + 0x004), 0x0);
+               mmio_write_32((0xf712c000 + 0x004), 0x801);
+               do {
+                       data = mmio_read_32((0xf712c000 + 0x004));
+               } while (data & 1);
+
+               data = mmio_read_32((0xf712c000 + 0x008));
+               if (!(data & 0x400)) {
+                       mdelay(10);
+                       return 0;
+               }
+               tf_printf("WARN:  " "lpddr3 cat fail\n");
+               data = mmio_read_32((0xf712c000 + 0x1d4));
+               if ((data & 0x1f00) && ((data & 0x1f) == 0)) {
+                       bdl[0] = mmio_read_32((0xf712c000 + 0x140));
+                       bdl[1] = mmio_read_32((0xf712c000 + 0x144));
+                       bdl[2] = mmio_read_32((0xf712c000 + 0x148));
+                       bdl[3] = mmio_read_32((0xf712c000 + 0x14c));
+                       bdl[4] = mmio_read_32((0xf712c000 + 0x150));
+                       if ((!(bdl[0] & 0x1f001f)) || (!(bdl[1] & 0x1f001f)) ||
+                                       (!(bdl[2] & 0x1f001f)) || (!(bdl[3] & 0x1f001f)) ||
+                                       (!(bdl[4] & 0x1f001f))) {
+                               tf_printf("WARN:  " "lpddr3 cat deskew error\n");
+                               if (i == 0x1f) {
+                                       tf_printf("WARN:  " "addrnbdl is max\n");
+                                       return -22;
+                               }
+                               mmio_write_32((0xf712c000 + 0x008), 0x400);
+                       } else {
+                               tf_printf("WARN:  " "lpddr3 cat other error1\n");
+                               return -22;
+                       }
+               } else {
+                       tf_printf("WARN:  " "lpddr3 cat other error2\n");
+                       return -22;
+               }
+       }
+       return -22;
+}
+
+static void ddrx_rdet(void)
+{
+       unsigned int data, rdet, bdl[4];
+
+       data = mmio_read_32((0xf712c000 + 0x0d0));
+       data &= 0xf800ffff;
+       data |= 0x8f0000;
+       mmio_write_32((0xf712c000 + 0x0d0), data);
+
+       data = mmio_read_32((0xf712c000 + 0x0dc));
+       data &= 0xfffffff0;
+       data |= 0xf;
+       mmio_write_32((0xf712c000 + 0x0dc), data);
+
+
+       data = mmio_read_32((0xf712c000 + 0x070));
+       data |= 0x80000;
+       mmio_write_32((0xf712c000 + 0x070), data);
+       data = mmio_read_32((0xf712c000 + 0x070));
+       data &= 0xfff7ffff;
+       mmio_write_32((0xf712c000 + 0x070), data);
+
+       mmio_write_32((0xf712c000 + 0x004), 0x8000);
+       mmio_write_32((0xf712c000 + 0x004), 0);
+
+       data = mmio_read_32((0xf712c000 + 0x0d0));
+       data &= ~0xf0000000;
+       data |= 0x80000000;
+       mmio_write_32((0xf712c000 + 0x0d0), data);
+
+       mmio_write_32((0xf712c000 + 0x004), 0x101);
+       do {
+               data = mmio_read_32((0xf712c000 + 0x004));
+       } while (!(data & 1));
+       data = mmio_read_32((0xf712c000 + 0x008));
+       if (data & 0x100)
+               tf_printf("WARN:    " "rdet lbs fail\n");
+
+       bdl[0] = mmio_read_32((0xf712c000 + 0x22c)) & 0x7f;
+       bdl[1] = mmio_read_32((0xf712c000 + 0x2ac)) & 0x7f;
+       bdl[2] = mmio_read_32((0xf712c000 + 0x32c)) & 0x7f;
+       bdl[3] = mmio_read_32((0xf712c000 + 0x3ac)) & 0x7f;
+       do {
+               data = mmio_read_32((0xf712c000 + 0x22c));
+               data &= ~0x7f;
+               data |= bdl[0];
+               mmio_write_32((0xf712c000 + 0x22c), data);
+               data = mmio_read_32((0xf712c000 + 0x2ac));
+               data &= ~0x7f;
+               data |= bdl[1];
+               mmio_write_32((0xf712c000 + 0x2ac), data);
+               data = mmio_read_32((0xf712c000 + 0x32c));
+               data &= ~0x7f;
+               data |= bdl[2];
+               mmio_write_32((0xf712c000 + 0x32c), data);
+               data = mmio_read_32((0xf712c000 + 0x3ac));
+               data &= ~0x7f;
+               data |= bdl[3];
+               mmio_write_32((0xf712c000 + 0x3ac), data);
+
+
+               data = mmio_read_32((0xf712c000 + 0x070));
+               data |= 0x80000;
+               mmio_write_32((0xf712c000 + 0x070), data);
+               data = mmio_read_32((0xf712c000 + 0x070));
+               data &= 0xfff7ffff;
+               mmio_write_32((0xf712c000 + 0x070), data);
+
+               mmio_write_32((0xf712c000 + 0x004), 0x8000);
+               mmio_write_32((0xf712c000 + 0x004), 0);
+
+               data = mmio_read_32((0xf712c000 + 0x0d0));
+               data &= ~0xf0000000;
+               data |= 0x40000000;
+               mmio_write_32((0xf712c000 + 0x0d0), data);
+               mmio_write_32((0xf712c000 + 0x004), 0x101);
+               do {
+                       data = mmio_read_32((0xf712c000 + 0x004));
+               } while (data & 1);
+
+               data = mmio_read_32((0xf712c000 + 0x008));
+               rdet = data & 0x100;
+               if (rdet) {
+                       tf_printf("INFO:    " "rdet ds fail\n");
+                       mmio_write_32((0xf712c000 + 0x008), 0x100);
+               }
+               bdl[0]++;
+               bdl[1]++;
+               bdl[2]++;
+               bdl[3]++;
+       } while (rdet);
+
+       data = mmio_read_32((0xf712c000 + 0x0d0));
+       data &= ~0xf0000000;
+       data |= 0x30000000;
+       mmio_write_32((0xf712c000 + 0x0d0), data);
+
+       mmio_write_32((0xf712c000 + 0x004), 0x101);
+       do {
+               data = mmio_read_32((0xf712c000 + 0x004));
+       } while (data & 1);
+       data = mmio_read_32((0xf712c000 + 0x008));
+       if (data & 0x100)
+               tf_printf("INFO:    " "rdet rbs av fail\n");
+}
+
+static void ddrx_wdet(void)
+{
+       unsigned int data, wdet, zero_bdl, dq[4];
+       int i;
+
+       data = mmio_read_32((0xf712c000 + 0x0d0));
+       data &= ~0xf;
+       data |= 0xf;
+       mmio_write_32((0xf712c000 + 0x0d0), data);
+
+       data = mmio_read_32((0xf712c000 + 0x070));
+       data |= 0x80000;
+       mmio_write_32((0xf712c000 + 0x070), data);
+       data = mmio_read_32((0xf712c000 + 0x070));
+       data &= ~0x80000;
+       mmio_write_32((0xf712c000 + 0x070), data);
+
+       mmio_write_32((0xf712c000 + 0x004), 0x8000);
+       mmio_write_32((0xf712c000 + 0x004), 0);
+       data = mmio_read_32((0xf712c000 + 0x0d0));
+       data &= ~0xf000;
+       data |= 0x8000;
+       mmio_write_32((0xf712c000 + 0x0d0), data);
+       mmio_write_32((0xf712c000 + 0x004), 0x201);
+       do {
+               data = mmio_read_32((0xf712c000 + 0x004));
+       } while (data & 1);
+       data = mmio_read_32((0xf712c000 + 0x008));
+       if (data & 0x200)
+               tf_printf("INFO:    " "wdet lbs fail\n");
+
+       dq[0] = mmio_read_32((0xf712c000 + 0x234)) & 0x1f00;
+       dq[1] = mmio_read_32((0xf712c000 + 0x2b4)) & 0x1f00;
+       dq[2] = mmio_read_32((0xf712c000 + 0x334)) & 0x1f00;
+       dq[3] = mmio_read_32((0xf712c000 + 0x3b4)) & 0x1f00;
+
+       do {
+               mmio_write_32((0xf712c000 + 0x234), dq[0]);
+               mmio_write_32((0xf712c000 + 0x2b4), dq[1]);
+               mmio_write_32((0xf712c000 + 0x334), dq[2]);
+               mmio_write_32((0xf712c000 + 0x3b4), dq[3]);
+
+               data = mmio_read_32((0xf712c000 + 0x070));
+               data |= 0x80000;
+               mmio_write_32((0xf712c000 + 0x070), data);
+               data = mmio_read_32((0xf712c000 + 0x070));
+               data &= ~0x80000;
+               mmio_write_32((0xf712c000 + 0x070), data);
+               mmio_write_32((0xf712c000 + 0x004), 0x8000);
+               mmio_write_32((0xf712c000 + 0x004), 0);
+
+               data = mmio_read_32((0xf712c000 + 0x0d0));
+               data &= ~0xf000;
+               data |= 0x4000;
+               mmio_write_32((0xf712c000 + 0x0d0), data);
+               mmio_write_32((0xf712c000 + 0x004), 0x201);
+               do {
+                       data = mmio_read_32((0xf712c000 + 0x004));
+               } while (data & 1);
+
+               data = mmio_read_32((0xf712c000 + 0x008));
+               wdet = data & 0x200;
+               if (wdet) {
+                       tf_printf("INFO:    " "wdet ds fail\n");
+                       mmio_write_32((0xf712c000 + 0x008), 0x200);
+               }
+               mdelay(10);
+
+               for (i = 0; i < 4; i++) {
+                       data = mmio_read_32((0xf712c000 + 0x210 + i * 0x80));
+                       if ((!(data & 0x1f)) || (!(data & 0x1f00)) ||
+                                       (!(data & 0x1f0000)) || (!(data & 0x1f000000)))
+                               zero_bdl = 1;
+                       data = mmio_read_32((0xf712c000 + 0x214 + i * 0x80));
+                       if ((!(data & 0x1f)) || (!(data & 0x1f00)) ||
+                                       (!(data & 0x1f0000)) || (!(data & 0x1f000000)))
+                               zero_bdl = 1;
+                       data = mmio_read_32((0xf712c000 + 0x218 + i * 0x80));
+                       if (!(data & 0x1f))
+                               zero_bdl = 1;
+                       if (zero_bdl) {
+                               if (i == 0)
+                                       dq[0] = dq[0] - 0x100;
+                               if (i == 1)
+                                       dq[1] = dq[1] - 0x100;
+                               if (i == 2)
+                                       dq[2] = dq[2] - 0x100;
+                               if (i == 3)
+                                       dq[3] = dq[3] - 0x100;
+                       }
+               }
+       } while (wdet);
+
+       data = mmio_read_32((0xf712c000 + 0x0d0));
+       data &= ~0xf000;
+       data |= 0x3000;
+       mmio_write_32((0xf712c000 + 0x0d0), data);
+       mmio_write_32((0xf712c000 + 0x004), 0x201);
+       do {
+               data = mmio_read_32((0xf712c000 + 0x004));
+       } while (data & 1);
+       data = mmio_read_32((0xf712c000 + 0x008));
+       if (data & 0x200)
+               tf_printf("INFO:    " "wdet rbs av fail\n");
+}
+
+static void set_ddrc_533mhz(void)
+{
+       unsigned int data;
+
+       mmio_write_32((0xf7032000 + 0x580), 0x3);
+       mmio_write_32((0xf7032000 + 0x5a8), 0x11111);
+       data = mmio_read_32((0xf7032000 + 0x104));
+       data |= 0x100;
+       mmio_write_32((0xf7032000 + 0x104), data);
+
+       mmio_write_32((0xf7030000 + 0x050), 0x30);
+       mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+       mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+       mmio_write_32((0xf712c000 + 0x00c), 0x400);
+       mmio_write_32((0xf712c000 + 0x018), 0x7);
+       mmio_write_32((0xf712c000 + 0x090), 0x6400000);
+       mmio_write_32((0xf712c000 + 0x258), 0x640);
+       mmio_write_32((0xf712c000 + 0x2d8), 0x640);
+       mmio_write_32((0xf712c000 + 0x358), 0x640);
+       mmio_write_32((0xf712c000 + 0x3d8), 0x640);
+       mmio_write_32((0xf712c000 + 0x018), 0x0);
+       mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+       mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+       mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+       mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+       data = mmio_read_32((0xf712c000 + 0x078));
+       data |= 4;
+       mmio_write_32((0xf712c000 + 0x078), data);
+       mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+       data = mmio_read_32((0xf712c000 + 0x020));
+       data &= 0xfffffffe;
+       mmio_write_32((0xf712c000 + 0x020), data);
+       mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+       mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+       mmio_write_32((0xf712c000 + 0x014), 0x10);
+       data = mmio_read_32((0xf712c000 + 0x1e4));
+       data &= 0xffffff00;
+       mmio_write_32((0xf712c000 + 0x1e4), data);
+       mmio_write_32((0xf712c000 + 0x030), 0x9dd87855);
+       mmio_write_32((0xf712c000 + 0x034), 0xa7138bb);
+       mmio_write_32((0xf712c000 + 0x038), 0x20091477);
+       mmio_write_32((0xf712c000 + 0x03c), 0x84534e16);
+       mmio_write_32((0xf712c000 + 0x040), 0x3008817);
+       mmio_write_32((0xf712c000 + 0x064), 0x106c3);
+       mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+       data = mmio_read_32((0xf712c000 + 0x070));
+       data &= 0xffff0000;
+       data |= 0x305;
+       mmio_write_32((0xf712c000 + 0x070), data);
+       data = mmio_read_32((0xf712c000 + 0x048));
+       data |= 0x40000000;
+       mmio_write_32((0xf712c000 + 0x048), data);
+       data = mmio_read_32((0xf712c000 + 0x020));
+       data &= ~0x10;
+       mmio_write_32((0xf712c000 + 0x020), data);
+       data = mmio_read_32((0xf712c000 + 0x080));
+       data &= ~0x2000;
+       mmio_write_32((0xf712c000 + 0x080), data);
+       mmio_write_32((0xf712c000 + 0x270), 0x3);
+       mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+       mmio_write_32((0xf712c000 + 0x370), 0x3);
+       mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+       mmio_write_32((0xf712c000 + 0x048), 0xd0420900);
+
+       mmio_write_32((0xf7128000 + 0x040), 0x0);
+       mmio_write_32((0xf712c000 + 0x004), 0x140f);
+       do {
+               data = mmio_read_32((0xf712c000 + 0x004));
+       } while (data & 1);
+       data = mmio_read_32((0xf712c000 + 0x008));
+       if (data & 0x7fe) {
+               tf_printf("NOTICE:  " "failed to init lpddr3 rank0 dram phy\n");
+               return;
+       }
+       tf_printf("NOTICE:  " "succeed to init lpddr3 rank0 dram phy\n");
+}
+
+static void set_ddrc_800mhz(void)
+{
+       unsigned int data;
+
+       mmio_write_32((0xf7032000 + 0x580), 0x2);
+       mmio_write_32((0xf7032000 + 0x5a8), 0x1003);
+       data = mmio_read_32((0xf7032000 + 0x104));
+       data &= 0xfffffcff;
+       mmio_write_32((0xf7032000 + 0x104), data);
+
+       mmio_write_32((0xf7030000 + 0x050), 0x30);
+       mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+       mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+       mmio_write_32((0xf712c000 + 0x00c), 0x400);
+       mmio_write_32((0xf712c000 + 0x018), 0x7);
+       mmio_write_32((0xf712c000 + 0x090), 0x5400000);
+       mmio_write_32((0xf712c000 + 0x258), 0x540);
+       mmio_write_32((0xf712c000 + 0x2d8), 0x540);
+       mmio_write_32((0xf712c000 + 0x358), 0x540);
+       mmio_write_32((0xf712c000 + 0x3d8), 0x540);
+       mmio_write_32((0xf712c000 + 0x018), 0x0);
+       mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+       mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+       mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+       mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+       data = mmio_read_32((0xf712c000 + 0x078));
+       data |= 4;
+       mmio_write_32((0xf712c000 + 0x078), data);
+       mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+       data = mmio_read_32((0xf712c000 + 0x020));
+       data &= 0xfffffffe;
+       mmio_write_32((0xf712c000 + 0x020), data);
+       mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+       mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+       mmio_write_32((0xf712c000 + 0x014), 0x10);
+       data = mmio_read_32((0xf712c000 + 0x1e4));
+       data &= 0xffffff00;
+       mmio_write_32((0xf712c000 + 0x1e4), data);
+       mmio_write_32((0xf712c000 + 0x030), 0xe663ab77);
+       mmio_write_32((0xf712c000 + 0x034), 0xea952db);
+       mmio_write_32((0xf712c000 + 0x038), 0x200d1cb1);
+       mmio_write_32((0xf712c000 + 0x03c), 0xc67d0721);
+       mmio_write_32((0xf712c000 + 0x040), 0x3008aa1);
+       mmio_write_32((0xf712c000 + 0x064), 0x11a43);
+       mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+       data = mmio_read_32((0xf712c000 + 0x070));
+       data &= 0xffff0000;
+       data |= 0x507;
+       mmio_write_32((0xf712c000 + 0x070), data);
+       data = mmio_read_32((0xf712c000 + 0x048));
+       data |= 0x40000000;
+       mmio_write_32((0xf712c000 + 0x048), data);
+       data = mmio_read_32((0xf712c000 + 0x020));
+       data &= 0xffffffef;
+       mmio_write_32((0xf712c000 + 0x020), data);
+       data = mmio_read_32((0xf712c000 + 0x080));
+       data &= 0xffffdfff;
+       mmio_write_32((0xf712c000 + 0x080), data);
+       mmio_write_32((0xf712c000 + 0x270), 0x3);
+       mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+       mmio_write_32((0xf712c000 + 0x370), 0x3);
+       mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+       mmio_write_32((0xf712c000 + 0x048), 0xd0420900);
+
+       mmio_write_32((0xf7128000 + 0x040), 0x2001);
+       mmio_write_32((0xf712c000 + 0x004), 0x140f);
+       do {
+               data = mmio_read_32((0xf712c000 + 0x004));
+       } while (data & 1);
+       data = mmio_read_32((0xf712c000 + 0x008));
+       if (data & 0x7fe) {
+               WARN("failed to init lpddr3 rank0 dram phy\n");
+               return;
+       }
+}
+
+static void ddrc_common_init(int ddr800)
+{
+       unsigned int data;
+
+       mmio_write_32((0xf7120000 + 0x020), 0x1);
+       mmio_write_32((0xf7120000 + 0x100), 0x1700);
+       mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+       mmio_write_32((0xf7121400 + 0x104), 0xf);
+       mmio_write_32((0xf7121800 + 0x104), 0xf);
+       mmio_write_32((0xf7121800 + 0x104), 0xf);
+       mmio_write_32((0xf7121c00 + 0x104), 0xf);
+       mmio_write_32((0xf7122000 + 0x104), 0xf);
+       mmio_write_32((0xf7128000 + 0x02c), 0x6);
+       mmio_write_32((0xf7128000 + 0x020), 0x1);
+       mmio_write_32((0xf7128000 + 0x028), 0x310201);
+       mmio_write_32((0xf712c000 + 0x1e4), 0xfe007600);
+       mmio_write_32((0xf7128000 + 0x01c), 0xaf001);
+
+
+       data = mmio_read_32((0xf7128000 + 0x280));
+       data |= 1 << 7;
+       mmio_write_32((0xf7128000 + 0x280), data);
+       mmio_write_32((0xf7128000 + 0x244), 0x3);
+
+       if (ddr800)
+               mmio_write_32((0xf7128000 + 0x240), 167 * 400000 / 1024);
+       else
+               mmio_write_32((0xf7128000 + 0x240), 167 * 533000 / 1024);
+
+       data = mmio_read_32((0xf712c000 + 0x080));
+       data &= 0xffff;
+       data |= 0x4002000;
+       mmio_write_32((0xf712c000 + 0x080), data);
+       mmio_write_32((0xf7128000 + 0x000), 0x0);
+       do {
+               data = mmio_read_32((0xf7128000 + 0x294));
+       } while (data & 1);
+       mmio_write_32((0xf7128000 + 0x000), 0x2);
+}
+
+
+static int dienum_det_and_rowcol_cfg(void)
+{
+       unsigned int data;
+
+       mmio_write_32((0xf7128000 + 0x210), 0x87);
+       mmio_write_32((0xf7128000 + 0x218), 0x10000);
+       mmio_write_32((0xf7128000 + 0x00c), 0x1);
+       do {
+               data = mmio_read_32((0xf7128000 + 0x00c));
+       } while (data & 1);
+       data = mmio_read_32((0xf7128000 + 0x4a8)) & 0xfc;
+       switch (data) {
+               case 0x18:
+                       mmio_write_32((0xf7128000 + 0x060), 0x132);
+                       mmio_write_32((0xf7128000 + 0x064), 0x132);
+                       mmio_write_32((0xf7120000 + 0x100), 0x1600);
+                       mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+                       break;
+               case 0x1c:
+                       mmio_write_32((0xf7128000 + 0x060), 0x142);
+                       mmio_write_32((0xf7128000 + 0x064), 0x142);
+                       mmio_write_32((0xf7120000 + 0x100), 0x1700);
+                       mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+                       break;
+               case 0x58:
+                       mmio_write_32((0xf7128000 + 0x060), 0x133);
+                       mmio_write_32((0xf7128000 + 0x064), 0x133);
+                       mmio_write_32((0xf7120000 + 0x100), 0x1700);
+                       mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+                       break;
+               default:
+                       break;
+       }
+       if (!data)
+               return -22;
+       return 0;
+}
+
+static int detect_ddr_chip_info(void)
+{
+       unsigned int data, mr5, mr6, mr7;
+
+       mmio_write_32((0xf7128000 + 0x210), 0x57);
+       mmio_write_32((0xf7128000 + 0x218), 0x10000);
+       mmio_write_32((0xf7128000 + 0x00c), 0x1);
+
+       do {
+               data = mmio_read_32((0xf7128000 + 0x00c));
+       } while (data & 1);
+
+       data = mmio_read_32((0xf7128000 + 0x4a8));
+       mr5 = data & 0xff;
+       switch (mr5) {
+               case 1:
+                       tf_printf("INFO:    " "Samsung DDR\n");
+                       break;
+               case 6:
+                       tf_printf("INFO:    " "Hynix DDR\n");
+                       break;
+               case 3:
+                       tf_printf("INFO:    " "Elpida DDR\n");
+                       break;
+               default:
+                       tf_printf("INFO:    " "DDR from other vendors\n");
+                       break;
+       }
+
+       mmio_write_32((0xf7128000 + 0x210), 0x67);
+       mmio_write_32((0xf7128000 + 0x218), 0x10000);
+       mmio_write_32((0xf7128000 + 0x00c), 0x1);
+       do {
+               data = mmio_read_32((0xf7128000 + 0x00c));
+       } while (data & 1);
+       data = mmio_read_32((0xf7128000 + 0x4a8));
+       mr6 = data & 0xff;
+       mmio_write_32((0xf7128000 + 0x210), 0x77);
+       mmio_write_32((0xf7128000 + 0x218), 0x10000);
+       mmio_write_32((0xf7128000 + 0x00c), 0x1);
+       do {
+               data = mmio_read_32((0xf7128000 + 0x00c));
+       } while (data & 1);
+       data = mmio_read_32((0xf7128000 + 0x4a8));
+       mr7 = data & 0xff;
+       data = mr5 + (mr6 << 8) + (mr7 << 16);
+       return data;
+}
+
+int lpddr3_freq_init(int ddr800)
+{
+       unsigned int data;
+
+       if (ddr800) {
+               set_ddrc_800mhz();
+               tf_printf("INFO:    " "%s, set ddrc 800mhz\n", __func__);
+       } else {
+               set_ddrc_533mhz();
+               tf_printf("INFO:    " "%s, set ddrc 533mhz\n", __func__);
+       }
+
+       data = cat_533mhz_800mhz();
+       if (data)
+               tf_printf("NOTICE:  " "fail to set eye diagram\n");
+
+       mmio_write_32((0xf712c000 + 0x004), 0xf1);
+       if (ddr800)
+               mmio_write_32((0xf7128000 + 0x050), 0x100023);
+       else
+               mmio_write_32((0xf7128000 + 0x050), 0x100123);
+       mmio_write_32((0xf7128000 + 0x060), 0x133);
+       mmio_write_32((0xf7128000 + 0x064), 0x133);
+       mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+       if (ddr800) {
+               mmio_write_32((0xf7128000 + 0x100), 0x755a9d12);
+               mmio_write_32((0xf7128000 + 0x104), 0x1753b055);
+               mmio_write_32((0xf7128000 + 0x108), 0x7401505f);
+               mmio_write_32((0xf7128000 + 0x10c), 0x578ca244);
+               mmio_write_32((0xf7128000 + 0x110), 0x10700000);
+               mmio_write_32((0xf7128000 + 0x114), 0x13141306);
+       } else {
+               mmio_write_32((0xf7128000 + 0x100), 0xb77b6718);
+               mmio_write_32((0xf7128000 + 0x104), 0x1e82a071);
+               mmio_write_32((0xf7128000 + 0x108), 0x9501c07e);
+               mmio_write_32((0xf7128000 + 0x10c), 0xaf50c255);
+               mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+               mmio_write_32((0xf7128000 + 0x114), 0x13181908);
+       }
+       mmio_write_32((0xf7128000 + 0x118), 0x44);
+       do {
+               data = mmio_read_32((0xf712c000 + 0x004));
+       } while (data & 1);
+
+       data = mmio_read_32((0xf712c000 + 0x008));
+       if (data & 0x7fe) {
+               tf_printf("NOTICE:  " "fail to init ddr3 rank0\n");
+               return -14;
+       }
+       tf_printf("INFO:    " "init ddr3 rank0\n");
+       ddrx_rdet();
+       ddrx_wdet();
+
+       data = mmio_read_32((0xf712c000 + 0x048));
+       data |= 1;
+       mmio_write_32((0xf712c000 + 0x048), data);
+       mmio_write_32((0xf712c000 + 0x004), 0x21);
+       do {
+               data = mmio_read_32((0xf712c000 + 0x004));
+       } while (data & 1);
+
+       data = mmio_read_32((0xf712c000 + 0x008));
+       if (data & 0x7fe)
+               tf_printf("NOTICE:  " "ddr3 rank1 init failure\n");
+       else
+               tf_printf("INFO:    " "ddr3 rank1 init pass\n");
+
+       data = mmio_read_32((0xf712c000 + 0x048));
+       data &= ~0xf;
+       mmio_write_32((0xf712c000 + 0x048), data);
+       return 0;
+}
+
+static void init_ddr(int ddr800)
+{
+       unsigned int data;
+       int ret;
+
+
+       data = mmio_read_32((0xf7032000 + 0x030));
+       data |= 1;
+       mmio_write_32((0xf7032000 + 0x030), data);
+       data = mmio_read_32((0xf7032000 + 0x010));
+       data |= 1;
+       mmio_write_32((0xf7032000 + 0x010), data);
+       
+       udelay(100);
+       do {
+               data = mmio_read_32((0xf7032000 + 0x030));
+               data &= 3 << 28;
+       } while (data != (3 << 28));
+       do {
+               data = mmio_read_32((0xf7032000 + 0x010));
+               data &= 3 << 28;
+       } while (data != (3 << 28));
+
+       ret = lpddr3_freq_init(ddr800);
+       if (ret)
+               return;
+}
+
+static void init_ddrc_qos(void)
+{
+       unsigned int port, data;
+
+       mmio_write_32((0xf7124000 + 0x088), 1);
+
+
+       port = 0;
+       mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210);
+       mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x11111111);
+       mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x11111111);
+       mmio_write_32((0xf7120000 + 0x400 + 0 * 0x10), 0x001d0007);
+
+
+       for (port = 3; port <= 4; port++) {
+               mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210);
+               mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x77777777);
+               mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x77777777);
+       }
+
+
+       port = 1;
+       mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000);
+       mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567);
+       mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567);
+
+
+       mmio_write_32((0xf7124000 + 0x1f0), 0);
+       mmio_write_32((0xf7124000 + 0x0bc), 0x3020100);
+       mmio_write_32((0xf7124000 + 0x0d0), 0x3020100);
+       mmio_write_32((0xf7124000 + 0x1f4), 0x01000100);
+       mmio_write_32((0xf7124000 + 0x08c + 0 * 4), 0xd0670402);
+       mmio_write_32((0xf7124000 + 0x068 + 0 * 4), 0x31);
+       mmio_write_32((0xf7124000 + 0x000), 0x7);
+
+       data = mmio_read_32((0xf7124000 + 0x09c));
+       data &= ~0xff0000;
+       data |= 0x400000;
+       mmio_write_32((0xf7124000 + 0x09c), data);
+       data = mmio_read_32((0xf7124000 + 0x0ac));
+       data &= ~0xff0000;
+       data |= 0x400000;
+       mmio_write_32((0xf7124000 + 0x0ac), data);
+       port = 2;
+       mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000);
+       mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567);
+       mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567);
+
+
+       mmio_write_32((0xf7124000 + 0x09c), 0xff7fff);
+       mmio_write_32((0xf7124000 + 0x0a0), 0xff);
+       mmio_write_32((0xf7124000 + 0x0ac), 0xff7fff);
+       mmio_write_32((0xf7124000 + 0x0b0), 0xff);
+       mmio_write_32((0xf7124000 + 0x0bc), 0x3020100);
+       mmio_write_32((0xf7124000 + 0x0d0), 0x3020100);
+}
+
+static void init_mmc0_pll(void)
+{
+       unsigned int data;
+
+       data = hi6553_read_8(0x084);
+       data |= 0x7;
+       hi6553_write_8(0x084, data);
+
+       /* select SYSPLL as the source of MMC0 */
+       /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
+       mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21);
+       do {
+               data = mmio_read_32(PERI_SC_CLK_SEL0);
+       } while (!(data & (1 << 5)));
+       /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
+       mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29);
+       do {
+               data = mmio_read_32(PERI_SC_CLK_SEL0);
+       } while (data & (1 << 13));
+
+       mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0));
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+       } while (!(data & (1 << 0)));
+
+       data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
+       data |= 1 << 1;
+       mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
+
+       do {
+               mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb);
+               data = mmio_read_32(PERI_SC_CLKCFG8BIT1);
+       } while ((data & 0xb) != 0xb);
+}
+
+static void reset_mmc0_clk(void)
+{
+       unsigned int data;
+
+       /* disable mmc0 bus clock */
+       mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+       } while (data & PERI_CLK0_MMC0);
+       /* enable mmc0 bus clock */
+       mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+       } while (!(data & PERI_CLK0_MMC0));
+       /* reset mmc0 clock domain */
+       mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
+
+       /* bypass mmc0 clock phase */
+       data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
+       data |= 3;
+       mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
+
+       /* disable low power */
+       data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
+       data |= 1 << 3;
+       mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+       } while (!(data & PERI_RST0_MMC0));
+
+       /* unreset mmc0 clock domain */
+       mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+       } while (data & PERI_RST0_MMC0);
+}
+
+static void init_media_clk(void)
+{
+       unsigned int data, value;
+
+       data = mmio_read_32(PMCTRL_MEDPLLCTRL);
+       data |= 1;
+       mmio_write_32(PMCTRL_MEDPLLCTRL, data);
+
+       for (;;) {
+               data = mmio_read_32(PMCTRL_MEDPLLCTRL);
+               value = 1 << 28;
+               if ((data & value) == value)
+                       break;
+       }
+
+       data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
+       data = 1 << 10;
+       mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
+}
+
+static void init_mmc1_pll(void)
+{
+       uint32_t data;
+
+       /* select SYSPLL as the source of MMC1 */
+       /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
+       mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27);
+       do {
+               data = mmio_read_32(PERI_SC_CLK_SEL0);
+       } while (!(data & (1 << 11)));
+       /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
+       mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30);
+       do {
+               data = mmio_read_32(PERI_SC_CLK_SEL0);
+       } while (data & (1 << 14));
+
+       mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1));
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+       } while (!(data & (1 << 1)));
+
+       data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
+       data |= 1 << 2;
+       mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
+
+       do {
+               /* 1.2GHz / 50 = 24MHz */
+               mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7));
+               data = mmio_read_32(PERI_SC_CLKCFG8BIT2);
+       } while ((data & 0x31) != 0x31);
+}
+
+static void reset_mmc1_clk(void)
+{
+       unsigned int data;
+
+       /* disable mmc1 bus clock */
+       mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+       } while (data & PERI_CLK0_MMC1);
+       /* enable mmc1 bus clock */
+       mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+       } while (!(data & PERI_CLK0_MMC1));
+       /* reset mmc1 clock domain */
+       mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1);
+
+       /* bypass mmc1 clock phase */
+       data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
+       data |= 3 << 2;
+       mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
+
+       /* disable low power */
+       data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
+       data |= 1 << 4;
+       mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+       } while (!(data & PERI_RST0_MMC1));
+
+       /* unreset mmc0 clock domain */
+       mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+       } while (data & PERI_RST0_MMC1);
+}
+
+static void ddr_phy_reset(void)
+{
+       mmio_write_32(0xf7030340, 0xa000);
+       mmio_write_32(0xf7030344, 0xa000);
+}
+
+void hi6220_pll_init(void)
+{
+       uint32_t data;
+
+       init_pll();
+       init_freq();
+
+       /*
+        * Init DDR with 533MHz. Otherwise, DDR initialization
+        * may fail on 800MHz on some boards.
+        */
+       ddr_phy_reset();
+       init_ddr(0);
+       /* Init DDR with 800MHz. */
+       ddr_phy_reset();
+       init_ddr(1);
+
+
+       ddrc_common_init(1);
+       dienum_det_and_rowcol_cfg();
+       detect_ddr_chip_info();
+
+       data = mmio_read_32(0xf7032000 + 0x010);
+       data &= ~0x1;
+       mmio_write_32(0xf7032000 + 0x010, data);
+       data = mmio_read_32(0xf7032000 + 0x010);
+
+       /*
+        * Test memory access. Do not use address 0x0 because the compiler
+        * may assume it is not a valid address and generate incorrect code
+        * (GCC 4.9.1 without -fno-delete-null-pointer-checks for instance).
+        */
+       mmio_write_32(0x4, 0xa5a55a5a);
+       INFO("ddr test value:0x%x\n", mmio_read_32(0x4));
+       init_ddrc_qos();
+
+       init_mmc0_pll();
+       reset_mmc0_clk();
+       init_media_clk();
+
+       dsb();
+
+       init_mmc1_pll();
+       reset_mmc1_clk();
+}
diff --git a/plat/hikey/usb.c b/plat/hikey/usb.c
new file mode 100644 (file)
index 0000000..2184bec
--- /dev/null
@@ -0,0 +1,1472 @@
+/*
+ * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
+ * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <debug.h>
+#include <gpio.h>
+#include <hi6220.h>
+#include <mmio.h>
+#include <partitions.h>
+#include <platform_def.h>
+#include <sp804_timer.h>
+#include <string.h>
+#include <usb.h>
+#include "hikey_private.h"
+
+#define NUM_ENDPOINTS                  16
+
+#define USB_BLOCK_HIGH_SPEED_SIZE      512
+
+struct ep_type {
+       unsigned char           active;
+       unsigned char           busy;
+       unsigned char           done;
+       unsigned int            rc;
+       unsigned int            size;
+};
+
+struct usb_endpoint {
+       struct usb_endpoint     *next;
+       unsigned int            maxpkt;
+       struct usb_request      *req;
+       unsigned char           num;
+       unsigned char           in;
+};
+
+struct usb_config_bundle {
+       struct usb_config_descriptor config;
+       struct usb_interface_descriptor interface;
+       struct usb_endpoint_descriptor ep1;
+       struct usb_endpoint_descriptor ep2;
+} __attribute__ ((packed));
+
+static setup_packet ctrl_req[NUM_ENDPOINTS]
+__attribute__ ((section("tzfw_coherent_mem")));
+static unsigned char ctrl_resp[2]
+__attribute__ ((section("tzfw_coherent_mem")));
+
+static struct ep_type endpoints[NUM_ENDPOINTS]
+__attribute__ ((section("tzfw_coherent_mem")));
+
+dwc_otg_dev_dma_desc_t dma_desc
+__attribute__ ((section("tzfw_coherent_mem")));
+dwc_otg_dev_dma_desc_t dma_desc_ep0
+__attribute__ ((section("tzfw_coherent_mem")));
+dwc_otg_dev_dma_desc_t dma_desc_in
+__attribute__ ((section("tzfw_coherent_mem")));
+dwc_otg_dev_dma_desc_t dma_desc_addr
+__attribute__ ((section("tzfw_coherent_mem")));
+
+static struct usb_config_bundle config_bundle
+__attribute__ ((section("tzfw_coherent_mem")));
+static struct usb_device_descriptor device_descriptor
+__attribute__ ((section("tzfw_coherent_mem")));
+
+static struct usb_request rx_req
+__attribute__ ((section("tzfw_coherent_mem")));
+static struct usb_request tx_req
+__attribute__ ((section("tzfw_coherent_mem")));
+
+static struct usb_string_descriptor serial_string
+__attribute__ ((section("tzfw_coherent_mem")));
+
+static const struct usb_string_descriptor string_devicename = {
+       24,
+       USB_DT_STRING,
+       {'A', 'n', 'd', 'r', 'o', 'i', 'd', ' ', '2', '.', '0'}
+};
+
+static const struct usb_string_descriptor serial_string_descriptor = {
+       34,
+       USB_DT_STRING,
+       {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}
+};
+
+static const struct usb_string_descriptor lang_descriptor = {
+       4,
+       USB_DT_STRING,
+       {0x0409}        /* en-US */
+};
+
+static void usb_rx_cmd_complete(unsigned actual, int stat);
+static void usb_rx_data_complete(unsigned actual, int status);
+
+static unsigned int rx_desc_bytes = 0;
+static unsigned long rx_addr;
+static unsigned long rx_length;
+static unsigned int last_one = 0;
+static char *cmdbuf;
+static struct usb_endpoint ep1in, ep1out;
+static int g_usb_enum_flag = 0;
+
+int usb_need_reset = 0;
+
+static int usb_drv_port_speed(void)
+{
+       /* 2'b00 High speed (PHY clock is at 30MHz or 60MHz) */
+       return (mmio_read_32(DSTS) & 2) == 0 ? 1 : 0;
+}
+
+static void reset_endpoints(void)
+{
+       int i;
+       unsigned int data;
+
+       INFO("enter reset_endpoints.\n");
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               endpoints[i].active = 0;
+               endpoints[i].busy = 0;
+               endpoints[i].rc = -1;
+               endpoints[i].done = 1;
+       }
+
+       /* EP0 IN ACTIVE NEXT=1 */
+       mmio_write_32(DIEPCTL0, 0x8800);
+
+       /* EP0 OUT ACTIVE */
+       mmio_write_32(DOEPCTL0, 0x8000);
+
+       /* Clear any pending OTG Interrupts */
+       mmio_write_32(GOTGINT, ~0);
+
+       /* Clear any pending interrupts */
+       mmio_write_32(GINTSTS, ~0);
+       mmio_write_32(DIEPINT0, ~0);
+       mmio_write_32(DOEPINT0, ~0);
+       mmio_write_32(DIEPINT1, ~0);
+       mmio_write_32(DOEPINT1, ~0);
+
+       /* IN EP interrupt mask */
+       mmio_write_32(DIEPMSK, 0x0D);
+       /* OUT EP interrupt mask */
+       mmio_write_32(DOEPMSK, 0x0D);
+       /* Enable interrupts on Ep0 */
+       mmio_write_32(DAINTMSK, 0x00010001);
+
+       /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/
+       data = DOEPTSIZ0_SUPCNT(3) | DOEPTSIZ0_PKTCNT |
+               (64 << DOEPTSIZ0_XFERSIZE_SHIFT);
+       mmio_write_32(DOEPTSIZ0, data);
+       //notes that:the compulsive conversion is expectable.
+       dma_desc_ep0.status.b.bs = 0x3;
+       dma_desc_ep0.status.b.mtrf = 0;
+       dma_desc_ep0.status.b.sr = 0;
+       dma_desc_ep0.status.b.l = 1;
+       dma_desc_ep0.status.b.ioc = 1;
+       dma_desc_ep0.status.b.sp = 0;
+       dma_desc_ep0.status.b.bytes = 64;
+       dma_desc_ep0.buf = (unsigned long)&ctrl_req;
+       dma_desc_ep0.status.b.sts = 0;
+       dma_desc_ep0.status.b.bs = 0x0;
+       mmio_write_32(DOEPDMA0, ((unsigned long)&(dma_desc_ep0)));
+       VERBOSE("%s, &ctrl_req:%llx:%x, &dms_desc_ep0:%llx:%x\n",
+               __func__, (unsigned long)&ctrl_req, (unsigned long)&ctrl_req,
+               (unsigned long)&dma_desc_ep0, (unsigned long)&dma_desc_ep0);
+       /* EP0 OUT ENABLE CLEARNAK */
+       data = mmio_read_32(DOEPCTL0);
+       mmio_write_32(DOEPCTL0, (data | 0x84000000));
+
+       VERBOSE("exit reset_endpoints. \n");
+}
+
+static int usb_drv_request_endpoint(int type, int dir)
+{
+       int ep = 1;    /*FIXME*/
+       unsigned int newbits, data;
+
+       newbits = (type << 18) | 0x10000000;
+
+       /*
+        * (type << 18):Endpoint Type (EPType)
+        * 0x10000000:Endpoint Enable (EPEna)
+        * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.
+        * (ep<<22):TxFIFO Number (TxFNum)
+        * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.
+        */
+       if (dir) {  // IN: to host
+               data = mmio_read_32(DIEPCTL(ep));
+               data &= ~0x000c0000;
+               data |= newbits | (ep << 22) | 0x20000;
+               mmio_write_32(DIEPCTL(ep), data);
+       } else {    // OUT: to device
+               data = mmio_read_32(DOEPCTL(ep));
+               data &= ~0x000c0000;
+               data |= newbits;
+               mmio_write_32(DOEPCTL(ep), data);
+       }
+       endpoints[ep].active = 1;       // true
+
+    return ep | dir;
+}
+
+void usb_drv_release_endpoint(int ep)
+{
+       ep = ep % NUM_ENDPOINTS;
+       if (ep < 1 || ep > NUM_ENDPOINTS)
+               return;
+
+       endpoints[ep].active = 0;
+}
+
+void usb_config(void)
+{
+       unsigned int data;
+
+       INFO("enter usb_config\n");
+
+       mmio_write_32(GDFIFOCFG, DATA_FIFO_CONFIG);
+       mmio_write_32(GRXFSIZ, RX_SIZE);
+       mmio_write_32(GNPTXFSIZ, ENDPOINT_TX_SIZE);
+
+       mmio_write_32(DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);
+       mmio_write_32(DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);
+       mmio_write_32(DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);
+       mmio_write_32(DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);
+       mmio_write_32(DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);
+       mmio_write_32(DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);
+       mmio_write_32(DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);
+       mmio_write_32(DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);
+       mmio_write_32(DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);
+       mmio_write_32(DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);
+       mmio_write_32(DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);
+       mmio_write_32(DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);
+       mmio_write_32(DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);
+       mmio_write_32(DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);
+       mmio_write_32(DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);
+
+       /*Init global csr register.*/
+
+       /*
+        * set Periodic TxFIFO Empty Level,
+        * Non-Periodic TxFIFO Empty Level,
+        * Enable DMA, Unmask Global Intr
+        */
+       INFO("USB: DMA mode.\n");
+       mmio_write_32(GAHBCFG, GAHBCFG_CTRL_MASK);
+
+       /*select 8bit UTMI+, ULPI Inerface*/
+       INFO("USB ULPI PHY\n");
+       mmio_write_32(GUSBCFG, 0x2400);
+
+       /* Detect usb work mode,host or device? */
+       do {
+               data = mmio_read_32(GINTSTS);
+       } while (data & GINTSTS_CURMODE_HOST);
+       VERBOSE("Enter device mode\n");
+       udelay(3);
+
+       /*Init global and device mode csr register.*/
+       /*set Non-Zero-Length status out handshake */
+       data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;
+       mmio_write_32(DCFG, data);
+
+       /* Interrupt unmask: IN event, OUT event, bus reset */
+       data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE |
+              GINTSTS_USBRST | GINTSTS_USBSUSP | GINTSTS_ERLYSUSP |
+              GINTSTS_GOUTNAKEFF;
+       mmio_write_32(GINTMSK, data);
+
+       do {
+               data = mmio_read_32(GINTSTS) & GINTSTS_ENUMDONE;
+       } while (data);
+       VERBOSE("USB Enum Done.\n");
+
+       /* Clear any pending OTG Interrupts */
+       mmio_write_32(GOTGINT, ~0);
+       /* Clear any pending interrupts */
+       mmio_write_32(GINTSTS, ~0);
+       mmio_write_32(GINTMSK, ~0);
+       data = mmio_read_32(GOTGINT);
+       data &= ~0x3000;
+       mmio_write_32(GOTGINT, data);
+       /*endpoint settings cfg*/
+       reset_endpoints();
+
+       udelay(1);
+
+       /*init finish. and ready to transfer data*/
+
+       /* Soft Disconnect */
+       mmio_write_32(DCTL, 0x802);
+       udelay(10000);
+
+       /* Soft Reconnect */
+       mmio_write_32(DCTL, 0x800);
+       VERBOSE("exit usb_config.\n");
+}
+
+void usb_drv_set_address(int address)
+{
+       unsigned int cfg;
+
+       cfg = mmio_read_32(DCFG);
+       cfg &= ~0x7F0;
+       cfg |= address << 4;
+       mmio_write_32(DCFG, cfg);       // 0x7F0: device address
+}
+
+static void ep_send(int ep, const void *ptr, int len)
+{
+       unsigned int data;
+
+       endpoints[ep].busy = 1;         // true
+       endpoints[ep].size = len;
+
+       /* EPx OUT ACTIVE */
+       data = mmio_read_32(DIEPCTL(ep)) | DXEPCTL_USBACTEP;
+       mmio_write_32(DIEPCTL(ep), data);
+
+       /* set DMA Address */
+       if (!len) {
+               /* send one empty packet */
+               dma_desc_in.buf = 0;
+       } else {
+               dma_desc_in.buf = (unsigned long)ptr;
+       }
+       dma_desc_in.status.b.bs = 0x3;
+       dma_desc_in.status.b.l = 1;
+       dma_desc_in.status.b.ioc = 1;
+       dma_desc_in.status.b.sp = 1;
+       dma_desc_in.status.b.sts = 0;
+       dma_desc_in.status.b.bs = 0x0;
+       dma_desc_in.status.b.bytes = len;
+       mmio_write_32(DIEPDMA(ep), (unsigned long)&dma_desc_in);
+
+       data = mmio_read_32(DIEPCTL(ep));
+       data |= DXEPCTL_EPENA | DXEPCTL_CNAK | DXEPCTL_NEXTEP(ep + 1);
+       mmio_write_32(DIEPCTL(ep), data);
+}
+
+void usb_drv_stall(int endpoint, char stall, char in)
+{
+       unsigned int data;
+
+       /*
+        * STALL Handshake (Stall)
+        */
+
+       data = mmio_read_32(DIEPCTL(endpoint));
+       if (in) {
+               if (stall)
+                       mmio_write_32(DIEPCTL(endpoint), data | 0x00200000);
+               else
+                       mmio_write_32(DIEPCTL(endpoint), data & ~0x00200000);
+       } else {
+               if (stall)
+                       mmio_write_32(DOEPCTL(endpoint), data | 0x00200000);
+               else
+                       mmio_write_32(DOEPCTL(endpoint), data & ~0x00200000);
+       }
+}
+
+int usb_drv_send_nonblocking(int endpoint, const void *ptr, int len)
+{
+       VERBOSE("%s, endpoint = %d, ptr = 0x%x, Len=%d.\n",
+               __func__, endpoint, ptr, len);
+       ep_send(endpoint % NUM_ENDPOINTS, ptr, len);
+       return 0;
+}
+
+void usb_drv_cancel_all_transfers(void)
+{
+       reset_endpoints();
+}
+
+int hiusb_epx_tx(unsigned ep, void *buf, unsigned len)
+{
+       int blocksize,packets;
+       unsigned int epints;
+       unsigned int cycle = 0;
+       unsigned int data;
+
+       endpoints[ep].busy = 1;         //true
+       endpoints[ep].size = len;
+
+       while (mmio_read_32(GINTSTS) & 0x40) {
+               data = mmio_read_32(DCTL);
+               data |= 0x100;
+               mmio_write_32(DCTL, data);
+       }
+
+       data = mmio_read_32(DIEPCTL(ep));
+       data |= 0x08000000;
+       mmio_write_32(DIEPCTL(ep), data);
+
+       /* EPx OUT ACTIVE */
+       mmio_write_32(DIEPCTL(ep), data | 0x8000);
+       if (!ep) {
+               blocksize = 64;
+       } else {
+               blocksize = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
+       }
+       packets = (len + blocksize - 1) / blocksize;
+
+       if (!len) {
+               /* one empty packet */
+               mmio_write_32(DIEPTSIZ(ep), 1 << 19);
+               /* NULL */
+               dma_desc_in.status.b.bs = 0x3;
+               dma_desc_in.status.b.l = 1;
+               dma_desc_in.status.b.ioc = 1;
+               dma_desc_in.status.b.sp = last_one;
+               dma_desc_in.status.b.bytes = 0;
+               dma_desc_in.buf = 0;
+               dma_desc_in.status.b.sts = 0;
+               dma_desc_in.status.b.bs = 0x0;
+               mmio_write_32(DIEPDMA(ep), (unsigned long)&dma_desc_in);
+       } else {
+               mmio_write_32(DIEPTSIZ(ep), len | (packets << 19));
+               dma_desc_in.status.b.bs = 0x3;
+               dma_desc_in.status.b.l = 1;
+               dma_desc_in.status.b.ioc = 1;
+               dma_desc_in.status.b.sp = last_one;
+               dma_desc_in.status.b.bytes = len;
+               dma_desc_in.buf = (unsigned long)buf;
+               dma_desc_in.status.b.sts = 0;
+               dma_desc_in.status.b.bs = 0x0;
+               mmio_write_32(DIEPDMA(ep), (unsigned long)&dma_desc_in);
+       }
+
+       cycle = 0;
+       while(1){
+               data = mmio_read_32(DIEPINT(ep));
+               if ((data & 0x2000) || (cycle > 10000)) {
+                       if (cycle > 10000) {
+                               NOTICE("Phase 2:ep(%d) status, DIEPCTL(%d) is [0x%x],"
+                                      "DTXFSTS(%d) is [0x%x], DIEPINT(%d) is [0x%x],"
+                                      "DIEPTSIZ(%d) is [0x%x] GINTSTS is [0x%x]\n",
+                                       ep, ep, data,
+                                       ep, mmio_read_32(DTXFSTS(ep)),
+                                       ep, mmio_read_32(DIEPINT(ep)),
+                                       ep, mmio_read_32(DIEPTSIZ(ep)),
+                                       mmio_read_32(GINTSTS));
+                       }
+                       break;
+               }
+
+               cycle++;
+               udelay(10);
+       }
+       VERBOSE("ep(%d) enable, DIEPCTL(%d) is [0x%x], DTXFSTS(%d) is [0x%x],"
+               "DIEPINT(%d) is [0x%x], DIEPTSIZ(%d) is [0x%x] \n",
+               ep, ep, mmio_read_32(DIEPCTL(ep)),
+               ep, mmio_read_32(DTXFSTS(ep)),
+               ep, mmio_read_32(DIEPINT(ep)),
+               ep, mmio_read_32(DIEPTSIZ(ep)));
+
+       __asm__ volatile("dsb   sy\n"
+                        "isb   sy\n");
+       data = mmio_read_32(DIEPCTL(ep));
+       data |= 0x84000000;
+       /* epena & cnak*/
+       mmio_write_32(DIEPCTL(ep), data);
+       __asm__ volatile("dsb   sy\n"
+                        "isb   sy\n");
+
+       cycle = 0;
+       while (1) {
+               epints = mmio_read_32(DIEPINT(ep)) & 1;
+               if ((mmio_read_32(GINTSTS) & 0x40000) && epints) {
+                       VERBOSE("Tx succ:ep(%d), DTXFSTS(%d) is [0x%x] \n",
+                               ep, ep, mmio_read_32(DTXFSTS(ep)));
+                       mmio_write_32(DIEPINT(ep), epints);
+                       if (endpoints[ep].busy) {
+                               endpoints[ep].busy = 0;//false
+                               endpoints[ep].rc = 0;
+                               endpoints[ep].done = 1;//true
+                       }
+                       break;
+               }
+               cycle++;
+               udelay(10);
+               VERBOSE("loop for intr: ep(%d), DIEPCTL(%d) is [0x%x], ",
+                       "DTXFSTS(%d) is [0x%x], DIEPINT(%d) is [0x%x] \n",
+                       ep, ep, mmio_read_32(DIEPCTL(ep)),
+                       ep, mmio_read_32(DTXFSTS(ep)),
+                       ep, mmio_read_32(DIEPINT(ep)));
+
+               if (cycle > 1000000) {
+                       WARN("Wait IOC intr over 10s! USB will reset\n");
+                       usb_need_reset = 1;
+                       return 1;
+               }
+       }
+
+       cycle = 0;
+       while (1) {
+               if ((mmio_read_32(DIEPINT(ep)) & 0x2000) || (cycle > 100000)) {
+                       if (cycle > 100000){
+                               WARN("all wait cycle is [%d]\n",cycle);
+                       }
+                       break;
+               }
+
+               cycle++;
+               udelay(10);
+       }
+
+       return 0;
+}
+
+int hiusb_epx_rx(unsigned ep, void *buf, unsigned len)
+{
+       unsigned int blocksize = 0, data;
+       int packets;
+
+       VERBOSE("ep%d rx, len = 0x%x, buf = 0x%x.\n", ep, len, buf);
+
+       endpoints[ep].busy = 1;//true
+       /* EPx UNSTALL */
+       data = mmio_read_32(DOEPCTL(ep)) & ~0x00200000;
+       mmio_write_32(DOEPCTL(ep), data);
+       /* EPx OUT ACTIVE */
+       data = mmio_read_32(DOEPCTL(ep)) | 0x8000;
+       mmio_write_32(DOEPCTL(ep), data);
+
+       blocksize = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
+       packets = (len + blocksize - 1) / blocksize;
+
+#define MAX_RX_PACKET 0x3FF
+
+       /*Max recv packets is 1023*/
+       if (packets > MAX_RX_PACKET) {
+               endpoints[ep].size = MAX_RX_PACKET * blocksize;
+               len = MAX_RX_PACKET * blocksize;
+       } else {
+               endpoints[ep].size = len;
+       }
+
+       if (!len) {
+               /* one empty packet */
+               mmio_write_32(DOEPTSIZ(ep), 1 << 19);
+               //NULL  /* dummy address */
+               dma_desc.status.b.bs = 0x3;
+               dma_desc.status.b.mtrf = 0;
+               dma_desc.status.b.sr = 0;
+               dma_desc.status.b.l = 1;
+               dma_desc.status.b.ioc = 1;
+               dma_desc.status.b.sp = 0;
+               dma_desc.status.b.bytes = 0;
+               dma_desc.buf = 0;
+               dma_desc.status.b.sts = 0;
+               dma_desc.status.b.bs = 0x0;
+
+               mmio_write_32(DOEPDMA(ep), (unsigned long)&dma_desc);
+       } else {
+               if (len >= blocksize * 64) {
+                       rx_desc_bytes = blocksize*64;
+               } else {
+                       rx_desc_bytes = len;
+               }
+               VERBOSE("rx len %d, rx_desc_bytes %d \n",len,rx_desc_bytes);
+               dma_desc.status.b.bs = 0x3;
+               dma_desc.status.b.mtrf = 0;
+               dma_desc.status.b.sr = 0;
+               dma_desc.status.b.l = 1;
+               dma_desc.status.b.ioc = 1;
+               dma_desc.status.b.sp = 0;
+               dma_desc.status.b.bytes = rx_desc_bytes;
+               dma_desc.buf = (unsigned long)buf;
+               dma_desc.status.b.sts = 0;
+               dma_desc.status.b.bs = 0x0;
+
+               mmio_write_32(DOEPDMA(ep), (unsigned long)&dma_desc);
+       }
+       /* EPx OUT ENABLE CLEARNAK */
+       data = mmio_read_32(DOEPCTL(ep));
+       data |= 0x84000000;
+       mmio_write_32(DOEPCTL(ep), data);
+       return 0;
+}
+
+int usb_queue_req(struct usb_endpoint *ept, struct usb_request *req)
+{
+       if (ept->in)
+               hiusb_epx_tx(ept->num, req->buf, req->length);
+       else
+               hiusb_epx_rx(ept->num, req->buf, req->length);
+
+       return 0;
+}
+
+static void rx_cmd(void)
+{
+       struct usb_request *req = &rx_req;
+       req->buf = cmdbuf;
+       req->length = RX_REQ_LEN;
+       req->complete = usb_rx_cmd_complete;
+       usb_queue_req(&ep1out, req);
+}
+
+static void rx_data(void)
+{
+       struct usb_request *req = &rx_req;
+
+       req->buf = (void *)((unsigned long) rx_addr);
+       req->length = rx_length;
+       req->complete = usb_rx_data_complete;
+       usb_queue_req(&ep1out, req);
+}
+
+void tx_status(const char *status)
+{
+       struct usb_request *req = &tx_req;
+       int len = strlen(status);
+
+       memcpy(req->buf, status, (unsigned int)len);
+       req->length = (unsigned int)len;
+       req->complete = 0;
+       usb_queue_req(&ep1in, req);
+}
+
+void fastboot_tx_status(const char *status)
+{
+       tx_status(status);
+       rx_cmd();
+}
+
+void tx_dump_page(const char *ptr, int len)
+{
+       struct usb_request *req = &tx_req;
+
+       memcpy(req->buf, ptr, (unsigned int)len);
+       req->length = (unsigned int)len;
+       req->complete = 0;
+       usb_queue_req(&ep1in, req);
+}
+
+
+static void usb_rx_data_complete(unsigned actual, int status)
+{
+
+       if(status != 0)
+               return;
+
+       if(actual > rx_length) {
+               actual = rx_length;
+       }
+
+       rx_addr += actual;
+       rx_length -= actual;
+
+       if(rx_length > 0) {
+               rx_data();
+       } else {
+               tx_status("OKAY");
+               rx_cmd();
+       }
+}
+
+static void usb_status(unsigned online, unsigned highspeed)
+{
+       if (online) {
+               INFO("usb: online (%s)\n", highspeed ? "highspeed" : "fullspeed");
+               rx_cmd();
+       }
+}
+
+void usb_handle_control_request(setup_packet* req)
+{
+       const void* addr = NULL;
+       int size = -1;
+       int i;
+       int maxpacket;
+       unsigned int data;
+       char *serialno;
+       struct usb_endpoint_descriptor epx;
+       struct usb_config_bundle const_bundle = {
+               .config = {
+                       .bLength        = sizeof(struct usb_config_descriptor),
+                       .bDescriptorType        = USB_DT_CONFIG,
+                       .wTotalLength   = sizeof(struct usb_config_descriptor) +
+                               sizeof(struct usb_interface_descriptor) +
+                               sizeof(struct usb_endpoint_descriptor) *
+                               USB_NUM_ENDPOINTS,
+                       .bNumInterfaces         = 1,
+                       .bConfigurationValue    = 1,
+                       .iConfiguration         = 0,
+                       .bmAttributes           = USB_CONFIG_ATT_ONE,
+                       .bMaxPower              = 0x80
+               },
+               .interface = {
+                       .bLength        = sizeof(struct usb_interface_descriptor),
+                       .bDescriptorType        = USB_DT_INTERFACE,
+                       .bInterfaceNumber       = 0,
+                       .bAlternateSetting      = 0,
+                       .bNumEndpoints          = USB_NUM_ENDPOINTS,
+                       .bInterfaceClass        = USB_CLASS_VENDOR_SPEC,
+                       .bInterfaceSubClass     = 0x42,
+                       .bInterfaceProtocol     = 0x03,
+                       .iInterface             = 0
+               }
+       };
+
+       /* avoid to hang on accessing unaligned memory */
+       struct usb_endpoint_descriptor const_ep1 = {
+               .bLength        = sizeof(struct usb_endpoint_descriptor),
+               .bDescriptorType        = USB_DT_ENDPOINT,
+               .bEndpointAddress       = 0x81,
+               .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+               .wMaxPacketSize         = 0,
+               .bInterval              = 0
+       };
+
+       struct usb_endpoint_descriptor const_ep2 = {
+               .bLength        = sizeof(struct usb_endpoint_descriptor),
+               .bDescriptorType        = USB_DT_ENDPOINT,
+               .bEndpointAddress       = 0x01,
+               .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+               .wMaxPacketSize         = 0,
+               .bInterval              = 1
+       };
+
+       struct usb_device_descriptor const_device = {
+               .bLength                = sizeof(struct usb_device_descriptor),
+               .bDescriptorType        = USB_DT_DEVICE,
+               .bcdUSB                 = 0x0200,
+               .bDeviceClass           = 0,
+               .bDeviceClass           = 0,
+               .bDeviceProtocol        = 0,
+               .bMaxPacketSize0        = 0x40,
+               .idVendor               = 0x18d1,
+               .idProduct              = 0xd00d,
+               .bcdDevice              = 0x0100,
+               .iManufacturer          = 1,
+               .iProduct               = 2,
+               .iSerialNumber          = 3,
+               .bNumConfigurations     = 1
+       };
+
+       memcpy(&config_bundle, &const_bundle, sizeof(struct usb_config_bundle));
+       memcpy(&config_bundle.ep1, &const_ep1, sizeof(struct usb_endpoint_descriptor));
+       memcpy(&config_bundle.ep2, &const_ep2, sizeof(struct usb_endpoint_descriptor));
+       memcpy(&device_descriptor, &const_device,
+               sizeof(struct usb_device_descriptor));
+
+       switch (req->request) {
+       case USB_REQ_GET_STATUS:
+               if (req->type == USB_DIR_IN)
+                       ctrl_resp[0] = 1;
+               else
+                       ctrl_resp[0] = 0;
+               ctrl_resp[1] = 0;
+               addr = ctrl_resp;
+               size = 2;
+               break;
+
+       case USB_REQ_CLEAR_FEATURE:
+               if ((req->type == USB_RECIP_ENDPOINT) &&
+                   (req->value == USB_ENDPOINT_HALT))
+                       usb_drv_stall(req->index & 0xf, 0, req->index >> 7);
+               size = 0;
+               break;
+
+       case USB_REQ_SET_FEATURE:
+               size = 0;
+               break;
+
+       case USB_REQ_SET_ADDRESS:
+               size = 0;
+               usb_drv_cancel_all_transfers();     // all endpoints reset
+               usb_drv_set_address(req->value);   // set device address
+               break;
+
+       case USB_REQ_GET_DESCRIPTOR:
+               VERBOSE("USB_REQ_GET_DESCRIPTOR: 0x%x\n", req->value >> 8);
+               switch (req->value >> 8) {
+               case USB_DT_DEVICE:
+                       addr = &device_descriptor;
+                       size = sizeof(device_descriptor);
+                       VERBOSE("Get device descriptor.\n");
+                       break;
+
+               case USB_DT_OTHER_SPEED_CONFIG:
+               case USB_DT_CONFIG:
+                       if ((req->value >> 8) == USB_DT_CONFIG) {
+                               maxpacket = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
+                               config_bundle.config.bDescriptorType = USB_DT_CONFIG;
+                       } else {
+                               maxpacket = usb_drv_port_speed() ? 64 : USB_BLOCK_HIGH_SPEED_SIZE;
+                               config_bundle.config.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
+                       }
+                       /* avoid hang when access unaligned structure */
+                       memcpy(&epx, &config_bundle.ep1, sizeof(struct usb_endpoint_descriptor));
+                       epx.wMaxPacketSize = maxpacket;
+                       memcpy(&config_bundle.ep1, &epx, sizeof(struct usb_endpoint_descriptor));
+                       memcpy(&epx, &config_bundle.ep2, sizeof(struct usb_endpoint_descriptor));
+                       epx.wMaxPacketSize = maxpacket;
+                       memcpy(&config_bundle.ep2, &epx, sizeof(struct usb_endpoint_descriptor));
+                       addr = &config_bundle;
+                       size = sizeof(config_bundle);
+                       VERBOSE("Get config descriptor.\n");
+                       break;
+
+               case USB_DT_STRING:
+                       switch (req->value & 0xff) {
+                       case 0:
+                               addr = &lang_descriptor;
+                               size = lang_descriptor.bLength;
+                               break;
+                       case 1:
+                               addr = &string_devicename;
+                               size = 14;
+                               break;
+                       case 2:
+                               addr = &string_devicename;
+                               size = string_devicename.bLength;
+                               break;
+                       case 3:
+                               serialno = load_serialno();
+                               if (serialno == NULL) {
+                                       addr = &serial_string_descriptor;
+                                       size = serial_string_descriptor.bLength;
+                               } else {
+                                       i = 0;
+                                       memcpy((void *)&serial_string,
+                                              (void *)&serial_string_descriptor,
+                                              sizeof(serial_string));
+                                       while (1) {
+                                               serial_string.wString[i] = serialno[i];
+                                               if (serialno[i] == '\0')
+                                                       break;
+                                               i++;
+                                       }
+                                       addr = &serial_string;
+                                       size = serial_string.bLength;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+               break;
+
+       case USB_REQ_GET_CONFIGURATION:
+               ctrl_resp[0] = 1;
+               addr = ctrl_resp;
+               size = 1;
+               break;
+
+       case USB_REQ_SET_CONFIGURATION:
+               usb_drv_cancel_all_transfers();     // call reset_endpoints  reset all EPs
+
+               usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
+               usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
+               /*
+                * 0x10088800:
+                * 1:EP enable; 8:EP type:BULK; 8:USB Active Endpoint; 8:Next Endpoint
+                */
+               data = mmio_read_32(DIEPCTL1) | 0x10088800;
+               mmio_write_32(DIEPCTL1, data);
+               data = mmio_read_32(DIEPCTL(1)) | 0x08000000;
+               mmio_write_32(DIEPCTL(1), data);
+
+               /* Enable interrupts on all endpoints */
+               mmio_write_32(DAINTMSK, 0xffffffff);
+
+               usb_status(req->value? 1 : 0, usb_drv_port_speed() ? 1 : 0);
+               size = 0;
+               VERBOSE("Set config descriptor.\n");
+
+               /* USB Ã¶¾Ù³É¹¦µã,ÖÃÉϱêʶ */
+               g_usb_enum_flag = 1;
+               break;
+
+       default:
+               break;
+       }
+
+       if (!size) {
+               usb_drv_send_nonblocking(0, 0, 0);  // send an empty packet
+       } else if (size == -1) { // stall:Applies to non-control, non-isochronous IN and OUT endpoints only.
+               usb_drv_stall(0, 1, 1);     // IN
+               usb_drv_stall(0, 1, 0);     // OUT
+       } else { // stall:Applies to control endpoints only.
+               usb_drv_stall(0, 0, 1);     // IN
+               usb_drv_stall(0, 0, 0);     // OUT
+
+               usb_drv_send_nonblocking(0, addr, size > req->length ? req->length : size);
+       }
+}
+
+/* IRQ handler */
+static void usb_poll(void)
+{
+       uint32_t ints;
+       uint32_t epints, data;
+
+       ints = mmio_read_32(GINTSTS);           /* interrupt status */
+
+
+       if ((ints & 0xc3010) == 0)
+               return;
+       /*
+        * bus reset
+        * The core sets this bit to indicate that a reset is detected on the USB.
+        */
+       if (ints & GINTSTS_USBRST) {
+               VERBOSE("bus reset intr\n");
+               /*set Non-Zero-Length status out handshake */
+               /*
+                * DCFG:This register configures the core in Device mode after power-on
+                * or after certain control commands or enumeration. Do not make changes
+                * to this register after initial programming.
+                * Send a STALL handshake on a nonzero-length status OUT transaction and
+                * do not send the received OUT packet to the application.
+                */
+               mmio_write_32(DCFG, 0x800004);
+               reset_endpoints();
+       }
+       /*
+        * enumeration done, we now know the speed
+        * The core sets this bit to indicate that speed enumeration is complete. The
+        * application must read the Device Status (DSTS) register to obtain the
+        * enumerated speed.
+        */
+       if (ints & GINTSTS_ENUMDONE) {
+               /* Set up the maximum packet sizes accordingly */
+               uint32_t maxpacket = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;  // high speed maxpacket=512
+               VERBOSE("enum done intr. Maxpacket:%d\n", maxpacket);
+               //Set Maximum In Packet Size (MPS)
+               data = mmio_read_32(DIEPCTL1) & ~0x000003ff;
+               mmio_write_32(DIEPCTL1, data | maxpacket);
+               //Set Maximum Out Packet Size (MPS)
+               data = mmio_read_32(DOEPCTL1) & ~0x000003ff;
+               mmio_write_32(DOEPCTL1, data | maxpacket);
+       }
+
+       /*
+        * IN EP event
+        * The core sets this bit to indicate that an interrupt is pending on one of the IN
+        * endpoints of the core (in Device mode). The application must read the
+        * Device All Endpoints Interrupt (DAINT) register to determine the exact
+        * number of the IN endpoint on which the interrupt occurred, and then read
+        * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to
+        * determine the exact cause of the interrupt. The application must clear the
+        * appropriate status bit in the corresponding DIEPINTn register to clear this bit.
+        */
+       if (ints & GINTSTS_IEPINT) {
+               epints = mmio_read_32(DIEPINT0);
+               mmio_write_32(DIEPINT0, epints);
+
+               //VERBOSE("IN EP event,ints:0x%x, DIEPINT0:%x, DAINT:%x, DAINTMSK:%x.\n",
+               //      ints, epints, mmio_read_32(DAINT), mmio_read_32(DAINTMSK));
+               if (epints & 0x1) { /* Transfer Completed Interrupt (XferCompl) */
+                       VERBOSE("TX completed.DIEPTSIZ(0) = 0x%x.\n", mmio_read_32(DIEPTSIZ0));
+                       /*FIXME,Maybe you can use bytes*/
+                       /*int bytes = endpoints[0].size - (DIEPTSIZ(0) & 0x3FFFF);*/ //actual transfer
+                       if (endpoints[0].busy) {
+                               endpoints[0].busy = 0;//false
+                               endpoints[0].rc = 0;
+                               endpoints[0].done = 1;//true
+                       }
+               }
+               if (epints & 0x4) { /* AHB error */
+                       WARN("AHB error on IN EP0.\n");
+               }
+
+               if (epints & 0x8) { /* Timeout */
+                       WARN("Timeout on IN EP0.\n");
+                       if (endpoints[0].busy) {
+                               endpoints[0].busy = 1;//false
+                               endpoints[0].rc = 1;
+                               endpoints[0].done = 1;//true
+                       }
+               }
+       }
+
+       /*
+        * OUT EP event
+        * The core sets this bit to indicate that an interrupt is pending on one of the
+        * OUT endpoints of the core (in Device mode). The application must read the
+        * Device All Endpoints Interrupt (DAINT) register to determine the exact
+        * number of the OUT endpoint on which the interrupt occurred, and then read
+        * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register
+        * to determine the exact cause of the interrupt. The application must clear the
+        * appropriate status bit in the corresponding DOEPINTn register to clear this bit.
+        */
+       if (ints & GINTSTS_OEPINT) {
+               /* indicates the status of an endpoint
+                * with respect to USB- and AHB-related events. */
+               epints = mmio_read_32(DOEPINT(0));
+               //VERBOSE("OUT EP event,ints:0x%x, DOEPINT0:%x, DAINT:%x, DAINTMSK:%x.\n",
+               //      ints, epints, mmio_read_32(DAINT), mmio_read_32(DAINTMSK));
+               if (epints) {
+                       mmio_write_32(DOEPINT(0), epints);
+                       /* Transfer completed */
+                       if (epints & DXEPINT_XFERCOMPL) {
+                               /*FIXME,need use bytes*/
+                               VERBOSE("EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n",
+                                       mmio_read_32(DOEPTSIZ(0)));
+                               if (endpoints[0].busy) {
+                                       endpoints[0].busy = 0;
+                                       endpoints[0].rc = 0;
+                                       endpoints[0].done = 1;
+                               }
+                       }
+                       if (epints & DXEPINT_AHBERR) { /* AHB error */
+                               WARN("AHB error on OUT EP0.\n");
+                       }
+
+                       /*
+                        * IN Token Received When TxFIFO is Empty (INTknTXFEmp)
+                        * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
+                        * was empty. This interrupt is asserted on the endpoint for which the IN token
+                        * was received.
+                        */
+                       if (epints & DXEPINT_SETUP) { /* SETUP phase done */
+                               VERBOSE("Setup phase \n");
+                               data = mmio_read_32(DIEPCTL(0)) | DXEPCTL_SNAK;
+                               mmio_write_32(DIEPCTL(0), data);
+                               data = mmio_read_32(DOEPCTL(0)) | DXEPCTL_SNAK;
+                               mmio_write_32(DOEPCTL(0), data);
+                               /*clear IN EP intr*/
+                               mmio_write_32(DIEPINT(0), ~0);
+                               usb_handle_control_request((setup_packet *)&ctrl_req);
+                       }
+
+                       /* Make sure EP0 OUT is set up to accept the next request */
+                       /* memset(p_ctrlreq, 0, NUM_ENDPOINTS*8); */
+                       data = DOEPTSIZ0_SUPCNT(3) | DOEPTSIZ0_PKTCNT |
+                               (64 << DOEPTSIZ0_XFERSIZE_SHIFT);
+                       mmio_write_32(DOEPTSIZ0, data);
+                       /*
+                        * IN Token Received When TxFIFO is Empty (INTknTXFEmp)
+                        * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
+                        * was empty. This interrupt is asserted on the endpoint for which the IN token
+                        * was received.
+                        */
+                       // notes that:the compulsive conversion is expectable.
+                       // Holds the start address of the external memory for storing or fetching endpoint data.
+                       dma_desc_ep0.status.b.bs = 0x3;
+                       dma_desc_ep0.status.b.mtrf = 0;
+                       dma_desc_ep0.status.b.sr = 0;
+                       dma_desc_ep0.status.b.l = 1;
+                       dma_desc_ep0.status.b.ioc = 1;
+                       dma_desc_ep0.status.b.sp = 0;
+                       dma_desc_ep0.status.b.bytes = 64;
+                       dma_desc_ep0.buf = (uintptr_t)&ctrl_req;
+                       dma_desc_ep0.status.b.sts = 0;
+                       dma_desc_ep0.status.b.bs = 0x0;
+                       mmio_write_32(DOEPDMA0, (uintptr_t)&dma_desc_ep0);
+                       // endpoint enable; clear NAK
+                       mmio_write_32(DOEPCTL0, 0x84000000);
+               }
+
+               epints = mmio_read_32(DOEPINT1);
+               if(epints) {
+                       mmio_write_32(DOEPINT1, epints);
+                       VERBOSE("OUT EP1: epints :0x%x,DOEPTSIZ1 :0x%x.\n",epints, mmio_read_32(DOEPTSIZ1));
+                       /* Transfer Completed Interrupt (XferCompl);Transfer completed */
+                       if (epints & DXEPINT_XFERCOMPL) {
+                               /* ((readl(DOEPTSIZ(1))) & 0x7FFFF is Transfer Size (XferSize) */
+                               /*int bytes = (p_endpoints + 1)->size - ((readl(DOEPTSIZ(1))) & 0x7FFFF);*/
+                               int bytes = rx_desc_bytes - dma_desc.status.b.bytes;
+                               VERBOSE("OUT EP1: recv %d bytes \n",bytes);
+                               if (endpoints[1].busy) {
+                                       endpoints[1].busy = 0;
+                                       endpoints[1].rc = 0;
+                                       endpoints[1].done = 1;
+                                       rx_req.complete(bytes, 0);
+                               }
+                       }
+
+                       if (epints & DXEPINT_AHBERR) { /* AHB error */
+                               WARN("AHB error on OUT EP1.\n");
+                       }
+                       if (epints & DXEPINT_SETUP) { /* SETUP phase done */
+                               WARN("SETUP phase done  on OUT EP1.\n");
+                       }
+               }
+       }
+       /* write to clear interrupts */
+       mmio_write_32(GINTSTS, ints);
+}
+
+#define EYE_PATTERN    0x70533483
+
+/*
+* pico phy exit siddq, nano phy enter siddq,
+* and open the clock of pico phy and dvc,
+*/
+static void dvc_and_picophy_init_chip(void)
+{
+       unsigned int data;
+
+       /* enable USB clock */
+       mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_USBOTG);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+       } while ((data & PERI_CLK0_USBOTG) == 0);
+
+
+       /* out of reset */
+       mmio_write_32(PERI_SC_PERIPH_RSTDIS0,
+                     PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
+                     PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K);
+       do {
+               data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+               data &= PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
+                       PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K;
+       } while (data);
+
+       mmio_write_32(PERI_SC_PERIPH_CTRL8, EYE_PATTERN);
+
+       /* configure USB PHY */
+       data = mmio_read_32(PERI_SC_PERIPH_CTRL4);
+       /* make PHY out of low power mode */
+       data &= ~PERI_CTRL4_PICO_SIDDQ;
+       /* detect VBUS by external circuit, switch D+ to 1.5KOhm pullup */
+       data |= PERI_CTRL4_PICO_VBUSVLDEXTSEL | PERI_CTRL4_PICO_VBUSVLDEXT;
+       data &= ~PERI_CTRL4_FPGA_EXT_PHY_SEL;
+       /* select PHY */
+       data &= ~PERI_CTRL4_OTG_PHY_SEL;
+       mmio_write_32(PERI_SC_PERIPH_CTRL4, data);
+
+       udelay(1000);
+
+       data = mmio_read_32(PERI_SC_PERIPH_CTRL5);
+       data &= ~PERI_CTRL5_PICOPHY_BC_MODE;
+       mmio_write_32(PERI_SC_PERIPH_CTRL5, data);
+    
+       udelay(20000);
+}
+
+int init_usb(void)
+{
+       static int init_flag = 0;
+       uint32_t        data;
+
+       if (init_flag == 0) {
+               memset(&ctrl_req, 0, sizeof(setup_packet));
+               memset(&ctrl_resp, 0, 2);
+               memset(&endpoints, 0, sizeof(struct ep_type) * NUM_ENDPOINTS);
+               memset(&dma_desc, 0, sizeof(struct dwc_otg_dev_dma_desc));
+               memset(&dma_desc_ep0, 0, sizeof(struct dwc_otg_dev_dma_desc));
+               memset(&dma_desc_in, 0, sizeof(struct dwc_otg_dev_dma_desc));
+       }
+
+       VERBOSE("Pico PHY and DVC init start.\n");
+
+       dvc_and_picophy_init_chip();
+       VERBOSE("Pico PHY and DVC init done.\n");
+
+       /* wait for OTG AHB master idle */
+       do {
+               data = mmio_read_32(GRSTCTL) & GRSTCTL_AHBIDLE;
+       } while (data == 0);
+       VERBOSE("Reset usb controller\n");
+
+       /* OTG: Assert software reset */
+       mmio_write_32(GRSTCTL, GRSTCTL_CSFTRST);
+
+       /* wait for OTG to ack reset */
+       while (mmio_read_32(GRSTCTL) & GRSTCTL_CSFTRST);
+
+       /* wait for OTG AHB master idle */
+       while ((mmio_read_32(GRSTCTL) & GRSTCTL_AHBIDLE) == 0);
+
+       VERBOSE("Reset usb controller done\n");
+
+       usb_config();
+       VERBOSE("exit usb_init()\n");
+       return 0;
+}
+
+#define LOCK_STATE_LOCKED              0
+#define LOCK_STATE_UNLOCKED            1
+#define LOCK_STATE_RELOCKED            2
+
+#define FB_MAX_FILE_SIZE               (256 * 1024 * 1024)
+
+static struct ptentry *flash_ptn = NULL;
+
+static void fb_getvar(char *cmdbuf)
+{
+       char response[64];
+       char part_name[32];
+       int bytes;
+       struct ptentry *ptn = 0;
+
+       if (!strncmp(cmdbuf + 7, "max-download-size", 17)) {
+               bytes = sprintf(response, "OKAY0x%08x",
+                               FB_MAX_FILE_SIZE);
+               response[bytes] = '\0';
+               tx_status(response);
+               rx_cmd();
+       } else if (!strncmp(cmdbuf + 7, "partition-type:", 15)) {
+               bytes = sprintf(part_name, "%s", cmdbuf + 22);
+               ptn = find_ptn(part_name);
+               if (ptn == NULL) {
+                       bytes = sprintf(response, "FAIL%s",
+                                       "invalid partition");
+                       response[bytes] = '\0';
+                       flash_ptn = NULL;
+               } else {
+                       bytes = sprintf(response, "OKAY");
+                       response[bytes] = '\0';
+                       flash_ptn = ptn;
+               }
+               tx_status(response);
+               rx_cmd();
+       } else if (!strncmp(cmdbuf + 7, "serialno", 8)) {
+               bytes = sprintf(response, "OKAY%s",
+                               load_serialno());
+               response[bytes] = '\0';
+               tx_status(response);
+               rx_cmd();
+       } else {
+               bytes = sprintf(response, "FAIL%s",
+                                       "unknown var");
+               response[bytes] = '\0';
+               tx_status(response);
+               rx_cmd();
+       }
+}
+
+/* FIXME: do not support endptr yet */
+static unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+       unsigned long step, data;
+       int i;
+
+       if (base == 0)
+               step = 10;
+       else if ((base < 2) || (base > 36)) {
+               VERBOSE("%s: invalid base %d\n", __func__, base);
+               return 0;
+       } else
+               step = base;
+
+       for (i = 0, data = 0; ; i++) {
+               if (nptr[i] == '\0')
+                       break;
+               else if (!isalpha(nptr[i]) && !isdigit(nptr[i])) {
+                       VERBOSE("%s: invalid string %s at %d [%x]\n",
+                               __func__, nptr, i, nptr[i]);
+                       return 0;
+               } else {
+                       data *= step;
+                       if (isupper(nptr[i]))
+                               data += nptr[i] - 'A' + 10;
+                       else if (islower(nptr[i]))
+                               data += nptr[i] - 'a' + 10;
+                       else if (isdigit(nptr[i]))
+                               data += nptr[i] - '0';
+               }
+       }
+       return data;
+}
+
+static void fb_serialno(char *cmdbuf)
+{
+       struct random_serial_num random;
+
+       generate_serialno(&random);
+       flush_random_serialno((unsigned long)&random, sizeof(random));
+}
+
+static int fb_assigned_sn(char *cmdbuf)
+{
+       struct random_serial_num random;
+       int ret;
+
+       ret = assign_serialno(cmdbuf, &random);
+       if (ret < 0)
+               return ret;
+       flush_random_serialno((unsigned long)&random, sizeof(random));
+       return 0;
+}
+
+#define FB_DOWNLOAD_BASE       0x20000000
+
+static unsigned long fb_download_base, fb_download_size;
+
+static void fb_download(char *cmdbuf)
+{
+       char response[64];
+       int bytes;
+
+       if (!flash_ptn) {
+               bytes = sprintf(response, "FAIL%s",
+                               "invalid partition");
+               response[bytes] = '\0';
+               tx_status(response);
+               rx_cmd();
+       } else {
+               rx_addr = FB_DOWNLOAD_BASE;
+               rx_length = strtoul(cmdbuf + 9, NULL, 16);
+               fb_download_base = rx_addr;
+               fb_download_size = rx_length;
+               if (rx_length > FB_MAX_FILE_SIZE) {
+                       bytes = sprintf(response, "FAIL%s",
+                                       "file is too large");
+                       response[bytes] = '\0';
+                       tx_status(response);
+                       rx_cmd();
+               } else {
+                       bytes = sprintf(response, "DATA%08x",
+                                       rx_length);
+                       VERBOSE("start:0x%x, length:0x%x, res:%s\n",
+                               rx_addr, rx_length, response);
+                       response[bytes] = '\0';
+                       tx_status(response);
+                       rx_data();
+               }
+       }
+}
+
+static void fb_flash(char *cmdbuf)
+{
+       flush_user_images(cmdbuf + 6, fb_download_base, fb_download_size);
+       tx_status("OKAY");
+       rx_cmd();
+}
+
+static void fb_reboot(char *cmdbuf)
+{
+       /* Send the system reset request */
+       mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
+
+       wfi();
+       panic();
+}
+
+static void usb_rx_cmd_complete(unsigned actual, int stat)
+{
+       if(stat != 0) return;
+
+       if(actual > 4095)
+               actual = 4095;
+       cmdbuf[actual] = 0;
+
+       INFO("cmd :%s\n",cmdbuf);
+
+       if(memcmp(cmdbuf, (void *)"reboot", 6) == 0) {
+               tx_status("OKAY");
+               fb_reboot(cmdbuf);
+               return;
+       } else if (!memcmp(cmdbuf, (void *)"getvar:", 7)) {
+               fb_getvar(cmdbuf);
+               return;
+       } else if (!memcmp(cmdbuf, (void *)"download:", 9)) {
+               fb_download(cmdbuf);
+               return;
+       } else if(memcmp(cmdbuf, (void *)"erase:", 6) == 0) {
+       } else if(memcmp(cmdbuf, (void *)"flash:", 6) == 0) {
+               INFO("recog updatefile\n");
+               fb_flash(cmdbuf);
+               return;
+       } else if(memcmp(cmdbuf, (void *)"boot", 4) == 0) {
+               INFO(" - OKAY\n");
+
+               return;
+       } else if (memcmp(cmdbuf, (void *)"oem serialno", 12) == 0) {
+               if (*(cmdbuf + 12) == '\0') {
+                       fb_serialno(cmdbuf);
+                       tx_status("OKAY");
+                       rx_cmd();
+                       return;
+               } else if (memcmp(cmdbuf + 12, (void *)" set", 4) == 0) {
+                       if (fb_assigned_sn(cmdbuf + 16) == 0) {
+                               tx_status("OKAY");
+                               rx_cmd();
+                               return;
+                       }
+               }
+       } else if (memcmp(cmdbuf, (void *)"oem led", 7) == 0) {
+               if ((*(cmdbuf + 7) >= '1') && (*(cmdbuf + 7) <= '4')) {
+                       int led;
+                       led = *(cmdbuf + 7) - '0';
+                       if (memcmp(cmdbuf + 8, (void *)" on", 3) == 0) {
+                               gpio_set_value(31 + led, 1);
+                               tx_status("OKAY");
+                               rx_cmd();
+                               return;
+                       } else if (memcmp(cmdbuf + 8, (void *)" off", 4) == 0) {
+                               gpio_set_value(31 + led, 0);
+                               tx_status("OKAY");
+                               rx_cmd();
+                               return;
+                       }
+               }
+       }
+
+       tx_status("FAILinvalid command");
+       rx_cmd();
+}
+
+static void usbloader_init(void)
+{
+       VERBOSE("enter usbloader_init\n");
+
+       /*usb sw and hw init*/
+       init_usb();
+
+       /*alloc and init sth for transfer*/
+       ep1in.num = BULK_IN_EP;
+       ep1in.in = 1;
+       ep1in.req = NULL;
+       ep1in.maxpkt = MAX_PACKET_LEN;
+       ep1in.next = &ep1in;
+       ep1out.num = BULK_OUT_EP;
+       ep1out.in = 0;
+       ep1out.req = NULL;
+       ep1out.maxpkt = MAX_PACKET_LEN;
+       ep1out.next = &ep1out;
+       cmdbuf = (char *)(rx_req.buf);
+
+       VERBOSE("exit usbloader_init\n");
+}
+
+void usb_reinit()
+{
+       if (usb_need_reset)
+       {
+               usb_need_reset = 0;
+               init_usb();
+       }
+}
+
+void usb_download(void)
+{
+       usbloader_init();
+       INFO("Enter downloading mode. Please run fastboot command on Host.\n");
+       for (;;) {
+               usb_poll();
+               usb_reinit();
+       }
+}
diff --git a/plat/juno/aarch64/bl1_plat_helpers.S b/plat/juno/aarch64/bl1_plat_helpers.S
new file mode 100644 (file)
index 0000000..3054eab
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include "../juno_def.h"
+
+       .globl  platform_is_primary_cpu
+       .globl  platform_get_entrypoint
+       .globl  platform_cold_boot_init
+       .globl  plat_secondary_cold_boot_setup
+
+       /* -----------------------------------------------------
+        * unsigned int platform_is_primary_cpu (unsigned int mpid);
+        *
+        * Given the mpidr say whether this cpu is the primary
+        * cpu (applicable ony after a cold boot)
+        * -----------------------------------------------------
+        */
+func platform_is_primary_cpu
+       mov     x9, x30
+       bl      platform_get_core_pos
+       ldr     x1, =SCP_BOOT_CFG_ADDR
+       ldr     x1, [x1]
+       ubfx    x1, x1, #PRIMARY_CPU_SHIFT, #PRIMARY_CPU_MASK
+       cmp     x0, x1
+       cset    x0, eq
+       ret     x9
+
+       /* -----------------------------------------------------
+        * void plat_secondary_cold_boot_setup (void);
+        *
+        * This function performs any platform specific actions
+        * needed for a secondary cpu after a cold reset e.g
+        * mark the cpu's presence, mechanism to place it in a
+        * holding pen etc.
+        * -----------------------------------------------------
+        */
+func plat_secondary_cold_boot_setup
+       /* Juno todo: Implement secondary CPU cold boot setup on Juno */
+cb_panic:
+       b       cb_panic
+
+
+       /* -----------------------------------------------------
+        * void platform_get_entrypoint (unsigned int mpid);
+        *
+        * Main job of this routine is to distinguish between
+        * a cold and warm boot.
+        * On a cold boot the secondaries first wait for the
+        * platform to be initialized after which they are
+        * hotplugged in. The primary proceeds to perform the
+        * platform initialization.
+        * On a warm boot, each cpu jumps to the address in its
+        * mailbox.
+        *
+        * TODO: Not a good idea to save lr in a temp reg
+        * -----------------------------------------------------
+        */
+func platform_get_entrypoint
+       mov     x9, x30 // lr
+       bl      platform_get_core_pos
+       ldr     x1, =TRUSTED_MAILBOXES_BASE
+       lsl     x0, x0, #TRUSTED_MAILBOX_SHIFT
+       ldr     x0, [x1, x0]
+       ret     x9
+
+
+       /* -----------------------------------------------------
+        * void platform_cold_boot_init (bl1_main function);
+        *
+        * Routine called only by the primary cpu after a cold
+        * boot to perform early platform initialization
+        * -----------------------------------------------------
+        */
+func platform_cold_boot_init
+       mov     x20, x0
+
+       /* ---------------------------------------------
+        * Give ourselves a small coherent stack to
+        * ease the pain of initializing the MMU and
+        * CCI in assembler
+        * ---------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_set_coherent_stack
+
+       /* ---------------------------------------------
+        * 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
+
+       /* ---------------------------------------------
+        * Give ourselves a stack allocated in Normal
+        * -IS-WBWA memory
+        * ---------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_set_stack
+
+       /* ---------------------------------------------
+        * Jump to the main function. Returning from it
+        * is a terminal error.
+        * ---------------------------------------------
+        */
+       blr     x20
+
+cb_init_panic:
+       b       cb_init_panic
diff --git a/plat/juno/aarch64/juno_common.c b/plat/juno/aarch64/juno_common.c
new file mode 100644 (file)
index 0000000..27d4c8f
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <xlat_tables.h>
+#include "../juno_def.h"
+
+#define MAP_MHU_SECURE MAP_REGION_FLAT(MHU_SECURE_BASE,                \
+                                       MHU_SECURE_SIZE,                \
+                                       (MHU_PAYLOAD_CACHED ?           \
+                                        MT_MEMORY : MT_DEVICE)         \
+                                       | MT_RW | MT_SECURE)
+
+#define MAP_FLASH      MAP_REGION_FLAT(FLASH_BASE,                     \
+                                       FLASH_SIZE,                     \
+                                       MT_MEMORY | MT_RO | MT_SECURE)
+
+#define MAP_IOFPGA     MAP_REGION_FLAT(IOFPGA_BASE,                    \
+                                       IOFPGA_SIZE,                    \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DEVICE0    MAP_REGION_FLAT(DEVICE0_BASE,                   \
+                                       DEVICE0_SIZE,                   \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DEVICE1    MAP_REGION_FLAT(DEVICE1_BASE,                   \
+                                       DEVICE1_SIZE,                   \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_NS_DRAM    MAP_REGION_FLAT(DRAM_NS_BASE,                   \
+                                       DRAM_NS_SIZE,                   \
+                                       MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_TSP_MEM    MAP_REGION_FLAT(TSP_SEC_MEM_BASE,               \
+                                       TSP_SEC_MEM_SIZE,               \
+                                       MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+#if IMAGE_BL1
+static const mmap_region_t juno_mmap[] = {
+       MAP_MHU_SECURE,
+       MAP_FLASH,
+       MAP_IOFPGA,
+       MAP_DEVICE0,
+       MAP_DEVICE1,
+       {0}
+};
+#endif
+#if IMAGE_BL2
+static const mmap_region_t juno_mmap[] = {
+       MAP_MHU_SECURE,
+       MAP_FLASH,
+       MAP_IOFPGA,
+       MAP_DEVICE0,
+       MAP_DEVICE1,
+       MAP_NS_DRAM,
+       MAP_TSP_MEM,
+       {0}
+};
+#endif
+#if IMAGE_BL31
+static const mmap_region_t juno_mmap[] = {
+       MAP_MHU_SECURE,
+       MAP_IOFPGA,
+       MAP_DEVICE0,
+       MAP_DEVICE1,
+       MAP_TSP_MEM,
+       {0}
+};
+#endif
+#if IMAGE_BL32
+static const mmap_region_t juno_mmap[] = {
+       MAP_IOFPGA,
+       MAP_DEVICE0,
+       MAP_DEVICE1,
+       {0}
+};
+#endif
+
+/* Array of secure interrupts to be configured by the gic driver */
+const unsigned int irq_sec_array[] = {
+       IRQ_MHU,
+       IRQ_GPU_SMMU_0,
+       IRQ_GPU_SMMU_1,
+       IRQ_ETR_SMMU,
+       IRQ_TZC400,
+       IRQ_TZ_WDOG,
+       IRQ_SEC_PHY_TIMER,
+       IRQ_SEC_SGI_0,
+       IRQ_SEC_SGI_1,
+       IRQ_SEC_SGI_2,
+       IRQ_SEC_SGI_3,
+       IRQ_SEC_SGI_4,
+       IRQ_SEC_SGI_5,
+       IRQ_SEC_SGI_6,
+       IRQ_SEC_SGI_7
+};
+
+const unsigned int num_sec_irqs = sizeof(irq_sec_array) /
+       sizeof(irq_sec_array[0]);
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#if USE_COHERENT_MEM
+#define DEFINE_CONFIGURE_MMU_EL(_el)                           \
+       void configure_mmu_el##_el(unsigned long total_base,    \
+                                 unsigned long total_size,     \
+                                 unsigned long ro_start,       \
+                                 unsigned long ro_limit,       \
+                                 unsigned long coh_start,      \
+                                 unsigned long coh_limit)      \
+       {                                                       \
+              mmap_add_region(total_base, total_base,          \
+                              total_size,                      \
+                              MT_MEMORY | MT_RW | MT_SECURE);  \
+              mmap_add_region(ro_start, ro_start,              \
+                              ro_limit - ro_start,             \
+                              MT_MEMORY | MT_RO | MT_SECURE);  \
+              mmap_add_region(coh_start, coh_start,            \
+                              coh_limit - coh_start,           \
+                              MT_DEVICE | MT_RW | MT_SECURE);  \
+              mmap_add(juno_mmap);                             \
+              init_xlat_tables();                              \
+                                                               \
+              enable_mmu_el##_el(0);                           \
+       }
+#else
+#define DEFINE_CONFIGURE_MMU_EL(_el)                           \
+       void configure_mmu_el##_el(unsigned long total_base,    \
+                                 unsigned long total_size,     \
+                                 unsigned long ro_start,       \
+                                 unsigned long ro_limit)       \
+       {                                                       \
+              mmap_add_region(total_base, total_base,          \
+                              total_size,                      \
+                              MT_MEMORY | MT_RW | MT_SECURE);  \
+              mmap_add_region(ro_start, ro_start,              \
+                              ro_limit - ro_start,             \
+                              MT_MEMORY | MT_RO | MT_SECURE);  \
+              mmap_add(juno_mmap);                             \
+              init_xlat_tables();                              \
+                                                               \
+              enable_mmu_el##_el(0);                           \
+       }
+#endif
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(1)
+DEFINE_CONFIGURE_MMU_EL(3)
+
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+       return NS_IMAGE_OFFSET;
+}
+
+uint64_t plat_get_syscnt_freq(void)
+{
+       uint64_t counter_base_frequency;
+
+       /* Read the frequency from Frequency modes table */
+       counter_base_frequency = mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF);
+
+       /* The first entry of the frequency modes table must not be 0 */
+       if (counter_base_frequency == 0)
+               panic();
+
+       return counter_base_frequency;
+}
+
+void plat_gic_init(void)
+{
+       arm_gic_init(GICC_BASE, GICD_BASE, 0, irq_sec_array, num_sec_irqs);
+}
diff --git a/plat/juno/aarch64/plat_helpers.S b/plat/juno/aarch64/plat_helpers.S
new file mode 100644 (file)
index 0000000..37966a3
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a57.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+#include "../juno_def.h"
+
+       .globl  plat_crash_console_init
+       .globl  plat_crash_console_putc
+       .globl  plat_report_exception
+       .globl  plat_reset_handler
+       .globl  platform_get_core_pos
+       .globl  platform_mem_init
+
+       /* Define a crash console for the plaform */
+#define JUNO_CRASH_CONSOLE_BASE                PL011_UART3_BASE
+
+       /* ---------------------------------------------
+        * int plat_crash_console_init(void)
+        * Function to initialize the crash console
+        * without a C Runtime to print crash report.
+        * Clobber list : x0, x1, x2
+        * ---------------------------------------------
+        */
+func plat_crash_console_init
+       mov_imm x0, JUNO_CRASH_CONSOLE_BASE
+       mov_imm x1, PL011_UART3_CLK_IN_HZ
+       mov_imm x2, PL011_BAUDRATE
+       b       console_core_init
+
+       /* ---------------------------------------------
+        * int plat_crash_console_putc(int c)
+        * Function to print a character on the crash
+        * console without a C Runtime.
+        * Clobber list : x1, x2
+        * ---------------------------------------------
+        */
+func plat_crash_console_putc
+       mov_imm x1, JUNO_CRASH_CONSOLE_BASE
+       b       console_core_putc
+
+       /* ---------------------------------------------
+        * void plat_report_exception(unsigned int type)
+        * Function to report an unhandled exception
+        * with platform-specific means.
+        * On Juno platform, it updates the LEDs
+        * to indicate where we are
+        * ---------------------------------------------
+        */
+func plat_report_exception
+       mrs     x1, CurrentEl
+       lsr     x1, x1, #MODE_EL_SHIFT
+       lsl     x1, x1, #SYS_LED_EL_SHIFT
+       lsl     x0, x0, #SYS_LED_EC_SHIFT
+       mov     x2, #(SECURE << SYS_LED_SS_SHIFT)
+       orr     x0, x0, x2
+       orr     x0, x0, x1
+       mov     x1, #VE_SYSREGS_BASE
+       add     x1, x1, #V2M_SYS_LED
+       str     w0, [x1]
+       ret
+
+       /*
+        * Return 0 to 3 for the A53s and 4 or 5 for the A57s
+        */
+func platform_get_core_pos
+       and     x1, x0, #MPIDR_CPU_MASK
+       and     x0, x0, #MPIDR_CLUSTER_MASK
+       eor     x0, x0, #(1 << MPIDR_AFFINITY_BITS)  // swap A53/A57 order
+       add     x0, x1, x0, LSR #6
+       ret
+
+
+       /* -----------------------------------------------------
+        * void platform_mem_init(void);
+        *
+        * We don't need to carry out any memory initialization
+        * on Juno. The Secure RAM is accessible straight away.
+        * -----------------------------------------------------
+        */
+func platform_mem_init
+       ret
+
+       /* -----------------------------------------------------
+        * void plat_reset_handler(void);
+        *
+        * Before adding code in this function, refer to the
+        * guidelines in docs/firmware-design.md to determine
+        * whether the code should reside within the
+        * FIRST_RESET_HANDLER_CALL block or not.
+        *
+        * Implement workaround for defect id 831273 by enabling
+        * an event stream every 65536 cycles and set the L2 RAM
+        * latencies for Cortex-A57. This code is included only
+        * when FIRST_RESET_HANDLER_CALL is defined since it
+        * should be executed only during BL1.
+        * -----------------------------------------------------
+        */
+func plat_reset_handler
+#ifdef FIRST_RESET_HANDLER_CALL
+       /* Read the MIDR_EL1 */
+       mrs     x0, midr_el1
+       ubfx    x1, x0, MIDR_PN_SHIFT, #12
+       cmp     w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+       b.ne    1f
+
+       /* Change the L2 Data and Tag Ram latency to 3 cycles */
+       mov     x0, #(L2_DATA_RAM_LATENCY_3_CYCLES |    \
+                       (L2_TAG_RAM_LATENCY_3_CYCLES << \
+                        L2CTLR_TAG_RAM_LATENCY_SHIFT))
+       msr     L2CTLR_EL1, x0
+
+1:
+       /* ---------------------------------------------
+        * Enable the event stream every 65536 cycles
+        * ---------------------------------------------
+        */
+       mov     x0, #(0xf << EVNTI_SHIFT)
+       orr     x0, x0, #EVNTEN_BIT
+       msr     CNTKCTL_EL1, x0
+       isb
+#endif /* FIRST_RESET_HANDLER_CALL */
+       ret
diff --git a/plat/juno/bl1_plat_setup.c b/plat/juno/bl1_plat_setup.c
new file mode 100644 (file)
index 0000000..23e8592
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <cci400.h>
+#include <console.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include "../../bl1/bl1_private.h"
+#include "juno_def.h"
+#include "juno_private.h"
+
+#if USE_COHERENT_MEM
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/* Data structure which holds the extents of the trusted RAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+       return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+       const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
+
+       /* Initialize the console to provide early debug support */
+       console_init(PL011_UART2_BASE, PL011_UART2_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /*
+        * Enable CCI-400 for this cluster. No need for locks as no other cpu is
+        * active at the moment
+        */
+       cci_init(CCI400_BASE,
+                CCI400_SL_IFACE3_CLUSTER_IX,
+                CCI400_SL_IFACE4_CLUSTER_IX);
+       cci_enable_cluster_coherency(read_mpidr());
+
+       /* Allow BL1 to see the whole Trusted RAM */
+       bl1_tzram_layout.total_base = TZRAM_BASE;
+       bl1_tzram_layout.total_size = TZRAM_SIZE;
+
+       /* Calculate how much RAM BL1 is using and how much remains free */
+       bl1_tzram_layout.free_base = TZRAM_BASE;
+       bl1_tzram_layout.free_size = TZRAM_SIZE;
+       reserve_mem(&bl1_tzram_layout.free_base,
+                   &bl1_tzram_layout.free_size,
+                   BL1_RAM_BASE,
+                   bl1_size);
+
+       INFO("BL1: 0x%lx - 0x%lx [size = %u]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
+            bl1_size);
+}
+
+
+/*
+ * Address of slave 'n' security setting in the NIC-400 address region
+ * control
+ * TODO: Ideally this macro should be moved in a "nic-400.h" header file but
+ * it would be the only thing in there so it's not worth it at the moment.
+ */
+#define NIC400_ADDR_CTRL_SECURITY_REG(n)       (0x8 + (n) * 4)
+
+static void init_nic400(void)
+{
+       /*
+        * NIC-400 Access Control Initialization
+        *
+        * Define access privileges by setting each corresponding bit to:
+        *   0 = Secure access only
+        *   1 = Non-secure access allowed
+        */
+
+       /*
+        * Allow non-secure access to some SOC regions, excluding UART1, which
+        * remains secure.
+        * Note: This is the NIC-400 device on the SOC
+        */
+       mmio_write_32(SOC_NIC400_BASE +
+                     NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_USB_EHCI), ~0);
+       mmio_write_32(SOC_NIC400_BASE +
+                     NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_TLX_MASTER), ~0);
+       mmio_write_32(SOC_NIC400_BASE +
+                     NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_USB_OHCI), ~0);
+       mmio_write_32(SOC_NIC400_BASE +
+                     NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_PL354_SMC), ~0);
+       mmio_write_32(SOC_NIC400_BASE +
+                     NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_APB4_BRIDGE), ~0);
+       mmio_write_32(SOC_NIC400_BASE +
+                     NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_BOOTSEC_BRIDGE),
+                     ~SOC_NIC400_BOOTSEC_BRIDGE_UART1);
+
+       /*
+        * Allow non-secure access to some CSS regions.
+        * Note: This is the NIC-400 device on the CSS
+        */
+       mmio_write_32(CSS_NIC400_BASE +
+                     NIC400_ADDR_CTRL_SECURITY_REG(CSS_NIC400_SLAVE_BOOTSECURE),
+                     ~0);
+}
+
+
+#define PCIE_SECURE_REG                0x3000
+#define PCIE_SEC_ACCESS_MASK   ((1 << 0) | (1 << 1)) /* REG and MEM access bits */
+
+static void init_pcie(void)
+{
+       /*
+        * PCIE Root Complex Security settings to enable non-secure
+        * access to config registers.
+        */
+       mmio_write_32(PCIE_CONTROL_BASE + PCIE_SECURE_REG, PCIE_SEC_ACCESS_MASK);
+}
+
+
+/*******************************************************************************
+ * Function which will perform any remaining platform-specific setup that can
+ * occur after the MMU and data cache have been enabled.
+ ******************************************************************************/
+void bl1_platform_setup(void)
+{
+       init_nic400();
+       init_pcie();
+
+       /* Initialise the IO layer and register platform IO devices */
+       io_setup();
+
+       /* Enable and initialize the System level generic timer */
+       mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN);
+}
+
+
+/*******************************************************************************
+ * Perform the very early platform specific architecture setup here. At the
+ * moment this only does basic initialization. Later architectural setup
+ * (bl1_arch_setup()) does not do anything platform specific.
+ ******************************************************************************/
+void bl1_plat_arch_setup(void)
+{
+       configure_mmu_el3(bl1_tzram_layout.total_base,
+                         bl1_tzram_layout.total_size,
+                         TZROM_BASE,
+                         TZROM_BASE + TZROM_SIZE
+#if USE_COHERENT_MEM
+                         , BL1_COHERENT_RAM_BASE,
+                         BL1_COHERENT_RAM_LIMIT
+#endif
+                         );
+}
+
+/*******************************************************************************
+ * Before calling this function BL2 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL2 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image,
+                             entry_point_info_t *bl2_ep)
+{
+       SET_SECURITY_STATE(bl2_ep->h.attr, SECURE);
+       bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+}
diff --git a/plat/juno/bl2_plat_setup.c b/plat/juno/bl2_plat_setup.c
new file mode 100644 (file)
index 0000000..8e7b2a0
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include "juno_def.h"
+#include "juno_private.h"
+#include "scp_bootloader.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+#if USE_COHERENT_MEM
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+#endif
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL2_RO_BASE (unsigned long)(&__RO_START__)
+#define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
+
+#if USE_COHERENT_MEM
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/* Data structure which holds the extents of the trusted RAM for BL2 */
+static meminfo_t bl2_tzram_layout
+__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE)));
+
+/*******************************************************************************
+ * Structure which holds the arguments which need to be passed to BL3-1
+ ******************************************************************************/
+static bl2_to_bl31_params_mem_t bl31_params_mem;
+
+meminfo_t *bl2_plat_sec_mem_layout(void)
+{
+       return &bl2_tzram_layout;
+}
+
+/*******************************************************************************
+ * This function assigns a pointer to the memory that the platform has kept
+ * aside to pass platform specific and trusted firmware related information
+ * to BL31. This memory is allocated by allocating memory to
+ * bl2_to_bl31_params_mem_t structure which is a superset of all the
+ * structure whose information is passed to BL31
+ * NOTE: This function should be called only once and should be done
+ * before generating params to BL31
+ ******************************************************************************/
+bl31_params_t *bl2_plat_get_bl31_params(void)
+{
+       bl31_params_t *bl2_to_bl31_params;
+
+       /*
+        * Initialise the memory for all the arguments that needs to
+        * be passed to BL3-1
+        */
+       memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t));
+
+       /* Assign memory for TF related information */
+       bl2_to_bl31_params = &bl31_params_mem.bl31_params;
+       SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0);
+
+       /* Fill BL3-1 related information */
+       bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY,
+               VERSION_1, 0);
+
+       /* Fill BL3-2 related information if it exists */
+#if BL32_BASE
+       bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
+               VERSION_1, 0);
+       bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
+               VERSION_1, 0);
+#endif
+
+       /* Fill BL3-3 related information */
+       bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
+               PARAM_EP, VERSION_1, 0);
+
+       /* BL3-3 expects to receive the primary CPU MPID (through x0) */
+       bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
+
+       bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
+       SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY,
+               VERSION_1, 0);
+
+       return bl2_to_bl31_params;
+}
+
+/*******************************************************************************
+ * This function returns a pointer to the shared memory that the platform
+ * has kept to point to entry point information of BL31 to BL2
+ ******************************************************************************/
+struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
+{
+#if DEBUG
+       bl31_params_mem.bl31_ep_info.args.arg1 = JUNO_BL31_PLAT_PARAM_VAL;
+#endif
+
+       return &bl31_params_mem.bl31_ep_info;
+}
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted RAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted RAM.
+ * Copy it to a safe loaction before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+void bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+       /* Initialize the console to provide early debug support */
+       console_init(PL011_UART2_BASE, PL011_UART2_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /* Setup the BL2 memory layout */
+       bl2_tzram_layout = *mem_layout;
+
+       /* Initialise the IO layer and register platform IO devices */
+       io_setup();
+}
+
+/*******************************************************************************
+ * Perform platform specific setup, i.e. initialize the IO layer, load BL3-0
+ * image and initialise the memory location to use for passing arguments to
+ * BL3-1.
+ ******************************************************************************/
+void bl2_platform_setup(void)
+{
+       /* Initialize the secure environment */
+       plat_security_setup();
+}
+
+/* Flush the TF params and the TF plat params */
+void bl2_plat_flush_bl31_params(void)
+{
+       flush_dcache_range((unsigned long)&bl31_params_mem,
+                       sizeof(bl2_to_bl31_params_mem_t));
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl2_plat_arch_setup(void)
+{
+       configure_mmu_el1(bl2_tzram_layout.total_base,
+                         bl2_tzram_layout.total_size,
+                         BL2_RO_BASE,
+                         BL2_RO_LIMIT
+#if USE_COHERENT_MEM
+                         , BL2_COHERENT_RAM_BASE,
+                         BL2_COHERENT_RAM_LIMIT
+#endif
+                         );
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-0, i.e. anywhere
+ * in trusted RAM as long as it doesn't overwrite BL2.
+ ******************************************************************************/
+void bl2_plat_get_bl30_meminfo(meminfo_t *bl30_meminfo)
+{
+       *bl30_meminfo = bl2_tzram_layout;
+}
+
+/*******************************************************************************
+ * Transfer BL3-0 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+int bl2_plat_handle_bl30(image_info_t *bl30_image_info)
+{
+       int ret;
+
+       ret = scp_bootloader_transfer((void *)bl30_image_info->image_base,
+               bl30_image_info->image_size);
+
+       if (ret == 0)
+               INFO("BL2: BL3-0 transferred to SCP\n\r");
+       else
+               ERROR("BL2: BL3-0 transfer failure\n\r");
+
+       return ret;
+}
+
+/*******************************************************************************
+ * Before calling this function BL31 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL31 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl31_ep_info(image_info_t *bl31_image_info,
+                              entry_point_info_t *bl31_ep_info)
+{
+       SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
+       bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+                                      DISABLE_ALL_EXCEPTIONS);
+}
+
+
+/*******************************************************************************
+ * Before calling this function BL32 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL32 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
+                              entry_point_info_t *bl32_ep_info)
+{
+       SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+       /*
+       * The Secure Payload Dispatcher service is responsible for
+       * setting the SPSR prior to entry into the BL32 image.
+       */
+       bl32_ep_info->spsr = 0;
+}
+
+/*******************************************************************************
+ * Before calling this function BL33 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL33 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl33_ep_info(image_info_t *image,
+                                      entry_point_info_t *bl33_ep_info)
+{
+       unsigned long el_status;
+       unsigned int mode;
+
+       /* Figure out what mode we enter the non-secure world in */
+       el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+       el_status &= ID_AA64PFR0_ELX_MASK;
+
+       if (el_status)
+               mode = MODE_EL2;
+       else
+               mode = MODE_EL1;
+
+       /*
+        * TODO: Consider the possibility of specifying the SPSR in
+        * the FIP ToC and allowing the platform to have a say as
+        * well.
+        */
+       bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX,
+                                      DISABLE_ALL_EXCEPTIONS);
+       SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-2
+ ******************************************************************************/
+void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
+{
+       /*
+        * Populate the extents of memory available for loading BL3-2.
+        */
+       bl32_meminfo->total_base = BL32_BASE;
+       bl32_meminfo->free_base = BL32_BASE;
+       bl32_meminfo->total_size =
+                      (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+       bl32_meminfo->free_size =
+                      (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-3
+ ******************************************************************************/
+void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
+{
+       bl33_meminfo->total_base = DRAM_NS_BASE;
+       bl33_meminfo->total_size = DRAM_NS_SIZE;
+       bl33_meminfo->free_base = DRAM_NS_BASE;
+       bl33_meminfo->free_size = DRAM_NS_SIZE;
+}
diff --git a/plat/juno/bl31_plat_setup.c b/plat/juno/bl31_plat_setup.c
new file mode 100644 (file)
index 0000000..ad8ea43
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl31.h>
+#include <bl_common.h>
+#include <cci400.h>
+#include <console.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+#include "juno_def.h"
+#include "juno_private.h"
+#include "mhu.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+extern unsigned long __BL31_END__;
+
+#if USE_COHERENT_MEM
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+#endif
+
+/*
+ * The next 3 constants identify the extents of the code, RO data region and the
+ * limit of the BL3-1 image.  These addresses are used by the MMU setup code and
+ * therefore they must be page-aligned.  It is the responsibility of the linker
+ * script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL31_END (unsigned long)(&__BL31_END__)
+
+#if USE_COHERENT_MEM
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/******************************************************************************
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL3-1 from BL2.
+ ******************************************************************************/
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL3-3 corresponds to the non-secure image type
+ * while BL3-2 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+       entry_point_info_t *next_image_info;
+
+       next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+
+       /* None of the images on this platform can have 0x0 as the entrypoint */
+       if (next_image_info->pc)
+               return next_image_info;
+       else
+               return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 specific platform actions. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables. Also, BL2
+ * has flushed this information to memory, so we are guaranteed to pick up good
+ * data
+ ******************************************************************************/
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+                              void *plat_params_from_bl2)
+{
+       /* Initialize the console to provide early debug support */
+       console_init(PL011_UART2_BASE, PL011_UART2_CLK_IN_HZ, PL011_BAUDRATE);
+
+       /*
+        * Initialise the CCI-400 driver for BL31 so that it is accessible after
+        * a warm boot. BL1 should have already enabled CCI coherency for this
+        * cluster during cold boot.
+        */
+       cci_init(CCI400_BASE,
+                CCI400_SL_IFACE3_CLUSTER_IX,
+                CCI400_SL_IFACE4_CLUSTER_IX);
+
+       /*
+        * Check params passed from BL2 should not be NULL,
+        */
+       assert(from_bl2 != NULL);
+       assert(from_bl2->h.type == PARAM_BL31);
+       assert(from_bl2->h.version >= VERSION_1);
+       /*
+        * In debug builds, we pass a special value in 'plat_params_from_bl2'
+        * to verify platform parameters from BL2 to BL3-1.
+        * In release builds, it's not used.
+        */
+       assert(((unsigned long long)plat_params_from_bl2) ==
+               JUNO_BL31_PLAT_PARAM_VAL);
+
+       /*
+        * Copy BL3-2 and BL3-3 entry point information.
+        * They are stored in Secure RAM, in BL2's address space.
+        */
+       bl32_ep_info = *from_bl2->bl32_ep_info;
+       bl33_ep_info = *from_bl2->bl33_ep_info;
+}
+
+/*******************************************************************************
+ * Initialize the MHU and the GIC.
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+       unsigned int reg_val;
+
+       mhu_secure_init();
+
+       /* Initialize the gic cpu and distributor interfaces */
+       plat_gic_init();
+       arm_gic_setup();
+
+       /* Enable and initialize the System level generic timer */
+       mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN);
+
+       /* Allow access to the System counter timer module */
+       reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
+       reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
+       reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
+       mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val);
+
+       reg_val = (1 << CNTNSAR_NS_SHIFT(1));
+       mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+
+       /* Topologies are best known to the platform. */
+       plat_setup_topology();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup()
+{
+       configure_mmu_el3(BL31_RO_BASE,
+                         (BL31_END - BL31_RO_BASE),
+                         BL31_RO_BASE,
+                         BL31_RO_LIMIT
+#if USE_COHERENT_MEM
+                         ,
+                         BL31_COHERENT_RAM_BASE,
+                         BL31_COHERENT_RAM_LIMIT
+#endif
+                         );
+}
diff --git a/plat/juno/include/plat_macros.S b/plat/juno/include/plat_macros.S
new file mode 100644 (file)
index 0000000..a9d2466
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cci400.h>
+#include <gic_v2.h>
+#include "platform_def.h"
+#include "../juno_def.h"
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+       .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+       .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+       .asciz "\n"
+spacer:
+       .asciz ":\t\t0x"
+
+
+       /* ---------------------------------------------
+        * The below macro prints out relevant GIC
+        * registers whenever an unhandled exception is
+        * taken in BL3-1.
+        * Clobbers: x0 - x10, x16, sp
+        * ---------------------------------------------
+        */
+       .macro plat_print_gic_regs
+       mov_imm x16, GICD_BASE
+       mov_imm x17, GICC_BASE
+       /* Load the gicc reg list to x6 */
+       adr     x6, gicc_regs
+       /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+       ldr     w8, [x17, #GICC_HPPIR]
+       ldr     w9, [x17, #GICC_AHPPIR]
+       ldr     w10, [x17, #GICC_CTLR]
+       /* Store to the crash buf and print to console */
+       bl      str_in_crash_buf_print
+
+       /* Print the GICD_ISPENDR regs */
+       add     x7, x16, #GICD_ISPENDR
+       adr     x4, gicd_pend_reg
+       bl      asm_print_str
+gicd_ispendr_loop:
+       sub     x4, x7, x16
+       cmp     x4, #0x280
+       b.eq    exit_print_gic_regs
+       bl      asm_print_hex
+
+       adr     x4, spacer
+       bl      asm_print_str
+
+       ldr     x4, [x7], #8
+       bl      asm_print_hex
+
+       adr     x4, newline
+       bl      asm_print_str
+       b       gicd_ispendr_loop
+exit_print_gic_regs:
+       .endm
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+       .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+       /* ------------------------------------------------
+        * The below macro prints out relevant interconnect
+        * registers whenever an unhandled exception is
+        * taken in BL3-1.
+        * Clobbers: x0 - x9, sp
+        * ------------------------------------------------
+        */
+       .macro plat_print_interconnect_regs
+       adr     x6, cci_iface_regs
+       /* Store in x7 the base address of the first interface */
+       mov_imm x7, (CCI400_BASE + SLAVE_IFACE3_OFFSET)
+       ldr     w8, [x7, #SNOOP_CTRL_REG]
+       /* Store in x7 the base address of the second interface */
+       mov_imm x7, (CCI400_BASE + SLAVE_IFACE4_OFFSET)
+       ldr     w9, [x7, #SNOOP_CTRL_REG]
+       /* Store to the crash buf and print to console */
+       bl      str_in_crash_buf_print
+       .endm
diff --git a/plat/juno/include/platform_def.h b/plat/juno/include/platform_def.h
new file mode 100644 (file)
index 0000000..31c191c
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include "../juno_def.h"
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT          "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH            aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if TRUSTED_BOARD_BOOT && (IMAGE_BL1 || IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x1000
+#else
+#define PLATFORM_STACK_SIZE 0x800
+#endif
+
+#define FIRMWARE_WELCOME_STR           "Booting Trusted Firmware\n"
+
+/* Trusted Boot Firmware BL2 */
+#define BL2_IMAGE_NAME                 "bl2.bin"
+
+/* EL3 Runtime Firmware BL3-1 */
+#define BL31_IMAGE_NAME                        "bl31.bin"
+
+/* SCP Firmware BL3-0 */
+#define BL30_IMAGE_NAME                        "bl30.bin"
+
+/* Secure Payload BL3-2 (Trusted OS) */
+#define BL32_IMAGE_NAME                        "bl32.bin"
+
+/* Non-Trusted Firmware BL3-3 */
+#define BL33_IMAGE_NAME                        "bl33.bin" /* e.g. UEFI */
+
+/* Firmware Image Package */
+#define FIP_IMAGE_NAME                 "fip.bin"
+
+#if TRUSTED_BOARD_BOOT
+/* Certificates */
+# define BL2_CERT_NAME                 "bl2.crt"
+# define TRUSTED_KEY_CERT_NAME         "trusted_key.crt"
+
+# define BL30_KEY_CERT_NAME            "bl30_key.crt"
+# define BL31_KEY_CERT_NAME            "bl31_key.crt"
+# define BL32_KEY_CERT_NAME            "bl32_key.crt"
+# define BL33_KEY_CERT_NAME            "bl33_key.crt"
+
+# define BL30_CERT_NAME                        "bl30.crt"
+# define BL31_CERT_NAME                        "bl31.crt"
+# define BL32_CERT_NAME                        "bl32.crt"
+# define BL33_CERT_NAME                        "bl33.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+#define PLATFORM_CACHE_LINE_SIZE       64
+#define PLATFORM_CLUSTER_COUNT         2
+#define PLATFORM_CORE_COUNT             6
+#define PLATFORM_NUM_AFFS              (PLATFORM_CLUSTER_COUNT + \
+                                        PLATFORM_CORE_COUNT)
+#define MAX_IO_DEVICES                 3
+#define MAX_IO_HANDLES                 4
+
+/*******************************************************************************
+ * BL1 specific defines.
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 base
+ * addresses.
+ ******************************************************************************/
+#define BL1_RO_BASE                    TZROM_BASE
+#define BL1_RO_LIMIT                   (TZROM_BASE + TZROM_SIZE)
+
+/*
+ * Put BL1 RW at the top of the Trusted SRAM. BL1_RW_BASE is calculated using
+ * the current BL1 RW debug size plus a little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+#define BL1_RW_BASE                    (TZRAM_BASE + TZRAM_SIZE - 0x8000)
+#else
+#define BL1_RW_BASE                    (TZRAM_BASE + TZRAM_SIZE - 0x6000)
+#endif
+#define BL1_RW_LIMIT                   (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+#define BL2_BASE                       (BL31_BASE - 0x1D000)
+#else
+#define BL2_BASE                       (BL31_BASE - 0xC000)
+#endif
+#define BL2_LIMIT                      BL31_BASE
+
+/*******************************************************************************
+ * Load address of BL3-0 in the Juno port
+ * BL3-0 is loaded to the same place as BL3-1.  Once BL3-0 is transferred to the
+ * SCP, it is discarded and BL3-1 is loaded over the top.
+ ******************************************************************************/
+#define BL30_BASE                      BL31_BASE
+
+/*******************************************************************************
+ * BL3-1 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL3-1 debug size plus a little space for growth.
+ */
+#define BL31_BASE                      (TZRAM_BASE + TZRAM_SIZE - 0x1D000)
+#define BL31_PROGBITS_LIMIT            BL1_RW_BASE
+#define BL31_LIMIT                     (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * BL3-2 specific defines.
+ ******************************************************************************/
+
+/*
+ * The TSP can execute either from Trusted SRAM or Trusted DRAM.
+ */
+#define BL32_SRAM_BASE                  TZRAM_BASE
+#define BL32_SRAM_LIMIT                 BL31_BASE
+#define BL32_DRAM_BASE                  DRAM_SEC_BASE
+#define BL32_DRAM_LIMIT                 (DRAM_SEC_BASE + DRAM_SEC_SIZE)
+
+#if (PLAT_TSP_LOCATION_ID == PLAT_TRUSTED_SRAM_ID)
+# define TSP_SEC_MEM_BASE              TZRAM_BASE
+# define TSP_SEC_MEM_SIZE              TZRAM_SIZE
+# define BL32_BASE                     BL32_SRAM_BASE
+# define BL32_LIMIT                    BL32_SRAM_LIMIT
+//# define BL32_PROGBITS_LIMIT BL2_BASE
+#elif (PLAT_TSP_LOCATION_ID == PLAT_DRAM_ID)
+# define TSP_SEC_MEM_BASE              DRAM_SEC_BASE
+# define TSP_SEC_MEM_SIZE              DRAM_SEC_SIZE
+# define BL32_BASE                     BL32_DRAM_BASE
+# define BL32_LIMIT                    BL32_DRAM_LIMIT
+#else
+# error "Unsupported PLAT_TSP_LOCATION_ID value"
+#endif
+
+/*******************************************************************************
+ * Load address of BL3-3 in the Juno port
+ ******************************************************************************/
+#define NS_IMAGE_OFFSET                        0xE0000000
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE                        (1ull << 32)
+
+#if IMAGE_BL1 || IMAGE_BL31
+# define MAX_XLAT_TABLES               3
+#endif
+
+#if IMAGE_BL2 || IMAGE_BL32
+# define MAX_XLAT_TABLES               3
+#endif
+
+#define MAX_MMAP_REGIONS               16
+
+/*******************************************************************************
+ * ID of the secure physical generic timer interrupt used by the TSP
+ ******************************************************************************/
+#define TSP_IRQ_SEC_PHY_TIMER          IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT   6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#if !USE_COHERENT_MEM
+/*******************************************************************************
+ * Size of the per-cpu data in bytes that should be reserved in the generic
+ * per-cpu data structure for the Juno port.
+ ******************************************************************************/
+#define PLAT_PCPU_DATA_SIZE    2
+#endif
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/juno/include/platform_oid.h b/plat/juno/include/platform_oid.h
new file mode 100644 (file)
index 0000000..38aca12
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PLATFORM_OID_H_
+#define PLATFORM_OID_H_
+
+/*
+ * This is the list of the different extensions containing relevant information
+ * to establish the chain of trust.
+ *
+ * The OIDs shown here are just an example. Real OIDs should be obtained from
+ * the ITU-T.
+ */
+
+/* Non-volatile counter extensions */
+#define TZ_FW_NVCOUNTER_OID            "1.2.3.1"
+#define NTZ_FW_NVCOUNTER_OID           "1.2.3.2"
+
+/* BL2 extensions */
+#define BL2_HASH_OID                   "1.2.3.3"
+
+/* Trusted Key extensions */
+#define TZ_WORLD_PK_OID                        "1.2.3.4"
+#define NTZ_WORLD_PK_OID               "1.2.3.5"
+
+/* BL3-1 extensions */
+#define BL31_CONTENT_CERT_PK_OID       "1.2.3.6"
+#define BL31_HASH_OID                  "1.2.3.7"
+
+/* BL3-0 extensions */
+#define BL30_CONTENT_CERT_PK_OID       "1.2.3.8"
+#define BL30_HASH_OID                  "1.2.3.9"
+
+/* BL3-2 extensions */
+#define BL32_CONTENT_CERT_PK_OID       "1.2.3.10"
+#define BL32_HASH_OID                  "1.2.3.11"
+
+/* BL3-3 extensions */
+#define BL33_CONTENT_CERT_PK_OID       "1.2.3.12"
+#define BL33_HASH_OID                  "1.2.3.13"
+
+#endif /* PLATFORM_OID_H_ */
diff --git a/plat/juno/juno_def.h b/plat/juno/juno_def.h
new file mode 100644 (file)
index 0000000..8a85aec
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __JUNO_DEF_H__
+#define __JUNO_DEF_H__
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define JUNO_BL31_PLAT_PARAM_VAL       0x0f1e2d3c4b5a6978ULL
+
+/*******************************************************************************
+ * Juno memory map related constants
+ ******************************************************************************/
+#define FLASH_BASE             0x08000000
+#define FLASH_SIZE             0x04000000
+
+/* Bypass offset from start of NOR flash */
+#define BL1_ROM_BYPASS_OFFSET  0x03EC0000
+
+#ifndef TZROM_BASE
+/* Use the bypass address */
+#define TZROM_BASE             FLASH_BASE + BL1_ROM_BYPASS_OFFSET
+#endif
+/* Actual ROM size on Juno is 64 KB, but TBB requires at least 80 KB in debug
+ * mode. We can test TBB on Juno bypassing the ROM and using 128 KB of flash */
+#if TRUSTED_BOARD_BOOT
+#define TZROM_SIZE             0x00020000
+#else
+#define TZROM_SIZE             0x00010000
+#endif
+
+#define TZRAM_BASE             0x04001000
+#define TZRAM_SIZE             0x0003F000
+
+#define PLAT_TRUSTED_SRAM_ID   0
+#define PLAT_DRAM_ID           1
+
+#define MHU_SECURE_BASE                0x04000000
+#define MHU_SECURE_SIZE                0x00001000
+
+#define MHU_PAYLOAD_CACHED     0
+
+#define TRUSTED_MAILBOXES_BASE MHU_SECURE_BASE
+#define TRUSTED_MAILBOX_SHIFT  4
+
+#define EMMC_BASE              0x0c000000
+#define EMMC_SIZE              0x04000000
+
+#define PSRAM_BASE             0x14000000
+#define PSRAM_SIZE             0x02000000
+
+#define IOFPGA_BASE            0x1c000000
+#define IOFPGA_SIZE            0x03000000
+
+#define NSROM_BASE             0x1f000000
+#define NSROM_SIZE             0x00001000
+
+/* Following covers Columbus Peripherals excluding NSROM and NSRAM  */
+#define DEVICE0_BASE           0x20000000
+#define DEVICE0_SIZE           0x0e000000
+#define MHU_BASE               0x2b1f0000
+
+#define NSRAM_BASE             0x2e000000
+#define NSRAM_SIZE             0x00008000
+
+/* Following covers Juno Peripherals and PCIe expansion area */
+#define DEVICE1_BASE           0x40000000
+#define DEVICE1_SIZE           0x40000000
+#define PCIE_CONTROL_BASE      0x7ff20000
+
+#define DRAM_BASE              0x80000000
+#define DRAM_SIZE              0x80000000
+
+/*
+ * DRAM at 0x8000_0000 is divided in two regions:
+ *   - Secure DRAM (default is the top 16MB except for the last 2MB, which are
+ *     used by the SCP for DDR retraining)
+ *   - Non-Secure DRAM (remaining DRAM starting at DRAM_BASE)
+ */
+
+#define DRAM_SCP_SIZE          0x00200000
+#define DRAM_SCP_BASE          (DRAM_BASE + DRAM_SIZE - DRAM_SCP_SIZE)
+
+#define DRAM_SEC_SIZE          0x00E00000
+#define DRAM_SEC_BASE          (DRAM_SCP_BASE - DRAM_SEC_SIZE)
+
+#define DRAM_NS_BASE           DRAM_BASE
+#define DRAM_NS_SIZE           (DRAM_SIZE - DRAM_SCP_SIZE - DRAM_SEC_SIZE)
+
+/* Second region of DRAM */
+#define DRAM2_BASE             0x880000000
+#define DRAM2_SIZE             0x180000000
+
+/* Memory mapped Generic timer interfaces  */
+#define SYS_CNTCTL_BASE                0x2a430000
+#define SYS_CNTREAD_BASE       0x2a800000
+#define SYS_TIMCTL_BASE                0x2a810000
+
+/* V2M motherboard system registers & offsets */
+#define VE_SYSREGS_BASE                0x1c010000
+#define V2M_SYS_LED            0x8
+
+/*
+ * V2M sysled bit definitions. The values written to this
+ * register are defined in arch.h & runtime_svc.h. Only
+ * used by the primary cpu to diagnose any cold boot issues.
+ *
+ * SYS_LED[0]   - Security state (S=0/NS=1)
+ * SYS_LED[2:1] - Exception Level (EL3-EL0)
+ * SYS_LED[7:3] - Exception Class (Sync/Async & origin)
+ *
+ */
+#define SYS_LED_SS_SHIFT               0x0
+#define SYS_LED_EL_SHIFT               0x1
+#define SYS_LED_EC_SHIFT               0x3
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+#define GICD_BASE                      0x2c010000
+#define GICC_BASE                      0x2c02f000
+#define GICH_BASE                      0x2c04f000
+#define GICV_BASE                      0x2c06f000
+
+#define IRQ_MHU                        69
+#define IRQ_GPU_SMMU_0         71
+#define IRQ_GPU_SMMU_1         73
+#define IRQ_ETR_SMMU           75
+#define IRQ_TZC400             80
+#define IRQ_TZ_WDOG            86
+
+#define IRQ_SEC_PHY_TIMER              29
+#define IRQ_SEC_SGI_0                  8
+#define IRQ_SEC_SGI_1                  9
+#define IRQ_SEC_SGI_2                  10
+#define IRQ_SEC_SGI_3                  11
+#define IRQ_SEC_SGI_4                  12
+#define IRQ_SEC_SGI_5                  13
+#define IRQ_SEC_SGI_6                  14
+#define IRQ_SEC_SGI_7                  15
+
+/*******************************************************************************
+ * PL011 related constants
+ ******************************************************************************/
+/* FPGA UART0 */
+#define PL011_UART0_BASE               0x1c090000
+/* FPGA UART1 */
+#define PL011_UART1_BASE               0x1c0a0000
+/* SoC UART0 */
+#define PL011_UART2_BASE               0x7ff80000
+/* SoC UART1 */
+#define PL011_UART3_BASE               0x7ff70000
+
+#define PL011_BAUDRATE                 115200
+
+#define PL011_UART0_CLK_IN_HZ          24000000
+#define PL011_UART1_CLK_IN_HZ          24000000
+#define PL011_UART2_CLK_IN_HZ          7273800
+#define PL011_UART3_CLK_IN_HZ          7273800
+
+/*******************************************************************************
+ * NIC-400 related constants
+ ******************************************************************************/
+
+/* CSS NIC-400 Global Programmers View (GPV) */
+#define CSS_NIC400_BASE                0x2a000000
+
+/* The slave_bootsecure controls access to GPU, DMC and CS. */
+#define CSS_NIC400_SLAVE_BOOTSECURE            8
+
+/* SoC NIC-400 Global Programmers View (GPV) */
+#define SOC_NIC400_BASE                0x7fd00000
+
+#define SOC_NIC400_USB_EHCI    0
+#define SOC_NIC400_TLX_MASTER  1
+#define SOC_NIC400_USB_OHCI    2
+#define SOC_NIC400_PL354_SMC   3
+/*
+ * The apb4_bridge controls access to:
+ *   - the PCIe configuration registers
+ *   - the MMU units for USB, HDLCD and DMA
+ */
+#define SOC_NIC400_APB4_BRIDGE 4
+/*
+ * The bootsec_bridge controls access to a bunch of peripherals, e.g. the UARTs.
+ */
+#define SOC_NIC400_BOOTSEC_BRIDGE              5
+#define SOC_NIC400_BOOTSEC_BRIDGE_UART1         (1 << 12)
+
+/*******************************************************************************
+ * TZC-400 related constants
+ ******************************************************************************/
+#define TZC400_BASE            0x2a4a0000
+
+#define TZC400_NSAID_CCI400    0  /* Note: Same as default NSAID!! */
+#define TZC400_NSAID_PCIE      1
+#define TZC400_NSAID_HDLCD0    2
+#define TZC400_NSAID_HDLCD1    3
+#define TZC400_NSAID_USB       4
+#define TZC400_NSAID_DMA330    5
+#define TZC400_NSAID_THINLINKS 6
+#define TZC400_NSAID_AP                9
+#define TZC400_NSAID_GPU       10
+#define TZC400_NSAID_SCP       11
+#define TZC400_NSAID_CORESIGHT 12
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define CCI400_BASE                    0x2c090000
+#define CCI400_SL_IFACE3_CLUSTER_IX    1
+#define CCI400_SL_IFACE4_CLUSTER_IX    0
+
+/*******************************************************************************
+ * SCP <=> AP boot configuration
+ ******************************************************************************/
+#define SCP_BOOT_CFG_ADDR      0x04000080
+#define PRIMARY_CPU_SHIFT      8
+#define PRIMARY_CPU_MASK       0xf
+
+#endif /* __JUNO_DEF_H__ */
diff --git a/plat/juno/juno_private.h b/plat/juno/juno_private.h
new file mode 100644 (file)
index 0000000..70439e8
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __JUNO_PRIVATE_H__
+#define __JUNO_PRIVATE_H__
+
+#include <bakery_lock.h>
+#include <bl_common.h>
+#include <cpu_data.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+struct plat_pm_ops;
+struct meminfo;
+struct bl31_params;
+struct image_info;
+struct entry_point_info;
+
+/*******************************************************************************
+ * This structure represents the superset of information that is passed to
+ * BL3-1 e.g. while passing control to it from BL2 which is bl31_params
+ * and other platform specific params
+ ******************************************************************************/
+typedef struct bl2_to_bl31_params_mem {
+       struct bl31_params bl31_params;
+       struct image_info bl31_image_info;
+       struct image_info bl32_image_info;
+       struct image_info bl33_image_info;
+       struct entry_point_info bl33_ep_info;
+       struct entry_point_info bl32_ep_info;
+       struct entry_point_info bl31_ep_info;
+} bl2_to_bl31_params_mem_t;
+
+#if IMAGE_BL31
+#if USE_COHERENT_MEM
+/*
+ * These are wrapper macros to the Coherent Memory Bakery Lock API.
+ */
+#define juno_lock_init(_lock_arg)              bakery_lock_init(_lock_arg)
+#define juno_lock_get(_lock_arg)               bakery_lock_get(_lock_arg)
+#define juno_lock_release(_lock_arg)           bakery_lock_release(_lock_arg)
+
+#else
+
+/*******************************************************************************
+ * Constants that specify how many bakeries this platform implements and bakery
+ * ids.
+ ******************************************************************************/
+#define JUNO_MAX_BAKERIES      1
+#define JUNO_MHU_BAKERY_ID     0
+
+/*******************************************************************************
+ * Definition of structure which holds platform specific per-cpu data. Currently
+ * it holds only the bakery lock information for each cpu. Constants to specify
+ * how many bakeries this platform implements and bakery ids are specified in
+ * juno_def.h
+ ******************************************************************************/
+typedef struct juno_cpu_data {
+       bakery_info_t pcpu_bakery_info[JUNO_MAX_BAKERIES];
+} juno_cpu_data_t;
+
+/* Macro to define the offset of bakery_info_t in juno_cpu_data_t */
+#define JUNO_CPU_DATA_LOCK_OFFSET      __builtin_offsetof\
+                                           (juno_cpu_data_t, pcpu_bakery_info)
+
+/*******************************************************************************
+ * Helper macros for bakery lock api when using the above juno_cpu_data_t for
+ * bakery lock data structures. It assumes that the bakery_info is at the
+ * beginning of the platform specific per-cpu data.
+ ******************************************************************************/
+#define juno_lock_init(_lock_arg)              /* No init required */
+#define juno_lock_get(_lock_arg)               bakery_lock_get(_lock_arg,      \
+                                                   CPU_DATA_PLAT_PCPU_OFFSET + \
+                                                   JUNO_CPU_DATA_LOCK_OFFSET)
+#define juno_lock_release(_lock_arg)           bakery_lock_release(_lock_arg,  \
+                                                   CPU_DATA_PLAT_PCPU_OFFSET + \
+                                                   JUNO_CPU_DATA_LOCK_OFFSET)
+
+/*
+ * Ensure that the size of the Juno specific per-cpu data structure and the size
+ * of the memory allocated in generic per-cpu data for the platform are the same.
+ */
+CASSERT(PLAT_PCPU_DATA_SIZE == sizeof(juno_cpu_data_t),        \
+       juno_pcpu_data_size_mismatch);
+#endif /* __USE_COHERENT_MEM__ */
+#else
+/*
+ * Dummy wrapper macros for all other BL stages other than BL3-1
+ */
+#define juno_lock_init(_lock_arg)
+#define juno_lock_get(_lock_arg)
+#define juno_lock_release(_lock_arg)
+
+#endif /* __IMAGE_BL31__ */
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void bl1_plat_arch_setup(void);
+void bl2_plat_arch_setup(void);
+void bl31_plat_arch_setup(void);
+int platform_setup_pm(const struct plat_pm_ops **plat_ops);
+unsigned int platform_get_core_pos(unsigned long mpidr);
+void configure_mmu_el1(unsigned long total_base,
+                      unsigned long total_size,
+                      unsigned long ro_start,
+                      unsigned long ro_limit
+#if USE_COHERENT_MEM
+                      , unsigned long coh_start,
+                      unsigned long coh_limit
+#endif
+                      );
+void configure_mmu_el3(unsigned long total_base,
+                      unsigned long total_size,
+                      unsigned long ro_start,
+                      unsigned long ro_limit
+#if USE_COHERENT_MEM
+                      , unsigned long coh_start,
+                      unsigned long coh_limit
+#endif
+                      );
+void plat_report_exception(unsigned long type);
+unsigned long plat_get_ns_image_entrypoint(void);
+unsigned long platform_get_stack(unsigned long mpidr);
+uint64_t plat_get_syscnt_freq(void);
+void plat_gic_init(void);
+
+/* Declarations for plat_topology.c */
+int plat_setup_topology(void);
+int plat_get_max_afflvl(void);
+unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr);
+unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr);
+
+/* Declarations for plat_io_storage.c */
+void io_setup(void);
+int plat_get_image_source(const char *image_name,
+                         uintptr_t *dev_handle,
+                         uintptr_t *image_spec);
+
+/* Declarations for security.c */
+void plat_security_setup(void);
+
+/*
+ * Before calling this function BL2 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL2 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ */
+void bl1_plat_set_bl2_ep_info(struct image_info *image,
+                             struct entry_point_info *ep);
+
+/*
+ * Before calling this function BL3-1 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL3-1 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ */
+void bl2_plat_set_bl31_ep_info(struct image_info *image,
+                              struct entry_point_info *ep);
+
+/*
+ * Before calling this function BL3-2 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL3-2 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ */
+void bl2_plat_set_bl32_ep_info(struct image_info *image,
+                              struct entry_point_info *ep);
+
+/*
+ * Before calling this function BL3-3 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL3-3 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ */
+void bl2_plat_set_bl33_ep_info(struct image_info *image,
+                              struct entry_point_info *ep);
+
+/* Gets the memory layout for BL3-2 */
+void bl2_plat_get_bl32_meminfo(struct meminfo *mem_info);
+
+/* Gets the memory layout for BL3-3 */
+void bl2_plat_get_bl33_meminfo(struct meminfo *mem_info);
+
+#endif /* __JUNO_PRIVATE_H__ */
diff --git a/plat/juno/juno_trusted_boot.c b/plat/juno/juno_trusted_boot.c
new file mode 100644 (file)
index 0000000..e63d4b2
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include "juno_def.h"
+#include "juno_private.h"
+
+/*
+ * Check the validity of the key
+ *
+ * 0 = success, Otherwise = error
+ */
+int plat_match_rotpk(const unsigned char *key_buf, unsigned int key_len)
+{
+       /* TODO: check against the ROT key stored in the platform */
+       return 0;
+}
diff --git a/plat/juno/mhu.c b/plat/juno/mhu.c
new file mode 100644 (file)
index 0000000..c1c414c
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <bakery_lock.h>
+#include <mmio.h>
+#include "juno_def.h"
+#include "juno_private.h"
+#include "mhu.h"
+
+/* SCP MHU secure channel registers */
+#define SCP_INTR_S_STAT                0x200
+#define SCP_INTR_S_SET         0x208
+#define SCP_INTR_S_CLEAR       0x210
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT                0x300
+#define CPU_INTR_S_SET         0x308
+#define CPU_INTR_S_CLEAR       0x310
+
+#if IMAGE_BL31
+#if USE_COHERENT_MEM
+static bakery_lock_t mhu_secure_lock __attribute__ ((section("tzfw_coherent_mem")));
+#define LOCK_ARG               &mhu_secure_lock
+#else
+#define LOCK_ARG               JUNO_MHU_BAKERY_ID
+#endif /*__USE_COHERENT_MEM__ */
+#else
+#define LOCK_ARG       /* Locks required only for BL3-1 images */
+#endif /* __IMAGE_BL31__ */
+
+void mhu_secure_message_start(void)
+{
+       juno_lock_get(LOCK_ARG);
+
+       /* Make sure any previous command has finished */
+       while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) != 0)
+               ;
+}
+
+void mhu_secure_message_send(uint32_t command)
+{
+       /* Send command to SCP and wait for it to pick it up */
+       mmio_write_32(MHU_BASE + CPU_INTR_S_SET, command);
+       while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) != 0)
+               ;
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+       /* Wait for response from SCP */
+       uint32_t response;
+       while (!(response = mmio_read_32(MHU_BASE + SCP_INTR_S_STAT)))
+               ;
+
+       return response;
+}
+
+void mhu_secure_message_end(void)
+{
+       /* Clear any response we got by writing all ones to the CLEAR register */
+       mmio_write_32(MHU_BASE + SCP_INTR_S_CLEAR, 0xffffffffu);
+
+       juno_lock_release(LOCK_ARG);
+}
+
+void mhu_secure_init(void)
+{
+       juno_lock_init(LOCK_ARG);
+
+       /*
+        * Clear the CPU's INTR register to make sure we don't see a stale
+        * or garbage value and think it's a message we've already sent.
+        */
+       mmio_write_32(MHU_BASE + CPU_INTR_S_CLEAR, 0xffffffffu);
+}
diff --git a/plat/juno/mhu.h b/plat/juno/mhu.h
new file mode 100644 (file)
index 0000000..5149c82
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MHU_H__
+#define __MHU_H__
+
+#include <stdint.h>
+
+extern void mhu_secure_message_start(void);
+extern void mhu_secure_message_send(uint32_t command);
+extern uint32_t mhu_secure_message_wait(void);
+extern void mhu_secure_message_end(void);
+
+extern void mhu_secure_init(void);
+
+#endif /* __MHU_H__ */
diff --git a/plat/juno/plat-tsp.ld.S b/plat/juno/plat-tsp.ld.S
new file mode 100644 (file)
index 0000000..16d6c17
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+    ASSERT(__BL32_END__ <= BL2_BASE, "BL3-2 image overlaps BL2 image.")
diff --git a/plat/juno/plat_io_storage.c b/plat/juno/plat_io_storage.c
new file mode 100644 (file)
index 0000000..b31865e
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <platform_def.h>
+#include <semihosting.h>       /* For FOPEN_MODE_... */
+#include <string.h>
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_spec;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_spec;
+static uintptr_t memmap_init_params;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+       .offset = FLASH_BASE,
+       .length = FLASH_SIZE
+};
+
+static const io_file_spec_t bl2_file_spec = {
+       .path = BL2_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_file_spec = {
+       .path = BL30_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_file_spec = {
+       .path = BL31_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_file_spec = {
+       .path = BL32_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_file_spec = {
+       .path = BL33_IMAGE_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_file_spec_t bl2_cert_file_spec = {
+       .path = BL2_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t trusted_key_cert_file_spec = {
+       .path = TRUSTED_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_key_cert_file_spec = {
+       .path = BL30_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_key_cert_file_spec = {
+       .path = BL31_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_key_cert_file_spec = {
+       .path = BL32_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_key_cert_file_spec = {
+       .path = BL33_KEY_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_cert_file_spec = {
+       .path = BL30_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_cert_file_spec = {
+       .path = BL31_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_cert_file_spec = {
+       .path = BL32_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_cert_file_spec = {
+       .path = BL33_CERT_NAME,
+       .mode = FOPEN_MODE_RB
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+       const char *image_name;
+       uintptr_t *dev_handle;
+       uintptr_t image_spec;
+       int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+       {
+               FIP_IMAGE_NAME,
+               &memmap_dev_handle,
+               (uintptr_t)&fip_block_spec,
+               open_memmap
+       }, {
+               BL2_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl2_file_spec,
+               open_fip
+       }, {
+               BL30_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl30_file_spec,
+               open_fip
+       }, {
+               BL31_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl31_file_spec,
+               open_fip
+       }, {
+               BL32_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl32_file_spec,
+               open_fip
+       }, {
+               BL33_IMAGE_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl33_file_spec,
+               open_fip
+       }, {
+#if TRUSTED_BOARD_BOOT
+               BL2_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl2_cert_file_spec,
+               open_fip
+       }, {
+               TRUSTED_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&trusted_key_cert_file_spec,
+               open_fip
+       }, {
+               BL30_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl30_key_cert_file_spec,
+               open_fip
+       }, {
+               BL31_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl31_key_cert_file_spec,
+               open_fip
+       }, {
+               BL32_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl32_key_cert_file_spec,
+               open_fip
+       }, {
+               BL33_KEY_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl33_key_cert_file_spec,
+               open_fip
+       }, {
+               BL30_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl30_cert_file_spec,
+               open_fip
+       }, {
+               BL31_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl31_cert_file_spec,
+               open_fip
+       }, {
+               BL32_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl32_cert_file_spec,
+               open_fip
+       }, {
+               BL33_CERT_NAME,
+               &fip_dev_handle,
+               (uintptr_t)&bl33_cert_file_spec,
+               open_fip
+       }, {
+#endif /* TRUSTED_BOARD_BOOT */
+               0, 0, 0
+       }
+};
+
+
+static int open_fip(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+
+       /* See if a Firmware Image Package is available */
+       result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_NAME);
+       if (result == IO_SUCCESS) {
+               INFO("Using FIP\n");
+               /*TODO: Check image defined in spec is present in FIP. */
+       }
+       return result;
+}
+
+
+static int open_memmap(const uintptr_t spec)
+{
+       int result = IO_FAIL;
+       uintptr_t local_image_handle;
+
+       result = io_dev_init(memmap_dev_handle, memmap_init_params);
+       if (result == IO_SUCCESS) {
+               result = io_open(memmap_dev_handle, spec, &local_image_handle);
+               if (result == IO_SUCCESS) {
+                       /* INFO("Using Memmap IO\n"); */
+                       io_close(local_image_handle);
+               }
+       }
+       return result;
+}
+
+void io_setup(void)
+{
+       int io_result = IO_FAIL;
+
+       /* Register the IO devices on this platform */
+       io_result = register_io_dev_fip(&fip_dev_con);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = register_io_dev_memmap(&memmap_dev_con);
+       assert(io_result == IO_SUCCESS);
+
+       /* Open connections to devices and cache the handles */
+       io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle);
+       assert(io_result == IO_SUCCESS);
+
+       io_result = io_dev_open(memmap_dev_con, memmap_dev_spec,
+                               &memmap_dev_handle);
+       assert(io_result == IO_SUCCESS);
+
+       /* Ignore improbable errors in release builds */
+       (void)io_result;
+}
+
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy */
+int plat_get_image_source(const char *image_name, uintptr_t *dev_handle,
+                         uintptr_t *image_spec)
+{
+       int result = IO_FAIL;
+       const struct plat_io_policy *policy;
+
+       if ((image_name != NULL) && (dev_handle != NULL) &&
+           (image_spec != NULL)) {
+               policy = policies;
+               while (policy->image_name != NULL) {
+                       if (strcmp(policy->image_name, image_name) == 0) {
+                               result = policy->check(policy->image_spec);
+                               if (result == IO_SUCCESS) {
+                                       *image_spec = policy->image_spec;
+                                       *dev_handle = *(policy->dev_handle);
+                                       break;
+                               }
+                       }
+                       policy++;
+               }
+       } else {
+               result = IO_FAIL;
+       }
+       return result;
+}
diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c
new file mode 100644 (file)
index 0000000..47338cf
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2013, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <debug.h>
+#include <cci400.h>
+#include <errno.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include "juno_def.h"
+#include "juno_private.h"
+#include "scpi.h"
+
+/*******************************************************************************
+ * Private Juno function to program the mailbox for a cpu before it is released
+ * from reset.
+ ******************************************************************************/
+static void juno_program_mailbox(uint64_t mpidr, uint64_t address)
+{
+       uint64_t linear_id;
+       uint64_t mbox;
+
+       linear_id = platform_get_core_pos(mpidr);
+       mbox = TRUSTED_MAILBOXES_BASE + (linear_id << TRUSTED_MAILBOX_SHIFT);
+       *((uint64_t *) mbox) = address;
+       flush_dcache_range(mbox, sizeof(mbox));
+}
+
+/*******************************************************************************
+ * Private Juno function which is used to determine if any platform actions
+ * should be performed for the specified affinity instance given its
+ * state. Nothing needs to be done if the 'state' is not off or if this is not
+ * the highest affinity level which will enter the 'state'.
+ ******************************************************************************/
+static int32_t juno_do_plat_actions(uint32_t afflvl, uint32_t state)
+{
+       uint32_t max_phys_off_afflvl;
+
+       assert(afflvl <= MPIDR_AFFLVL1);
+
+       if (state != PSCI_STATE_OFF)
+               return -EAGAIN;
+
+       /*
+        * Find the highest affinity level which will be suspended and postpone
+        * all the platform specific actions until that level is hit.
+        */
+       max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
+       assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
+       assert(psci_get_suspend_afflvl() >= max_phys_off_afflvl);
+       if (afflvl != max_phys_off_afflvl)
+               return -EAGAIN;
+
+       return 0;
+}
+
+/*******************************************************************************
+ * Juno handler called to check the validity of the power state parameter.
+ ******************************************************************************/
+int32_t juno_validate_power_state(unsigned int power_state)
+{
+       /* Sanity check the requested state */
+       if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) {
+               /*
+                * It's possible to enter standby only on affinity level 0 i.e.
+                * a cpu on the Juno. Ignore any other affinity level.
+                */
+               if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0)
+                       return PSCI_E_INVALID_PARAMS;
+       }
+
+       /*
+        * We expect the 'state id' to be zero.
+        */
+       if (psci_get_pstate_id(power_state))
+               return PSCI_E_INVALID_PARAMS;
+
+       return PSCI_E_SUCCESS;
+}
+
+
+/*******************************************************************************
+ * Juno handler called when an affinity instance is about to be turned on. The
+ * level and mpidr determine the affinity instance.
+ ******************************************************************************/
+int32_t juno_affinst_on(uint64_t mpidr,
+                       uint64_t sec_entrypoint,
+                       uint32_t afflvl,
+                       uint32_t state)
+{
+       /*
+        * SCP takes care of powering up higher affinity levels so we
+        * only need to care about level 0
+        */
+       if (afflvl != MPIDR_AFFLVL0)
+               return PSCI_E_SUCCESS;
+
+       /*
+        * Setup mailbox with address for CPU entrypoint when it next powers up
+        */
+       juno_program_mailbox(mpidr, sec_entrypoint);
+
+       scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
+                                scpi_power_on);
+
+       return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Juno handler called when an affinity instance has just been powered on after
+ * being turned off earlier. The level and mpidr determine the affinity
+ * instance. The 'state' arg. allows the platform to decide whether the cluster
+ * was turned off prior to wakeup and do what's necessary to setup it up
+ * correctly.
+ ******************************************************************************/
+void juno_affinst_on_finish(uint32_t afflvl, uint32_t state)
+{
+       unsigned long mpidr;
+
+       /* Determine if any platform actions need to be executed. */
+       if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       /* Get the mpidr for this cpu */
+       mpidr = read_mpidr_el1();
+
+       /*
+        * Perform the common cluster specific operations i.e enable coherency
+        * if this cluster was off.
+        */
+       if (afflvl != MPIDR_AFFLVL0)
+               cci_enable_cluster_coherency(mpidr);
+
+
+       /* Enable the gic cpu interface */
+       arm_gic_cpuif_setup();
+
+       /* Juno todo: Is this setup only needed after a cold boot? */
+       arm_gic_pcpu_distif_setup();
+
+       /* Clear the mailbox for this cpu. */
+       juno_program_mailbox(mpidr, 0);
+}
+
+/*******************************************************************************
+ * Common function called while turning a cpu off or suspending it. It is called
+ * from juno_off() or juno_suspend() when these functions in turn are called for
+ * the highest affinity level which will be powered down. It performs the
+ * actions common to the OFF and SUSPEND calls.
+ ******************************************************************************/
+static void juno_power_down_common(uint32_t afflvl)
+{
+       uint32_t cluster_state = scpi_power_on;
+
+       /* Prevent interrupts from spuriously waking up this cpu */
+       arm_gic_cpuif_deactivate();
+
+       /* Cluster is to be turned off, so disable coherency */
+       if (afflvl > MPIDR_AFFLVL0) {
+               cci_disable_cluster_coherency(read_mpidr_el1());
+               cluster_state = scpi_power_off;
+       }
+
+       /*
+        * Ask the SCP to power down the appropriate components depending upon
+        * their state.
+        */
+       scpi_set_css_power_state(read_mpidr_el1(),
+                                scpi_power_off,
+                                cluster_state,
+                                scpi_power_on);
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to be turned off. The
+ * level and mpidr determine the affinity instance. The 'state' arg. allows the
+ * platform to decide whether the cluster is being turned off and take
+ * appropriate actions.
+ *
+ * CAUTION: There is no guarantee that caches will remain turned on across calls
+ * to this function as each affinity level is dealt with. So do not write & read
+ * global variables across calls. It will be wise to do flush a write to the
+ * global to prevent unpredictable results.
+ ******************************************************************************/
+static void juno_affinst_off(uint32_t afflvl, uint32_t state)
+{
+       /* Determine if any platform actions need to be executed */
+       if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       juno_power_down_common(afflvl);
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to be suspended. The
+ * level and mpidr determine the affinity instance. The 'state' arg. allows the
+ * platform to decide whether the cluster is being turned off and take apt
+ * actions. The 'sec_entrypoint' determines the address in BL3-1 from where
+ * execution should resume.
+ *
+ * CAUTION: There is no guarantee that caches will remain turned on across calls
+ * to this function as each affinity level is dealt with. So do not write & read
+ * global variables across calls. It will be wise to do flush a write to the
+ * global to prevent unpredictable results.
+ ******************************************************************************/
+static void juno_affinst_suspend(uint64_t sec_entrypoint,
+                                   uint32_t afflvl,
+                                   uint32_t state)
+{
+       /* Determine if any platform actions need to be executed */
+       if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
+               return;
+
+       /*
+        * Setup mailbox with address for CPU entrypoint when it next powers up.
+        */
+       juno_program_mailbox(read_mpidr_el1(), sec_entrypoint);
+
+       juno_power_down_common(afflvl);
+}
+
+/*******************************************************************************
+ * Juno handler called when an affinity instance has just been powered on after
+ * having been suspended earlier. The level and mpidr determine the affinity
+ * instance.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+static void juno_affinst_suspend_finish(uint32_t afflvl,
+                                          uint32_t state)
+{
+       juno_affinst_on_finish(afflvl, state);
+}
+
+/*******************************************************************************
+ * Juno handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 juno_system_off(void)
+{
+       uint32_t response;
+
+       /* Send the power down request to the SCP */
+       response = scpi_sys_power_state(scpi_system_shutdown);
+
+       if (response != SCP_OK) {
+               ERROR("Juno System Off: SCP error %u.\n", response);
+               panic();
+       }
+       wfi();
+       ERROR("Juno System Off: operation not handled.\n");
+       panic();
+}
+
+static void __dead2 juno_system_reset(void)
+{
+       uint32_t response;
+
+       /* Send the system reset request to the SCP */
+       response = scpi_sys_power_state(scpi_system_reboot);
+
+       if (response != SCP_OK) {
+               ERROR("Juno System Reset: SCP error %u.\n", response);
+               panic();
+       }
+       wfi();
+       ERROR("Juno System Reset: operation not handled.\n");
+       panic();
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to enter standby.
+ ******************************************************************************/
+void juno_affinst_standby(unsigned int power_state)
+{
+       unsigned int scr;
+
+       scr = read_scr_el3();
+       /* Enable PhysicalIRQ bit for NS world to wake the CPU */
+       write_scr_el3(scr | SCR_IRQ_BIT);
+       isb();
+       dsb();
+       wfi();
+
+       /*
+        * Restore SCR to the original value, synchronisation of scr_el3 is
+        * done by eret while el3_exit to save some execution cycles.
+        */
+       write_scr_el3(scr);
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static const plat_pm_ops_t juno_ops = {
+       .affinst_on             = juno_affinst_on,
+       .affinst_on_finish      = juno_affinst_on_finish,
+       .affinst_off            = juno_affinst_off,
+       .affinst_standby        = juno_affinst_standby,
+       .affinst_suspend        = juno_affinst_suspend,
+       .affinst_suspend_finish = juno_affinst_suspend_finish,
+       .system_off             = juno_system_off,
+       .system_reset           = juno_system_reset,
+       .validate_power_state   = juno_validate_power_state
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops)
+{
+       *plat_ops = &juno_ops;
+       return 0;
+}
diff --git a/plat/juno/plat_security.c b/plat/juno/plat_security.c
new file mode 100644 (file)
index 0000000..64e493f
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <tzc400.h>
+#include "juno_def.h"
+
+/*******************************************************************************
+ * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access
+ * and allow Non-Secure masters full access
+ ******************************************************************************/
+static void init_tzc400(void)
+{
+       tzc_init(TZC400_BASE);
+
+       /* Disable filters. */
+       tzc_disable_filters();
+
+       /* Region 1 set to cover Non-Secure DRAM at 0x8000_0000. Apply the
+        * same configuration to all filters in the TZC. */
+       tzc_configure_region(REG_ATTR_FILTER_BIT_ALL, 1,
+                       DRAM_NS_BASE, DRAM_NS_BASE + DRAM_NS_SIZE - 1,
+                       TZC_REGION_S_NONE,
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CCI400)     |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_PCIE)       |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD0)     |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD1)     |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_USB)        |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_DMA330)     |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_THINLINKS)  |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_AP)         |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_GPU)        |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CORESIGHT));
+
+       /* Region 2 set to cover Secure DRAM */
+       tzc_configure_region(REG_ATTR_FILTER_BIT_ALL, 2,
+                       DRAM_SEC_BASE, DRAM_SEC_BASE + DRAM_SEC_SIZE - 1,
+                       TZC_REGION_S_RDWR,
+                       0);
+
+       /* Region 3 set to cover DRAM used by SCP for DDR retraining */
+       tzc_configure_region(REG_ATTR_FILTER_BIT_ALL, 3,
+                       DRAM_SCP_BASE, DRAM_SCP_BASE + DRAM_SCP_SIZE - 1,
+                       TZC_REGION_S_NONE,
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_SCP));
+
+       /* Region 4 set to cover Non-Secure DRAM at 0x8_8000_0000 */
+       tzc_configure_region(REG_ATTR_FILTER_BIT_ALL, 4,
+                       DRAM2_BASE, DRAM2_BASE + DRAM2_SIZE - 1,
+                       TZC_REGION_S_NONE,
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CCI400)     |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_PCIE)       |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD0)     |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD1)     |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_USB)        |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_DMA330)     |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_THINLINKS)  |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_AP)         |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_GPU)        |
+                       TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CORESIGHT));
+
+       /* Raise an exception if a NS device tries to access secure memory */
+       tzc_set_action(TZC_ACTION_ERR);
+
+       /* Enable filters. */
+       tzc_enable_filters();
+}
+
+/*******************************************************************************
+ * Initialize the secure environment. At this moment only the TrustZone
+ * Controller is initialized.
+ ******************************************************************************/
+void plat_security_setup(void)
+{
+       /* Initialize the TrustZone Controller */
+       init_tzc400();
+}
diff --git a/plat/juno/plat_topology.c b/plat/juno/plat_topology.c
new file mode 100644 (file)
index 0000000..39d4dab
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.h>
+#include <psci.h>
+
+unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr)
+{
+       /* Report 1 (absent) instance at levels higher that the cluster level */
+       if (aff_lvl > MPIDR_AFFLVL1)
+               return 1;
+
+       if (aff_lvl == MPIDR_AFFLVL1)
+               return 2; /* We have two clusters */
+
+       return mpidr & 0x100 ? 4 : 2; /* 4 cpus in cluster 1, 2 in cluster 0 */
+}
+
+unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr)
+{
+       return aff_lvl <= MPIDR_AFFLVL1 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT;
+}
+
+int plat_get_max_afflvl()
+{
+       return MPIDR_AFFLVL1;
+}
+
+int plat_setup_topology()
+{
+       /* Juno todo: Make topology configurable via SCC */
+       return 0;
+}
diff --git a/plat/juno/platform.mk b/plat/juno/platform.mk
new file mode 100644 (file)
index 0000000..8beaecf
--- /dev/null
@@ -0,0 +1,111 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+# On Juno, the Secure Payload can be loaded either in Trusted SRAM (default) or
+# Secure DRAM allocated by the TrustZone Controller.
+
+PLAT_TSP_LOCATION      :=      tsram
+
+ifeq (${PLAT_TSP_LOCATION}, tsram)
+  PLAT_TSP_LOCATION_ID := PLAT_TRUSTED_SRAM_ID
+else ifeq (${PLAT_TSP_LOCATION}, dram)
+  PLAT_TSP_LOCATION_ID := PLAT_DRAM_ID
+else
+  $(error "Unsupported PLAT_TSP_LOCATION value")
+endif
+
+# Process flags
+$(eval $(call add_define,PLAT_TSP_LOCATION_ID))
+
+
+PLAT_INCLUDES          :=      -Iplat/juno/include/
+
+PLAT_BL_COMMON_SOURCES :=      drivers/arm/pl011/pl011_console.S       \
+                               drivers/io/io_fip.c                     \
+                               drivers/io/io_memmap.c                  \
+                               drivers/io/io_storage.c                 \
+                               lib/aarch64/xlat_tables.c               \
+                               plat/common/aarch64/plat_common.c       \
+                               plat/common/plat_gic.c                  \
+                               plat/juno/plat_io_storage.c
+
+BL1_SOURCES            +=      drivers/arm/cci400/cci400.c             \
+                               lib/cpus/aarch64/cortex_a53.S           \
+                               lib/cpus/aarch64/cortex_a57.S           \
+                               plat/common/aarch64/platform_up_stack.S \
+                               plat/juno/bl1_plat_setup.c              \
+                               plat/juno/aarch64/bl1_plat_helpers.S    \
+                               plat/juno/aarch64/plat_helpers.S        \
+                               plat/juno/aarch64/juno_common.c
+
+BL2_SOURCES            +=      drivers/arm/tzc400/tzc400.c             \
+                               plat/common/aarch64/platform_up_stack.S \
+                               plat/juno/bl2_plat_setup.c              \
+                               plat/juno/mhu.c                         \
+                               plat/juno/plat_security.c               \
+                               plat/juno/aarch64/plat_helpers.S        \
+                               plat/juno/aarch64/juno_common.c         \
+                               plat/juno/scp_bootloader.c              \
+                               plat/juno/scpi.c
+
+BL31_SOURCES           +=      drivers/arm/cci400/cci400.c             \
+                               drivers/arm/gic/arm_gic.c               \
+                               drivers/arm/gic/gic_v2.c                \
+                               drivers/arm/gic/gic_v3.c                \
+                               lib/cpus/aarch64/cortex_a53.S           \
+                               lib/cpus/aarch64/cortex_a57.S           \
+                               plat/common/aarch64/platform_mp_stack.S \
+                               plat/juno/bl31_plat_setup.c             \
+                               plat/juno/mhu.c                         \
+                               plat/juno/aarch64/plat_helpers.S        \
+                               plat/juno/aarch64/juno_common.c         \
+                               plat/juno/plat_pm.c                     \
+                               plat/juno/plat_topology.c               \
+                               plat/juno/scpi.c
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+  BL1_SOURCES          +=      plat/juno/juno_trusted_boot.c
+  BL2_SOURCES          +=      plat/juno/juno_trusted_boot.c
+endif
+
+ifneq (${RESET_TO_BL31},0)
+  $(error "Using BL3-1 as the reset vector is not supported on Juno. \
+  Please set RESET_TO_BL31 to 0.")
+endif
+
+NEED_BL30              :=      yes
+
+# Enable workarounds for selected Cortex-A57 erratas.
+ERRATA_A57_806969      :=      1
+ERRATA_A57_813420      :=      1
+
+# Enable option to skip L1 data cache flush during the Cortex-A57 cluster
+# power down sequence
+SKIP_A57_L1_FLUSH_PWR_DWN      :=       1
diff --git a/plat/juno/scp_bootloader.c b/plat/juno/scp_bootloader.c
new file mode 100644 (file)
index 0000000..a6d25d4
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include "juno_def.h"
+#include "mhu.h"
+#include "scp_bootloader.h"
+#include "scpi.h"
+
+/* Boot commands sent from AP -> SCP */
+#define BOOT_CMD_START 0x01
+#define BOOT_CMD_DATA  0x02
+
+typedef struct {
+       uint32_t image_size;
+} cmd_start_payload;
+
+typedef struct {
+       uint32_t sequence_num;
+       uint32_t offset;
+       uint32_t size;
+} cmd_data_payload;
+
+#define BOOT_DATA_MAX_SIZE  0x1000
+
+/* Boot commands sent from SCP -> AP */
+#define BOOT_CMD_ACK   0x03
+#define BOOT_CMD_NACK  0x04
+
+typedef struct {
+       uint32_t sequence_num;
+} cmd_ack_payload;
+
+/*
+ * Unlike the runtime protocol, the boot protocol uses the same memory region
+ * for both AP -> SCP and SCP -> AP transfers; define the address of this...
+ */
+static void * const cmd_payload = (void *)(MHU_SECURE_BASE + 0x0080);
+
+static void *scp_boot_message_start(void)
+{
+       mhu_secure_message_start();
+
+       return cmd_payload;
+}
+
+static void scp_boot_message_send(unsigned command, size_t size)
+{
+       /* Make sure payload can be seen by SCP */
+       if (MHU_PAYLOAD_CACHED)
+               flush_dcache_range((unsigned long)cmd_payload, size);
+
+       /* Send command to SCP */
+       mhu_secure_message_send(command | (size << 8));
+}
+
+static uint32_t scp_boot_message_wait(size_t size)
+{
+       uint32_t response =  mhu_secure_message_wait();
+
+       /* Make sure we see the reply from the SCP and not any stale data */
+       if (MHU_PAYLOAD_CACHED)
+               inv_dcache_range((unsigned long)cmd_payload, size);
+
+       return response & 0xff;
+}
+
+static void scp_boot_message_end(void)
+{
+       mhu_secure_message_end();
+}
+
+static int transfer_block(uint32_t sequence_num, uint32_t offset, uint32_t size)
+{
+       cmd_data_payload *cmd_data = scp_boot_message_start();
+       cmd_data->sequence_num = sequence_num;
+       cmd_data->offset = offset;
+       cmd_data->size = size;
+
+       scp_boot_message_send(BOOT_CMD_DATA, sizeof(*cmd_data));
+
+       cmd_ack_payload *cmd_ack = cmd_payload;
+       int ok = scp_boot_message_wait(sizeof(*cmd_ack)) == BOOT_CMD_ACK
+                && cmd_ack->sequence_num == sequence_num;
+
+       scp_boot_message_end();
+
+       return ok;
+}
+
+int scp_bootloader_transfer(void *image, unsigned int image_size)
+{
+       uintptr_t offset = (uintptr_t)image - MHU_SECURE_BASE;
+       uintptr_t end = offset + image_size;
+       uint32_t response;
+
+       mhu_secure_init();
+
+       /* Initiate communications with SCP */
+       do {
+               cmd_start_payload *cmd_start = scp_boot_message_start();
+               cmd_start->image_size = image_size;
+
+               scp_boot_message_send(BOOT_CMD_START, sizeof(*cmd_start));
+
+               response = scp_boot_message_wait(0);
+
+               scp_boot_message_end();
+       } while (response != BOOT_CMD_ACK);
+
+       /* Transfer image to SCP a block at a time */
+       uint32_t sequence_num = 1;
+       size_t size;
+       while ((size = end - offset) != 0) {
+               if (size > BOOT_DATA_MAX_SIZE)
+                       size = BOOT_DATA_MAX_SIZE;
+               while (!transfer_block(sequence_num, offset, size))
+                       ; /* Retry forever */
+               offset += size;
+               sequence_num++;
+       }
+
+       /* Wait for SCP to signal it's ready */
+       return scpi_wait_ready();
+}
diff --git a/plat/juno/scp_bootloader.h b/plat/juno/scp_bootloader.h
new file mode 100644 (file)
index 0000000..e872513
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SCP_BOOTLOADER_H__
+#define __SCP_BOOTLOADER_H__
+
+int scp_bootloader_transfer(void *image, unsigned int image_size);
+
+#endif
diff --git a/plat/juno/scpi.c b/plat/juno/scpi.c
new file mode 100644 (file)
index 0000000..950c00b
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include "juno_def.h"
+#include "mhu.h"
+#include "scpi.h"
+
+#define MHU_SECURE_SCP_TO_AP_PAYLOAD   (MHU_SECURE_BASE+0x0080)
+#define MHU_SECURE_AP_TO_SCP_PAYLOAD   (MHU_SECURE_BASE+0x0280)
+
+#define SIZE_SHIFT     20      /* Bit position for size value in MHU header */
+#define SIZE_MASK      0x1ff   /* Mask to extract size value in MHU header*/
+
+
+void *scpi_secure_message_start(void)
+{
+       mhu_secure_message_start();
+
+       /* Return address of payload area. */
+       return (void *)MHU_SECURE_AP_TO_SCP_PAYLOAD;
+}
+
+void scpi_secure_message_send(unsigned command, size_t size)
+{
+       /* Make sure payload can be seen by SCP */
+       if (MHU_PAYLOAD_CACHED)
+               flush_dcache_range(MHU_SECURE_AP_TO_SCP_PAYLOAD, size);
+
+       mhu_secure_message_send(command | (size << SIZE_SHIFT));
+}
+
+unsigned scpi_secure_message_receive(void **message_out, size_t *size_out)
+{
+       uint32_t response =  mhu_secure_message_wait();
+
+       /* Get size of payload */
+       size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
+
+       /* Clear size from response */
+       response &= ~(SIZE_MASK << SIZE_SHIFT);
+
+       /* Make sure we don't read stale data */
+       if (MHU_PAYLOAD_CACHED)
+               inv_dcache_range(MHU_SECURE_SCP_TO_AP_PAYLOAD, size);
+
+       if (size_out)
+               *size_out = size;
+
+       if (message_out)
+               *message_out = (void *)MHU_SECURE_SCP_TO_AP_PAYLOAD;
+
+       return response;
+}
+
+void scpi_secure_message_end(void)
+{
+       mhu_secure_message_end();
+}
+
+static void scpi_secure_send32(unsigned command, uint32_t message)
+{
+       *(__typeof__(message) *)scpi_secure_message_start() = message;
+       scpi_secure_message_send(command, sizeof(message));
+       scpi_secure_message_end();
+}
+
+int scpi_wait_ready(void)
+{
+       /* Get a message from the SCP */
+       scpi_secure_message_start();
+       size_t size;
+       unsigned command = scpi_secure_message_receive(NULL, &size);
+       scpi_secure_message_end();
+
+       /* We are expecting 'SCP Ready', produce correct error if it's not */
+       scpi_status_t response = SCP_OK;
+       if (command != SCPI_CMD_SCP_READY)
+               response = SCP_E_SUPPORT;
+       else if (size != 0)
+               response = SCP_E_SIZE;
+
+       /* Send our response back to SCP */
+       scpi_secure_send32(command, response);
+
+       return response == SCP_OK ? 0 : -1;
+}
+
+void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
+               scpi_power_state_t cluster_state, scpi_power_state_t css_state)
+{
+       uint32_t state = mpidr & 0x0f;  /* CPU ID */
+       state |= (mpidr & 0xf00) >> 4;  /* Cluster ID */
+       state |= cpu_state << 8;
+       state |= cluster_state << 12;
+       state |= css_state << 16;
+       scpi_secure_send32(SCPI_CMD_SET_CSS_POWER_STATE, state);
+}
+
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
+{
+       uint32_t *response;
+       size_t size;
+       uint8_t state = system_state & 0xff;
+
+       /* Send the command */
+       *(__typeof__(state) *)scpi_secure_message_start() = state;
+       scpi_secure_message_send(SCPI_CMD_SYS_POWER_STATE, sizeof(state));
+       scpi_secure_message_receive((void *)&response, &size);
+       scpi_secure_message_end();
+       return *response;
+}
diff --git a/plat/juno/scpi.h b/plat/juno/scpi.h
new file mode 100644 (file)
index 0000000..8a5ef65
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SCPI_H__
+#define __SCPI_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+extern void *scpi_secure_message_start(void);
+extern void scpi_secure_message_send(unsigned command, size_t size);
+extern unsigned scpi_secure_message_receive(void **message_out, size_t *size_out);
+extern void scpi_secure_message_end(void);
+
+
+enum {
+       SCP_OK = 0,     /* Success */
+       SCP_E_PARAM,    /* Invalid parameter(s) */
+       SCP_E_ALIGN,    /* Invalid alignment */
+       SCP_E_SIZE,     /* Invalid size */
+       SCP_E_HANDLER,  /* Invalid handler or callback */
+       SCP_E_ACCESS,   /* Invalid access or permission denied */
+       SCP_E_RANGE,    /* Value out of range */
+       SCP_E_TIMEOUT,  /* Time out has ocurred */
+       SCP_E_NOMEM,    /* Invalid memory area or pointer */
+       SCP_E_PWRSTATE, /* Invalid power state */
+       SCP_E_SUPPORT,  /* Feature not supported or disabled */
+};
+
+typedef uint32_t scpi_status_t;
+
+typedef enum {
+       SCPI_CMD_SCP_READY = 0x01,
+       SCPI_CMD_SET_CSS_POWER_STATE = 0x04,
+       SCPI_CMD_SYS_POWER_STATE = 0x08
+} scpi_command_t;
+
+typedef enum {
+       scpi_power_on = 0,
+       scpi_power_retention = 1,
+       scpi_power_off = 3,
+} scpi_power_state_t;
+
+typedef enum {
+       scpi_system_shutdown = 0,
+       scpi_system_reboot = 1,
+       scpi_system_reset = 2
+} scpi_system_state_t;
+
+extern int scpi_wait_ready(void);
+extern void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
+               scpi_power_state_t cluster_state, scpi_power_state_t css_state);
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
+
+#endif /* __SCPI_H__ */
diff --git a/plat/juno/tsp/tsp-juno.mk b/plat/juno/tsp/tsp-juno.mk
new file mode 100644 (file)
index 0000000..4d56ea2
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2014, 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.
+#
+
+# TSP source files specific to Juno platform
+BL32_SOURCES           +=      drivers/arm/gic/arm_gic.c               \
+                               drivers/arm/gic/gic_v2.c                \
+                               plat/common/aarch64/platform_mp_stack.S \
+                               plat/juno/aarch64/juno_common.c         \
+                               plat/juno/aarch64/plat_helpers.S        \
+                               plat/juno/tsp/tsp_plat_setup.c
diff --git a/plat/juno/tsp/tsp_plat_setup.c b/plat/juno/tsp/tsp_plat_setup.c
new file mode 100644 (file)
index 0000000..8293a13
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <console.h>
+#include <platform_tsp.h>
+#include "../juno_def.h"
+#include "../juno_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+extern unsigned long __BL32_END__;
+
+#if USE_COHERENT_MEM
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+#endif
+
+/*
+ * The next 3 constants identify the extents of the code, RO data region and the
+ * limit of the BL3-2 image.  These addresses are used by the MMU setup code and
+ * therefore they must be page-aligned.  It is the responsibility of the linker
+ * script to ensure that __RO_START__, __RO_END__ & __BL32_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL32_RO_BASE (unsigned long)(&__RO_START__)
+#define BL32_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL32_END (unsigned long)(&__BL32_END__)
+
+#if USE_COHERENT_MEM
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+void tsp_early_platform_setup(void)
+{
+       /*
+        * Initialize a different console than already in use to display
+        * messages from TSP
+        */
+       console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+}
+
+/*******************************************************************************
+ * Perform platform specific setup placeholder
+ ******************************************************************************/
+void tsp_platform_setup(void)
+{
+       plat_gic_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this only intializes the MMU
+ ******************************************************************************/
+void tsp_plat_arch_setup(void)
+{
+       configure_mmu_el1(BL32_RO_BASE,
+                         (BL32_END - BL32_RO_BASE),
+                         BL32_RO_BASE,
+                         BL32_RO_LIMIT
+#if USE_COHERENT_MEM
+                         , BL32_COHERENT_RAM_BASE,
+                         BL32_COHERENT_RAM_LIMIT
+#endif
+                         );
+}
diff --git a/plat/rpi3/aarch64/plat_helpers.S b/plat/rpi3/aarch64/plat_helpers.S
new file mode 100644 (file)
index 0000000..71e3d12
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a53.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+#include "../rpi3_def.h"
+
+
+       .globl  plat_crash_console_init
+       .globl  plat_crash_console_putc
+       .globl  plat_report_exception
+       .globl  plat_reset_handler
+       .globl  platform_get_core_pos
+       .globl  platform_mem_init
+       .globl  platform_set_el0_stack
+       .globl  platform_spin_core
+       .globl  plat_print_gic_regs
+       .globl  plat_print_interconnect_regs
+       .globl  plat_interrupt_type_to_line
+       .globl  plat_ic_get_pending_interrupt_type
+       .globl  plat_report_smc64
+
+       /* Define a crash console for the plaform */
+#define RPI3_CRASH_CONSOLE_BASE                UART0_BASE
+
+       /* ---------------------------------------------
+        * int plat_crash_console_init(void)
+        * Function to initialize the crash console
+        * without a C Runtime to print crash report.
+        * Clobber list : x0, x1, x2
+        * ---------------------------------------------
+        */
+func plat_crash_console_init
+       mov x0, #1
+       ret
+       b dummy_console_init
+
+       /* ---------------------------------------------
+        * int plat_crash_console_putc(int c)
+        * Function to print a character on the crash
+        * console without a C Runtime.
+        * Clobber list : x1, x2
+        * ---------------------------------------------
+        */
+func _wait_for_xmitr
+nr:    
+       mov     x1, #0x5054                     // #20564
+       movk    x1, #0x3f21, lsl #16
+       ldr     w1, [x1]
+       tbz     w1, #5, nr
+       ret
+
+func _console_putc
+       mov     x2, x30 // lr
+       bl      _wait_for_xmitr
+       mov     x1, #0x5040                    // #20544
+       movk    x1, #0x3f21, lsl #16
+       str     w0, [x1]
+       mov     w1, w0
+       and     w1, w1, #0xff
+       cmp     w1, #0xa
+       b.ne    xi
+       bl      _wait_for_xmitr
+       mov     x1, #0x5040                    // #20544
+       movk    x1, #0x3f21, lsl #16
+       mov     w0, #0xd
+       str     w0, [x1]
+xi:    mov     x30, x2
+       ret
+       
+func plat_crash_console_putc
+       b       _console_putc
+
+smc64_msg:
+       .asciz "SMC_64 entered\n"
+       
+func plat_report_smc64
+       mov     x9, x30
+       adr     x3, smc64_msg
+1:
+       ldrb    w0, [x3], #0x1
+       cbz     x0, 2f
+       bl      plat_crash_console_putc
+       b       1b
+2:     
+       ret     x9
+       
+       /* ---------------------------------------------
+        * void plat_report_exception(unsigned int type)
+        * Function to report an unhandled exception
+        * with platform-specific means.
+        * ---------------------------------------------
+        */
+func plat_report_exception
+       mov     x8, x30
+
+       adr     x4, plat_err_str
+       bl      asm_print_str
+
+       adr     x4, esr_el3_str
+       bl      asm_print_str
+
+       mrs     x4, esr_el3
+       bl      asm_print_hex
+
+       adr     x4, elr_el3_str
+       bl      asm_print_str
+
+       mrs     x4, elr_el3
+       bl      asm_print_hex
+
+       mov     x30, x8
+       ret
+
+       /* -----------------------------------------------------
+        * void plat_reset_handler(void);
+        *
+        * Implement workaround for defect id 831273 by enabling
+        * an event stream every 65536 cycles and set the L2 RAM
+        * latencies for Cortex-A57.
+        * -----------------------------------------------------
+        */
+func plat_reset_handler
+       /* do nothing */
+       ret
+
+       /*
+        * Return 0 to 3
+        */
+func platform_get_core_pos
+       and     x1, x0, #MPIDR_CPU_MASK
+       and     x0, x0, #MPIDR_CLUSTER_MASK
+       add     x0, x1, x0, LSR #6
+       ret
+
+
+       /*
+         No GIC on PI
+       */
+func plat_print_gic_regs
+       ret
+
+func plat_print_interconnect_regs
+       ret
+
+func plat_interrupt_type_to_line
+       ret
+
+func plat_ic_get_pending_interrupt_type
+       ret
+       
+       /* -----------------------------------------------------
+        * void platform_mem_init(void);
+        *
+        * We don't need to carry out any memory initialization
+        * on LS1043. The Secure RAM is accessible straight away.
+        * -----------------------------------------------------
+        */
+func platform_mem_init
+       ret
+
+func platform_spin_core
+       /*
+        * MPIDR_EL1 Fields:
+        * MPIDR[1:0] = AFF0_CPUID <- Core ID (0,1)
+        * MPIDR[7:2] = AFF0_RES
+        * MPIDR[15:8] = AFF1_CLUSTERID <- Cluster ID (0,1,2,3)
+        * MPIDR[23:16] = AFF2_CLUSTERID
+        * MPIDR[24] = MT
+        * MPIDR[29:25] = RES0
+        * MPIDR[30] = U
+        * MPIDR[31] = ME
+        * MPIDR[39:32] = AFF3
+        *
+        * Linear Processor ID (LPID) calculation from MPIDR_EL1:
+        * (We only use AFF0_CPUID and AFF1_CLUSTERID for now
+        * until AFF2_CLUSTERID and AFF3 have non-zero values)
+        *
+        * LPID = MPIDR[15:8] | MPIDR[1:0]
+        */
+       mrs     x0, mpidr_el1
+       ubfm    x1, x0, #8, #15
+       ubfm    x2, x0, #0, #1
+       orr     x10, x2, x1, lsl #2     /* x10 has LPID */
+       ubfm    x9, x0, #0, #15         /* x9 contains MPIDR[15:0] */
+       /*
+        * offset of the spin table element for this core from start of spin
+        * table (each elem is padded to 64 bytes)
+        */
+       lsl     x1, x10, #6
+       ldr     x0, =__spin_table
+       /* address of this cpus spin table element */
+       add     x11, x1, x0
+
+slave_cpu:
+       ldr     x0, [x11]
+       cbz     x0, slave_cpu
+       mov     x1, #1
+       cbz     x1, slave_exit
+slave_exit:
+       br      x0                      /* branch to the given address */
+
+.section .rodata.rev_err_str, "aS"
+plat_err_str:
+       .asciz "\nPlatform exception reporting:"
+esr_el3_str:
+       .asciz "\nESR_EL3: "
+elr_el3_str:
+       .asciz "\nELR_EL3: "
diff --git a/plat/rpi3/aarch64/rpi3_common.c b/plat/rpi3/aarch64/rpi3_common.c
new file mode 100644 (file)
index 0000000..d233ccd
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <xlat_tables.h>
+#include <../rpi3_def.h>
+
+#define MAP_DEVICE     MAP_REGION_FLAT(DEVICE_BASE,                    \
+                                       DEVICE_SIZE,                    \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_NS_DRAM    MAP_REGION_FLAT(DRAM_NS_BASE,                   \
+                                       DRAM_NS_SIZE,                   \
+                                       MT_DEVICE | MT_RW | MT_NS)
+
+#define MAP_TSP_MEM    MAP_REGION_FLAT(TSP_SEC_MEM_BASE,               \
+                                       TSP_SEC_MEM_SIZE,               \
+                                       MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_SRAM       MAP_REGION_FLAT(SRAM_BASE,                      \
+                                       SRAM_SIZE,                      \
+                                       MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+
+#if IMAGE_BL31
+static const mmap_region_t rpi3_mmap[] = {
+       MAP_DEVICE,
+       MAP_NS_DRAM,
+       MAP_TSP_MEM,
+       {0}
+};
+#endif
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#define DEFINE_CONFIGURE_MMU_EL(_el)                           \
+       void configure_mmu_el##_el(unsigned long total_base,    \
+                                 unsigned long total_size,     \
+                                 unsigned long ro_start,       \
+                                 unsigned long ro_limit,       \
+                                 unsigned long coh_start,      \
+                                  unsigned long coh_limit)     \
+       {                                                       \
+              mmap_add_region(total_base, total_base,          \
+                              total_size,                      \
+                              MT_MEMORY | MT_RW | MT_SECURE);  \
+              mmap_add_region(ro_start, ro_start,              \
+                              ro_limit - ro_start,             \
+                              MT_MEMORY | MT_RO | MT_SECURE);  \
+              mmap_add_region(coh_start, coh_start,            \
+                              coh_limit - coh_start,           \
+                              MT_DEVICE | MT_RW | MT_SECURE);  \
+              mmap_add(rpi3_mmap);                             \
+              init_xlat_tables();                              \
+                                                               \
+              enable_mmu_el##_el(0);                           \
+       }
+
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(1)
+DEFINE_CONFIGURE_MMU_EL(3)
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+       return NS_IMAGE_OFFSET;
+}
+
+uint64_t plat_get_syscnt_freq(void)
+{
+       return 1200000;
+}
+
+void plat_gic_init(void)
+{
+  return;
+}
diff --git a/plat/rpi3/bl31_plat_setup.c b/plat/rpi3/bl31_plat_setup.c
new file mode 100644 (file)
index 0000000..4cc0cf2
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl31.h>
+#include <bl_common.h>
+#include <console.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+#include <string.h>
+#include <platform_def.h>
+#include "rpi3_def.h"
+#include "rpi3_private.h"
+#include "debug.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/******************************************************************************
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL3-1 from BL2.
+ ******************************************************************************/
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*
+  From opteed_main.c
+*/
+struct optee_header {
+  uint32_t magic;
+  uint8_t version;
+  uint8_t arch;
+  uint16_t flags;
+  uint32_t init_size;
+  uint32_t init_load_addr_hi;
+  uint32_t init_load_addr_lo;
+  uint32_t init_mem_usage;
+  uint32_t paged_size;
+};
+
+#define OPTEE_MAGIC            0x4554504f
+#define OPTEE_VERSION          1
+#define OPTEE_ARCH_ARM32       0
+#define OPTEE_ARCH_ARM64       1
+
+static struct optee_header optee_header;
+
+
+
+uint32_t __spin_table[64]
+# if USE_COHERENT_MEM
+  __attribute__ ((section("tzfw_coherent_mem")));
+# endif
+
+uint64_t *bl31_get_spin_tbl_addr(void)
+{
+  return(uint64_t *)(&__spin_table[0]);
+}
+
+uint64_t bl31_getspin(void)
+{
+  memset(&__spin_table[0], 0, sizeof(__spin_table));
+  return(uint64_t)(platform_spin_core);
+}
+
+struct uboot_data {
+  unsigned int kernel_load;
+  unsigned int dtb_load;
+  unsigned int el;
+  unsigned int optee_load;
+};
+
+extern unsigned int __uboot_data;
+void bl31_uboot_set_entries(unsigned int kernel, unsigned int dtb,
+                           unsigned int el, unsigned int optee_load)
+{
+  struct uboot_data *data = (struct uboot_data *)(&__uboot_data);
+  data->kernel_load = kernel;
+  data->dtb_load = dtb;
+  data->el = el;
+  data->optee_load = optee_load;
+}
+
+unsigned int bl31_get_uboot_optee_load(void)
+{
+  struct uboot_data *data = (struct uboot_data *)(&__uboot_data);
+
+  return(data->optee_load);
+}
+
+unsigned int bl31_get_uboot_kernel_load(void)
+{
+  struct uboot_data *data = (struct uboot_data *)(&__uboot_data);
+
+  return(data->kernel_load);
+}
+
+unsigned int bl31_get_uboot_dtb_load(void)
+{
+  struct uboot_data *data = (struct uboot_data *)(&__uboot_data);
+
+  return(data->dtb_load);
+}
+
+unsigned int bl31_get_uboot_el(void)
+{
+  struct uboot_data *data = (struct uboot_data *)(&__uboot_data);
+
+  /* Running AARCH64 */
+  if (data->el) {
+    /* EL2 */
+    return(0x3c9);
+  }
+  else {
+    /* EL1 */
+    return(0x3c5);
+  }
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL3-3 corresponds to the non-secure image type
+ * while BL3-2 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+       entry_point_info_t *next_image_info;
+
+       next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+
+       /* None of the images on this platform can have 0x0 as the entrypoint */
+       if (next_image_info->pc)
+               return next_image_info;
+       else
+               return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 specific platform actions. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables. Also, BL2
+ * has flushed this information to memory, so we are guaranteed to pick up good
+ * data
+ ******************************************************************************/
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+                              void *plat_params_from_bl2)
+{
+  /*
+   * Copy BL3-2 and BL3-3 entry point information.
+   * They are stored in Secure RAM, in BL2's address space.
+   */
+# if 0 /* old ... not being passed in */
+  bl32_ep_info = *from_bl2->bl32_ep_info;
+  bl33_ep_info = *from_bl2->bl33_ep_info;
+# else
+  bl31_set_next_image_type(NON_SECURE);
+
+  SET_PARAM_HEAD(&bl32_ep_info,
+                PARAM_EP,
+                VERSION_1,
+                0);
+  SET_SECURITY_STATE(bl32_ep_info.h.attr, SECURE);
+
+  optee_header.magic = OPTEE_MAGIC;
+  optee_header.version = OPTEE_VERSION;
+  optee_header.arch = OPTEE_ARCH_ARM64;
+  optee_header.init_load_addr_hi = 0;
+
+  optee_header.init_load_addr_lo = bl31_get_uboot_optee_load();
+
+  bl32_ep_info.pc = (uintptr_t)&optee_header;
+  bl32_ep_info.spsr = 0;
+  bl32_ep_info.args.arg0 = 0;
+  bl32_ep_info.args.arg1 = 0;
+  bl32_ep_info.args.arg2 = bl31_get_uboot_dtb_load();
+
+
+  SET_PARAM_HEAD(&bl33_ep_info,
+                PARAM_EP,
+                VERSION_1,
+                0);
+  SET_SECURITY_STATE(bl33_ep_info.h.attr, NON_SECURE);
+
+  bl33_ep_info.pc = bl31_get_uboot_kernel_load();
+
+  /*
+    0x3c9: AA64, EL2H
+    0x3c5: AA64, EL1h
+  */
+  bl33_ep_info.spsr = bl31_get_uboot_el();
+  bl33_ep_info.args.arg0 = bl31_get_uboot_dtb_load();
+  bl33_ep_info.args.arg1 = 0;
+  bl33_ep_info.args.arg2 = 0;
+  bl33_ep_info.args.arg3 = 0;
+  bl33_ep_info.args.arg4 = 0;
+
+# endif
+
+}
+
+/*******************************************************************************
+ * Initialize the GIC.
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+       /* Initialize the gic cpu and distributor interfaces */
+       plat_gic_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup()
+{
+       configure_mmu_el3(BL31_RO_BASE,
+                         BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE,
+                         BL31_RO_BASE,
+                         BL31_RO_LIMIT,
+                         BL31_COHERENT_RAM_BASE,
+                          BL31_COHERENT_RAM_LIMIT);
+}
diff --git a/plat/rpi3/console.c b/plat/rpi3/console.c
new file mode 100644 (file)
index 0000000..ed01816
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+# include <console.h>
+
+# include <stdio.h>
+
+# include "rpi3_def.h"
+
+static unsigned char *base;
+
+void set_serial(unsigned long base_addr)
+{
+  base = (unsigned char *)base_addr;
+}
+
+void fix_serial(void)
+{
+  base = (unsigned char *)UART0_BASE;
+}
+
+int console_init(unsigned long base_addr,
+                unsigned int uart_clk, unsigned int baud_rate)
+{
+  base = (unsigned char *)base_addr;
+
+  (void)uart_clk;
+  (void)baud_rate;
+
+  return(1);
+}
+
+int dummy_console_init(unsigned long base_addr,
+                      unsigned int uart_clk, unsigned int baud_rate)
+{
+  base = (unsigned char *)UART0_BASE;
+  (void)base_addr;
+  (void)uart_clk;
+  (void)baud_rate;
+
+  return(1);
+}
+
+static unsigned int serial8250_in(int offset)
+{
+  unsigned char *base = (unsigned char *)(UART0_BASE);
+  volatile unsigned int *reg = (unsigned int *)(base + offset);
+  volatile unsigned int data;
+
+  data = *reg;
+
+  return(unsigned int)(data);
+}
+
+static void serial8250_out(int offset, int value)
+{
+  unsigned char *base = (unsigned char *)(UART0_BASE);
+  volatile unsigned int *reg = (unsigned int *)(base + offset);
+
+  *reg = (unsigned char)value;
+}
+
+# define UART_TX       0
+# define UART_RX       0
+# define UART_LSR      20
+# define UART_LSR_TEMT 0x40
+# define UART_LSR_THRE 0x20
+# define UART_LSR_DR   0x01
+
+# define TX_READY (1 << 5)
+
+#define BOTH_EMPTY (TX_READY)
+
+static void wait_for_xmitr(void)
+{
+  unsigned int status;
+  
+  for (;;) {
+    status = serial8250_in(UART_LSR);
+    if ((status & BOTH_EMPTY) == BOTH_EMPTY)
+      return;
+  }
+}
+
+static void serial_putc(int c)
+{
+  wait_for_xmitr();
+  serial8250_out(UART_TX, c);
+}
+
+int console_putc(int c)
+{
+  serial_putc(c);
+  if (c == '\n') {
+    serial_putc('\r');
+  }
+  return(c);
+}
+
+int console_getc(void)
+{
+  while ((serial8250_in(UART_LSR) & UART_LSR_DR) == 0) {
+    ;
+  }
+  return serial8250_in(UART_RX);
+}
diff --git a/plat/rpi3/include/plat_macros.S b/plat/rpi3/include/plat_macros.S
new file mode 100644 (file)
index 0000000..1ce00ef
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+# include "platform_def.h"
+# include "../rpi3_def.h"
+
+
+       .macro plat_print_gic_regs
+       .endm
+
+       .macro plat_print_interconnect_regs
+       .endm
diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h
new file mode 100644 (file)
index 0000000..cd05f17
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+# if 0
+# define RPI3_CONFIG
+# endif
+
+# define CFG_USE_UBOOT_HOOKS
+
+ #define PLATFORM_MAX_AFFLVL      MPIDR_AFFLVL1
+
+#include <arch.h>
+#include "../rpi3_def.h"
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT          "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH            aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE            0x800
+
+/* EL3 Runtime Firmware BL3-1 */
+#define BL31_IMAGE_NAME                        "bl31.bin"
+
+/* Secure Payload BL3-2 (Trusted OS) */
+#define BL32_IMAGE_NAME                        "bl32.bin"
+
+/* Non-Trusted Firmware BL3-3 */
+#define BL33_IMAGE_NAME                        "bl33.bin" /* e.g. uImage */
+
+/* Firmware Image Package */
+#define FIP_IMAGE_NAME                 "fip.bin"
+
+#define PLATFORM_PER_CORE_EL0_STACK     PLATFORM_STACK_SIZE /* 4096 */
+#define PLATFORM_CACHE_LINE_SIZE       64
+#define PLATFORM_CLUSTER_COUNT         1
+#define PLATFORM_CORE_COUNT             4
+#define PLATFORM_NUM_AFFS              (PLATFORM_CLUSTER_COUNT + \
+                                        PLATFORM_CORE_COUNT)
+#define MAX_IO_DEVICES                 3
+#define MAX_IO_HANDLES                 4
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+
+#define DDR_BASE                       0x00000000
+
+/*
+  Make the linker happy ... where to link bl31
+*/
+# define BL2_LIMIT                       (DRAM_NS_BASE + DRAM_NS_SIZE)    /* BL31 load address */
+
+/*******************************************************************************
+ * BL3-1 specific defines.
+ ******************************************************************************/
+#define BL31_BASE                      (BL2_LIMIT)
+#define BL31_LIMIT                     (BL31_BASE + 0x40000)
+
+
+/*******************************************************************************
+ * BL3-2 specific defines.
+ ******************************************************************************/
+
+/*
+ * The TSP can execute from DRAM.
+ */
+
+#define BL32_SRAM_BASE                  0x10010000 /* 64k chunk */
+#define BL32_SRAM_LIMIT                 (64 * 1024) /* not very big */
+
+#define BL32_DRAM_BASE                  DRAM_SEC_BASE
+#define BL32_DRAM_LIMIT                 (DRAM_SEC_BASE+DRAM_SEC_SIZE)
+
+#if (PLAT_TSP_LOCATION_ID == PLAT_TRUSTED_DRAM_ID)
+#define TSP_SEC_MEM_BASE               BL32_DRAM_BASE
+#define TSP_SEC_MEM_SIZE               (BL32_DRAM_LIMIT - BL32_DRAM_BASE)
+#define BL32_BASE                      BL32_DRAM_BASE
+#define BL32_LIMIT                     BL32_DRAM_LIMIT
+#else
+#error "Unsupported PLAT_TSP_LOCATION_ID value"
+#endif
+
+/*******************************************************************************
+ * BL3-0 specific defines:
+ *
+ * BL3-0 is loaded for mcu firmware, firstly load it into temperary buffer
+ * into 0x0100_0000; then BL2 will parse the sections and load then into
+ * seperated buffers as needed.
+ *
+ ******************************************************************************/
+#define BL30_BASE                      (DRAM_NS_BASE + 0x01000000)
+#define BL30_LIMIT                     (DRAM_NS_BASE + 0x01100000)
+#define BL30_SIZE                      (BL30_LIMIT - BL30_BASE)
+
+/*******************************************************************************
+ * Load address of BL3-3 for RPi
+ ******************************************************************************/
+#define NS_IMAGE_OFFSET                        (0x00080000)  /* Linux load address */
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE                        (1ull << 32)
+
+# define DEBUG_XLAT_TABLE 0 /* enables page table dumping/debug in xlat_tables.c */
+
+#if IMAGE_BL1 || IMAGE_BL31 || IMAGE_BL32
+# define MAX_XLAT_TABLES               4
+#endif
+
+#if IMAGE_BL2
+# define MAX_XLAT_TABLES               4
+#endif
+
+#define MAX_MMAP_REGIONS               16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT   6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rpi3/plat_pm.c b/plat/rpi3/plat_pm.c
new file mode 100644 (file)
index 0000000..d7c6fc3
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <debug.h>
+#include <cci400.h>
+#include <errno.h>
+#include <gic_v2.h>
+
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+# include "rpi3_private.h"
+
+
+# define BOOT_ENTRY_ADDR 0
+# define NUM_BOOT_ENTRY         8
+
+static int cpu_release(int nr, uint64_t boot_addr)
+{
+  /*
+    Each core is spinning at its respective address
+  */
+  uint64_t *table = (uint64_t *)bl31_get_spin_tbl_addr();
+
+  if (nr <= 0) {
+    return PSCI_E_NOT_PRESENT;
+  }
+
+  table = table + (nr * NUM_BOOT_ENTRY);
+
+  table[BOOT_ENTRY_ADDR] = boot_addr;
+
+# if 0
+  INFO("%s(%d): nr: %d boot_addr: 0x%llx table: 0x%llx\n",
+        __func__, __LINE__,
+        nr, boot_addr, table);
+# endif
+
+  return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * RPI3 handler called when an affinity instance is about to be turned on. The
+ * level and mpidr determine the affinity instance.
+ ******************************************************************************/
+//extern int psci_0_2_cpu_on_64(unsigned long cpuid, uint64_t entry_point); /* in bl31_plat_setup.c */
+int32_t rpi3_affinst_on(uint64_t mpidr,
+                         uint64_t sec_entrypoint,
+                         uint32_t afflvl,
+                         uint32_t state)
+{
+       int cpu, cluster;
+       unsigned long linear_id;
+       unsigned int reg;
+       int status = PSCI_E_SUCCESS;
+
+       linear_id = platform_get_core_pos(mpidr);
+       cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT;
+       cpu = mpidr & MPIDR_CPU_MASK;
+
+       (void)linear_id;
+       (void)reg;
+       (void)cluster;
+       (void)cpu;
+
+       VERBOSE("#%s(%d): mpidr:%llx, afflvl:%x, state:%x linear_id: %d\n",
+                 __func__, __LINE__,
+                 mpidr, afflvl, state, linear_id);
+
+       /* directly return for power on */
+       if (state == PSCI_STATE_ON)
+               return PSCI_E_SUCCESS;
+
+       switch (afflvl) {
+       case MPIDR_AFFLVL0:
+          status = cpu_release(linear_id, sec_entrypoint);
+          break;
+
+       case MPIDR_AFFLVL1:
+          status = PSCI_E_SUCCESS; /* do nothing at cluster level */
+         break;
+       }
+       return status;
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance has just been powered on after
+ * being turned off earlier. The level and mpidr determine the affinity
+ * instance. The 'state' arg. allows the platform to decide whether the cluster
+ * was turned off prior to wakeup and do what's necessary to setup it up
+ * correctly.
+ ******************************************************************************/
+void rpi3_affinst_on_finish(uint32_t afflvl, uint32_t state)
+{
+       unsigned long mpidr;
+       unsigned long linear_id;
+
+       (void)mpidr;
+       (void)linear_id;
+}
+
+
+static void __dead2 rpi3_system_off(void)
+{
+   INFO("Pull the plug.\n");
+   for (;;);
+}
+
+#define RESET_TIMEOUT 10
+
+struct bcm2835_wdog_regs {
+       uint32_t unknown0[7];
+       uint32_t rstc;
+       uint32_t unknown1;
+       uint32_t wdog;
+};
+
+#define BCM2835_WDOG_PASSWORD                  0x5a000000
+#define BCM2835_WDOG_PHYSADDR                  0x3f100000
+#define BCM2835_WDOG_RSTC_WRCFG_MASK           0x00000030
+#define BCM2835_WDOG_RSTC_WRCFG_FULL_RESET     0x00000020
+
+static void reset_cpu(void)
+{
+       struct bcm2835_wdog_regs *regs =
+               (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR;
+       uint32_t rstc;
+
+       rstc = regs->rstc;
+       rstc &= ~BCM2835_WDOG_RSTC_WRCFG_MASK;
+       rstc |= BCM2835_WDOG_RSTC_WRCFG_FULL_RESET;
+
+       regs->wdog = BCM2835_WDOG_PASSWORD | RESET_TIMEOUT;
+       regs->rstc = BCM2835_WDOG_PASSWORD | rstc;
+
+}
+
+#define DCFG_RSTCR_RESET_REQ   0x2
+#define CONFIG_SYS_IMMR                                0x01000000
+#define CONFIG_SYS_FSL_GUTS_ADDR               (CONFIG_SYS_IMMR + 0x00ee0000)
+#define TGT 0x01ee00b0
+static void __dead2 rpi3_system_reset(void)
+{
+
+  reset_cpu();
+
+  for (;;);
+
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static const plat_pm_ops_t rpi3_ops = {
+  .affinst_on          = rpi3_affinst_on,
+  .affinst_on_finish   = rpi3_affinst_on_finish,
+  .affinst_off         = NULL,
+  .affinst_standby     = NULL,
+  .affinst_suspend     = NULL,
+  .affinst_suspend_finish      = NULL,
+  .system_off          = rpi3_system_off,
+  .system_reset                = rpi3_system_reset,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops)
+{
+       *plat_ops = &rpi3_ops;
+       return 0;
+}
diff --git a/plat/rpi3/plat_topology.c b/plat/rpi3/plat_topology.c
new file mode 100644 (file)
index 0000000..5ecd710
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <platform_def.h>
+#include <psci.h>
+
+unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr)
+{
+       /* Report 1 (absent) instance at levels higher than the cluster level */
+       if (aff_lvl > MPIDR_AFFLVL1)
+               return 1;
+
+       if (aff_lvl == MPIDR_AFFLVL1)
+               return 1; /* We have one cluster */
+
+       return 4; /* 4 cpus in cluster 0 */
+}
+
+unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr)
+{
+       return aff_lvl <= MPIDR_AFFLVL1 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT;
+}
+
+int plat_get_max_afflvl()
+{
+       return MPIDR_AFFLVL1;
+}
+
+int plat_setup_topology()
+{
+       return 0;
+}
diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk
new file mode 100644 (file)
index 0000000..beba0b0
--- /dev/null
@@ -0,0 +1,54 @@
+ #
+ # Copyright (c) 2016, Sequitur Labs Inc. 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.
+ #
+
+
+# On rpi3, TEE lands in high-RAM, above Linux
+#
+PLAT_TSP_LOCATION      :=      tdram
+
+PLAT_TSP_LOCATION_ID := PLAT_TRUSTED_DRAM_ID
+
+# Process flags
+$(eval $(call add_define,PLAT_TSP_LOCATION_ID))
+
+
+PLAT_INCLUDES          :=      -Iplat/rpi3/include/
+
+PLAT_BL_COMMON_SOURCES :=      lib/aarch64/xlat_tables.c               \
+                               plat/common/aarch64/plat_common.c       \
+                               plat/rpi3/console.c                     \
+                               plat/rpi3/aarch64/rpi3_common.c \
+                               plat/rpi3/aarch64/plat_helpers.S
+
+BL31_SOURCES           +=      lib/cpus/aarch64/cortex_a53.S           \
+                               plat/common/aarch64/platform_mp_stack.S \
+                               plat/rpi3/bl31_plat_setup.c             \
+                               plat/rpi3/plat_pm.c                     \
+                               plat/rpi3/plat_topology.c
diff --git a/plat/rpi3/rpi3_def.h b/plat/rpi3/rpi3_def.h
new file mode 100644 (file)
index 0000000..72fcc64
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RPI3_DEF_H__
+#define __RPI3_DEF_H__
+
+# define UART0_BASE                     0x3f215040
+
+# define DEVICE_BASE                   0x3f000000
+# define DEVICE_SIZE                   0x01000000
+
+/* The size of DDR RAM is 1GB. */
+# define DRAM_BASE                     0x00000000
+# define DRAM_SIZE                     0x40000000
+
+
+# define PLAT_TRUSTED_DRAM_ID  1
+
+/*
+ *   - Non-Secure DRAM (remaining DRAM starting at DRAM_BASE)
+ TEE-shared nonsec starts at 0x20000 ; with 4MB shared
+ */
+
+# define DRAM_NS_BASE                  (0x08000000) 
+# define DRAM_NS_SIZE                  (4 * 1024 * 1024) 
+
+# define DRAM_SEC_BASE                 (DRAM_NS_BASE + DRAM_NS_SIZE)      /* ATF load address */
+# define DRAM_SEC_SIZE                 (28 * 1024 * 1024)
+# define OPTEE_BASE                     (DRAM_SEC_BASE + 0x20000) /* set above ATF by 64k... */
+
+# endif /* __RPI3_DEF_H__ */
diff --git a/plat/rpi3/rpi3_private.h b/plat/rpi3/rpi3_private.h
new file mode 100644 (file)
index 0000000..86c643e
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __RPI3_PRIVATE_H__
+#define __RPI3_PRIVATE_H__
+
+#include <bl_common.h>
+
+/*******************************************************************************
+ * This structure represents the superset of information that is passed to
+ * BL3-1 e.g. while passing control to it from BL2 which is bl31_params
+ * and other platform specific params
+ ******************************************************************************/
+typedef struct bl2_to_bl31_params_mem {
+       struct bl31_params bl31_params;
+       struct image_info bl31_image_info;
+       struct image_info bl32_image_info;
+       struct image_info bl33_image_info;
+       struct entry_point_info bl33_ep_info;
+       struct entry_point_info bl32_ep_info;
+       struct entry_point_info bl31_ep_info;
+} bl2_to_bl31_params_mem_t;
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+void configure_mmu_el3(unsigned long total_base,
+                      unsigned long total_size,
+                      unsigned long ro_start,
+                      unsigned long ro_limit,
+                      unsigned long coh_start,
+                      unsigned long coh_limit);
+
+extern void plat_gic_init(void);
+
+extern uint64_t *bl31_get_spin_tbl_addr(void);
+extern void platform_spin_core(void);
+
+#endif /* __RPI3_PRIVATE_H__ */
diff --git a/readme.md b/readme.md
new file mode 100644 (file)
index 0000000..454b5f1
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,162 @@
+ARM Trusted Firmware - version 1.1
+==================================
+
+ARM Trusted Firmware provides a reference implementation of secure world
+software for [ARMv8-A], including Exception Level 3 (EL3) software. This release
+provides complete support for version 0.2 of the [PSCI] specification, initial
+support for the new version 1.0 of that specification, and prototype support for
+the Trusted Board Boot Requirements specification.
+
+The intent is to provide a reference implementation of various ARM interface
+standards, such as the Power State Coordination Interface ([PSCI]), Trusted
+Board Boot Requirements (TBBR) and [Secure Monitor] [TEE-SMC] code. As far as
+possible the code is designed for reuse or porting to other ARMv8-A model and
+hardware platforms.
+
+ARM will continue development in collaboration with interested parties to
+provide a full reference implementation of PSCI, TBBR and Secure Monitor code
+to the benefit of all developers working with ARMv8-A TrustZone technology.
+
+
+License
+-------
+
+The software is provided under a BSD 3-Clause [license]. Certain source files
+are derived from FreeBSD code: the original license is included in these
+source files.
+
+
+This Release
+------------
+
+This release is a limited functionality implementation of the Trusted Firmware.
+It provides a suitable starting point for productization. Future versions will
+contain new features, optimizations and quality improvements.
+
+### Functionality
+
+*   Prototype implementation of a subset of the Trusted Board Boot Requirements
+    Platform Design Document (PDD). This includes packaging the various firmware
+    images into a Firmware Image Package (FIP) to be loaded from non-volatile
+    storage, and a prototype of authenticated boot using key certificates stored
+    in the FIP.
+
+*   Initializes the secure world (for example, exception vectors, control
+    registers, GIC and interrupts for the platform), before transitioning into
+    the normal world.
+
+*   Supports both GICv2 and GICv3 initialization for use by normal world
+    software.
+
+*   Starts the normal world at the Exception Level and Register Width specified
+    by the platform port. Typically this is AArch64 EL2 if available.
+
+*   Handles SMCs (Secure Monitor Calls) conforming to the [SMC Calling
+    Convention PDD] [SMCCC] using an EL3 runtime services framework.
+
+*   Handles SMCs relating to the [Power State Coordination Interface PDD] [PSCI]
+    for the Secondary CPU Boot, CPU Hotplug, CPU Idle and System Shutdown/Reset
+    use-cases.
+
+*   A Test Secure-EL1 Payload and Dispatcher to demonstrate Secure Monitor
+    functionality such as world switching, EL1 context management and interrupt
+    routing. This also demonstrates Secure-EL1 interaction with PSCI. Some of
+    this functionality is provided in library form for re-use by other
+    Secure-EL1 Payload Dispatchers.
+
+*   Support for alternative Trusted Boot Firmware. Some platforms have their own
+    Trusted Boot implementation and only require the Secure Monitor
+    functionality provided by ARM Trusted Firmware.
+
+*   Isolation of memory accessible by the secure world from the normal world
+    through programming of a TrustZone controller.
+
+*   Support for CPU specific reset sequences, power down sequences and register
+    dumping during crash reporting. The CPU specific reset sequences include
+    support for errata workarounds.
+
+For a full description of functionality and implementation details, please
+see the [Firmware Design] and supporting documentation. The [Change Log]
+provides details of changes made since the last release.
+
+### Platforms
+
+This release of the Trusted Firmware has been tested on Revision B of the
+[Juno ARM Development Platform] [Juno] with Version r0p0-00rel7 of the
+[ARM SCP Firmware] [SCP download].
+
+The Trusted Firmware has also been tested on the 64-bit Linux versions of the
+following ARM [FVP]s:
+
+*   `Foundation_Platform` (Version 9.1, Build 9.1.33)
+*   `FVP_Base_AEMv8A-AEMv8A` (Version 6.2, Build 0.8.6202)
+*   `FVP_Base_Cortex-A57x4-A53x4` (Version 6.2, Build 0.8.6202)
+*   `FVP_Base_Cortex-A57x1-A53x1` (Version 6.2, Build 0.8.6202)
+*   `FVP_Base_Cortex-A57x2-A53x4` (Version 6.2, Build 0.8.6202)
+
+The Foundation FVP can be downloaded free of charge. The Base FVPs can be
+licensed from ARM: see [www.arm.com/fvp] [FVP].
+
+### Still to Come
+
+*   Complete and more flexible Trusted Board Boot implementation.
+
+*   Complete implementation of the [PSCI] v1.0 specification.
+
+*   Support for alternative types of Secure-EL1 Payloads.
+
+*   Extending the GICv3 support to the secure world.
+
+*   Support for new System IP devices.
+
+For a full list of detailed issues in the current code, please see the [Change
+Log] and the [GitHub issue tracker].
+
+
+Getting Started
+---------------
+
+Get the Trusted Firmware source code from
+[GitHub](https://www.github.com/ARM-software/arm-trusted-firmware).
+
+See the [User Guide] for instructions on how to install, build and use
+the Trusted Firmware with the ARM [FVP]s.
+
+See the [Firmware Design] for information on how the ARM Trusted Firmware works.
+
+See the [Porting Guide] as well for information about how to use this
+software on another ARMv8-A platform.
+
+See the [Contributing Guidelines] for information on how to contribute to this
+project and the [Acknowledgments] file for a list of contributors to the
+project.
+
+### Feedback and support
+
+ARM welcomes any feedback on the Trusted Firmware. Please send feedback using
+the [GitHub issue tracker].
+
+ARM licensees may contact ARM directly via their partner managers.
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved._
+
+
+[License]:                  ./license.md "BSD license for ARM Trusted Firmware"
+[Contributing Guidelines]:  ./contributing.md "Guidelines for contributors"
+[Acknowledgments]:          ./acknowledgements.md "Contributor acknowledgments"
+[Change Log]:               ./docs/change-log.md
+[User Guide]:               ./docs/user-guide.md
+[Firmware Design]:          ./docs/firmware-design.md
+[Porting Guide]:            ./docs/porting-guide.md
+
+[ARMv8-A]:               http://www.arm.com/products/processors/armv8-architecture.php "ARMv8-A Architecture"
+[FVP]:                   http://www.arm.com/fvp "ARM's Fixed Virtual Platforms"
+[Juno]:                  http://www.arm.com/products/tools/development-boards/versatile-express/juno-arm-development-platform.php "Juno ARM Development Platform"
+[SCP download]:          https://silver.arm.com/download/download.tm?pv=1764630
+[PSCI]:                  http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf "Power State Coordination Interface PDD (ARM DEN 0022C)"
+[SMCCC]:                 http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html "SMC Calling Convention PDD (ARM DEN 0028A)"
+[TEE-SMC]:               http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php "Secure Monitor and TEEs"
+[GitHub issue tracker]:  https://github.com/ARM-software/tf-issues/issues
diff --git a/services/spd/opteed/opteed.mk b/services/spd/opteed/opteed.mk
new file mode 100644 (file)
index 0000000..8057dcc
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+OPTEED_DIR             :=      services/spd/opteed
+SPD_INCLUDES           :=
+
+SPD_SOURCES            :=      services/spd/opteed/opteed_common.c     \
+                               services/spd/opteed/opteed_helpers.S    \
+                               services/spd/opteed/opteed_main.c       \
+                               services/spd/opteed/opteed_pm.c
+
+NEED_BL32              :=      yes
diff --git a/services/spd/opteed/opteed_common.c b/services/spd/opteed/opteed_common.c
new file mode 100644 (file)
index 0000000..5743102
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <context_mgmt.h>
+#include <string.h>
+#include "opteed_private.h"
+
+/*******************************************************************************
+ * Given a OPTEE entrypoint info pointer, entry point PC, register width,
+ * cpu id & pointer to a context data structure, this function will
+ * initialize OPTEE context and entry point info for OPTEE.
+ ******************************************************************************/
+void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point,
+                               uint32_t rw, uint64_t pc,
+                               uint64_t paged_part, uint64_t mem_limit,
+                               optee_context_t *optee_ctx)
+{
+       uint32_t ep_attr;
+
+       /* Passing a NULL context is a critical programming error */
+       assert(optee_ctx);
+       assert(optee_entry_point);
+       assert(pc);
+
+       /* Associate this context with the cpu specified */
+       optee_ctx->mpidr = read_mpidr_el1();
+       optee_ctx->state = 0;
+       set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF);
+
+       cm_set_context(&optee_ctx->cpu_ctx, SECURE);
+
+       /* initialise an entrypoint to set up the CPU context */
+       ep_attr = SECURE | EP_ST_ENABLE;
+       if (read_sctlr_el3() & SCTLR_EE_BIT)
+               ep_attr |= EP_EE_BIG;
+       SET_PARAM_HEAD(optee_entry_point, PARAM_EP, VERSION_1, ep_attr);
+       optee_entry_point->pc = pc;
+       if (rw == OPTEE_AARCH64)
+               optee_entry_point->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+                                                 DISABLE_ALL_EXCEPTIONS);
+       else
+               optee_entry_point->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+                                                     SPSR_E_LITTLE,
+                                                     DAIF_FIQ_BIT |
+                                                       DAIF_IRQ_BIT |
+                                                       DAIF_ABT_BIT);
+       memset(&optee_entry_point->args, 0, sizeof(optee_entry_point->args));
+       optee_entry_point->args.arg0 = paged_part;
+       optee_entry_point->args.arg1 = mem_limit;
+}
+
+/*******************************************************************************
+ * This function takes an OPTEE context pointer and:
+ * 1. Applies the S-EL1 system register context from optee_ctx->cpu_ctx.
+ * 2. Saves the current C runtime state (callee saved registers) on the stack
+ *    frame and saves a reference to this state.
+ * 3. Calls el3_exit() so that the EL3 system and general purpose registers
+ *    from the optee_ctx->cpu_ctx are used to enter the OPTEE image.
+ ******************************************************************************/
+uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx)
+{
+       uint64_t rc;
+
+       assert(optee_ctx != NULL);
+       assert(optee_ctx->c_rt_ctx == 0);
+
+       /* Apply the Secure EL1 system register context and switch to it */
+       assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx);
+       cm_el1_sysregs_context_restore(SECURE);
+       cm_set_next_eret_context(SECURE);
+
+       rc = opteed_enter_sp(&optee_ctx->c_rt_ctx);
+#if DEBUG
+       optee_ctx->c_rt_ctx = 0;
+#endif
+
+       return rc;
+}
+
+
+/*******************************************************************************
+ * This function takes an OPTEE context pointer and:
+ * 1. Saves the S-EL1 system register context tp optee_ctx->cpu_ctx.
+ * 2. Restores the current C runtime state (callee saved registers) from the
+ *    stack frame using the reference to this state saved in opteed_enter_sp().
+ * 3. It does not need to save any general purpose or EL3 system register state
+ *    as the generic smc entry routine should have saved those.
+ ******************************************************************************/
+void opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret)
+{
+       assert(optee_ctx != NULL);
+       /* Save the Secure EL1 system register context */
+       assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx);
+       cm_el1_sysregs_context_save(SECURE);
+
+       assert(optee_ctx->c_rt_ctx != 0);
+       opteed_exit_sp(optee_ctx->c_rt_ctx, ret);
+
+       /* Should never reach here */
+       assert(0);
+}
diff --git a/services/spd/opteed/opteed_helpers.S b/services/spd/opteed/opteed_helpers.S
new file mode 100644 (file)
index 0000000..ef59540
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm_macros.S>
+#include "opteed_private.h"
+
+       .global opteed_enter_sp
+       /* ---------------------------------------------
+        * This function is called with SP_EL0 as stack.
+        * Here we stash our EL3 callee-saved registers
+        * on to the stack as a part of saving the C
+        * runtime and enter the secure payload.
+        * 'x0' contains a pointer to the memory where
+        * the address of the C runtime context is to be
+        * saved.
+        * ---------------------------------------------
+        */
+func opteed_enter_sp
+       /* Make space for the registers that we're going to save */
+       mov     x3, sp
+       str     x3, [x0, #0]
+       sub     sp, sp, #OPTEED_C_RT_CTX_SIZE
+
+       /* Save callee-saved registers on to the stack */
+       stp     x19, x20, [sp, #OPTEED_C_RT_CTX_X19]
+       stp     x21, x22, [sp, #OPTEED_C_RT_CTX_X21]
+       stp     x23, x24, [sp, #OPTEED_C_RT_CTX_X23]
+       stp     x25, x26, [sp, #OPTEED_C_RT_CTX_X25]
+       stp     x27, x28, [sp, #OPTEED_C_RT_CTX_X27]
+       stp     x29, x30, [sp, #OPTEED_C_RT_CTX_X29]
+
+       /* ---------------------------------------------
+        * Everything is setup now. el3_exit() will
+        * use the secure context to restore to the
+        * general purpose and EL3 system registers to
+        * ERET into OPTEE.
+        * ---------------------------------------------
+        */
+       b       el3_exit
+
+       /* ---------------------------------------------
+        * This function is called 'x0' pointing to a C
+        * runtime context saved in opteed_enter_sp().  It
+        * restores the saved registers and jumps to
+        * that runtime with 'x0' as the new sp. This
+        * destroys the C runtime context that had been
+        * built on the stack below the saved context by
+        * the caller. Later the second parameter 'x1'
+        * is passed as return value to the caller
+        * ---------------------------------------------
+        */
+       .global opteed_exit_sp
+func opteed_exit_sp
+       /* Restore the previous stack */
+       mov     sp, x0
+
+       /* Restore callee-saved registers on to the stack */
+       ldp     x19, x20, [x0, #(OPTEED_C_RT_CTX_X19 - OPTEED_C_RT_CTX_SIZE)]
+       ldp     x21, x22, [x0, #(OPTEED_C_RT_CTX_X21 - OPTEED_C_RT_CTX_SIZE)]
+       ldp     x23, x24, [x0, #(OPTEED_C_RT_CTX_X23 - OPTEED_C_RT_CTX_SIZE)]
+       ldp     x25, x26, [x0, #(OPTEED_C_RT_CTX_X25 - OPTEED_C_RT_CTX_SIZE)]
+       ldp     x27, x28, [x0, #(OPTEED_C_RT_CTX_X27 - OPTEED_C_RT_CTX_SIZE)]
+       ldp     x29, x30, [x0, #(OPTEED_C_RT_CTX_X29 - OPTEED_C_RT_CTX_SIZE)]
+
+       /* ---------------------------------------------
+        * This should take us back to the instruction
+        * after the call to the last opteed_enter_sp().
+        * Place the second parameter to x0 so that the
+        * caller will see it as a return value from the
+        * original entry call
+        * ---------------------------------------------
+        */
+       mov     x0, x1
+       ret
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
new file mode 100644 (file)
index 0000000..49a301a
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+
+/*******************************************************************************
+ * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a
+ * plug-in component to the Secure Monitor, registered as a runtime service. The
+ * SPD is expected to be a functional extension of the Secure Payload (SP) that
+ * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting
+ * the Trusted OS/Applications range to the dispatcher. The SPD will either
+ * handle the request locally or delegate it to the Secure Payload. It is also
+ * responsible for initialising and maintaining communication with the SP.
+ ******************************************************************************/
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <errno.h>
+#include <platform.h>
+#include <runtime_svc.h>
+#include <stddef.h>
+#include <string.h>
+#include <uuid.h>
+#include "opteed_private.h"
+#include "teesmc_opteed_macros.h"
+#include "teesmc_opteed.h"
+
+#define OPTEE_MAGIC            0x4554504f
+#define OPTEE_VERSION          1
+#define OPTEE_ARCH_ARM32       0
+#define OPTEE_ARCH_ARM64       1
+
+struct optee_header {
+       uint32_t magic;
+       uint8_t version;
+       uint8_t arch;
+       uint16_t flags;
+       uint32_t init_size;
+       uint32_t init_load_addr_hi;
+       uint32_t init_load_addr_lo;
+       uint32_t init_mem_usage;
+       uint32_t paged_size;
+};
+
+/*******************************************************************************
+ * Address of the entrypoint vector table in OPTEE. It is
+ * initialised once on the primary core after a cold boot.
+ ******************************************************************************/
+optee_vectors_t *optee_vectors;
+
+/*******************************************************************************
+ * Array to keep track of per-cpu OPTEE state
+ ******************************************************************************/
+optee_context_t opteed_sp_context[OPTEED_CORE_COUNT];
+uint32_t opteed_rw;
+
+
+
+static int32_t opteed_init(void);
+
+/*******************************************************************************
+ * This function is the handler registered for S-EL1 interrupts by the
+ * OPTEED. It validates the interrupt and upon success arranges entry into
+ * the OPTEE at 'optee_fiq_entry()' for handling the interrupt.
+ ******************************************************************************/
+static uint64_t opteed_sel1_interrupt_handler(uint32_t id,
+                                           uint32_t flags,
+                                           void *handle,
+                                           void *cookie)
+{
+       uint32_t linear_id;
+       uint64_t mpidr;
+       optee_context_t *optee_ctx;
+
+       /* Check the security state when the exception was generated */
+       assert(get_interrupt_src_ss(flags) == NON_SECURE);
+
+#if IMF_READ_INTERRUPT_ID
+       /* Check the security status of the interrupt */
+       assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_S_EL1);
+#endif
+
+       /* Sanity check the pointer to this cpu's context */
+       mpidr = read_mpidr();
+       assert(handle == cm_get_context(NON_SECURE));
+
+       /* Save the non-secure context before entering the OPTEE */
+       cm_el1_sysregs_context_save(NON_SECURE);
+
+       /* Get a reference to this cpu's OPTEE context */
+       linear_id = platform_get_core_pos(mpidr);
+       optee_ctx = &opteed_sp_context[linear_id];
+       assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE));
+
+       cm_set_elr_el3(SECURE, (uint64_t)&optee_vectors->fiq_entry);
+       cm_el1_sysregs_context_restore(SECURE);
+       cm_set_next_eret_context(SECURE);
+
+       /*
+        * Tell the OPTEE that it has to handle an FIQ (synchronously).
+        * Also the instruction in normal world where the interrupt was
+        * generated is passed for debugging purposes. It is safe to
+        * retrieve this address from ELR_EL3 as the secure context will
+        * not take effect until el3_exit().
+        */
+       SMC_RET1(&optee_ctx->cpu_ctx, read_elr_el3());
+}
+
+
+static int is_mem_free(uint64_t free_base, size_t free_size,
+                      uint64_t addr, size_t size)
+{
+       return (addr >= free_base) && (addr + size <= free_base + free_size);
+}
+
+/*******************************************************************************
+ * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type
+ * (aarch32/aarch64) if not already known and initialises the context for entry
+ * into OPTEE for its initialization.
+ ******************************************************************************/
+int32_t opteed_setup(void)
+{
+       entry_point_info_t *ep_info;
+       struct optee_header *header;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id;
+       uintptr_t init_load_addr;
+       size_t init_size;
+       size_t init_mem_usage;
+       uintptr_t payload_addr;
+       uintptr_t mem_limit;
+       uintptr_t paged_part;
+       uintptr_t paged_size;
+
+       linear_id = platform_get_core_pos(mpidr);
+
+       /*
+        * Get information about the Secure Payload (BL32) image. Its
+        * absence is a critical failure.  TODO: Add support to
+        * conditionally include the SPD service
+        */
+       ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+       if (!ep_info) {
+               WARN("No OPTEE provided by BL2 boot loader.\n");
+               goto err;
+       }
+
+       header = (struct optee_header *)ep_info->pc;
+
+       if (header->magic != OPTEE_MAGIC || header->version != OPTEE_VERSION) {
+               WARN("Invalid OPTEE header.\n");
+               goto err;
+       }
+
+       if (header->arch == OPTEE_ARCH_ARM32)
+               opteed_rw = OPTEE_AARCH32;
+       else if (header->arch == OPTEE_ARCH_ARM64)
+               opteed_rw = OPTEE_AARCH64;
+       else {
+               WARN("Invalid OPTEE architecture (%d)\n", header->arch);
+               goto err;
+       }
+
+       init_load_addr = ((uint64_t)header->init_load_addr_hi << 32) |
+                               header->init_load_addr_lo;
+       init_size = header->init_size;
+       init_mem_usage = header->init_mem_usage;
+       payload_addr = (uintptr_t)(header + 1);
+       paged_size = header->paged_size;
+
+       /*
+        * Move OPTEE binary to the required location in memory.
+        *
+        * There's two ways OPTEE can be running in memory:
+        * 1. A memory large enough to keep the entire OPTEE binary
+        *    (DRAM currently)
+        * 2. A part of OPTEE in a smaller (and more secure) memory
+        *    (SRAM currently). This is achieved with demand paging
+        *    of read-only data/code against a backing store in some
+        *    larger memory (DRAM currently).
+        *
+        * In either case dictates init_load_addr in the OPTEE
+        * header the address where what's after the header
+        * (payload) should be residing when started. init_size in
+        * the header tells how much of the payload that need to be
+        * copied. init_mem_usage tells how much runtime memory in
+        * total is needed by OPTEE.
+        *
+        * In alternative 2 there's additional data after
+        * init_size, this is the rest of OPTEE which is demand
+        * paged into memory.  A pointer to that data is supplied
+        * to OPTEE when initializing.
+        *
+        * Alternative 1 only uses DRAM when executing OPTEE while
+        * alternative 2 uses both SRAM and DRAM to execute.
+        *
+        * All data written which is later read by OPTEE must be flushed
+        * out to memory since OPTEE starts with MMU turned off and caches
+        * disabled.
+        */
+       if (is_mem_free(BL32_SRAM_BASE,
+                        BL32_SRAM_LIMIT - BL32_SRAM_BASE,
+                        init_load_addr, init_mem_usage)) {
+               /* Running in SRAM, paging some code against DRAM */
+               memcpy((void *)init_load_addr, (void *)payload_addr,
+                      init_size);
+               flush_dcache_range(init_load_addr, init_size);
+               paged_part = payload_addr + init_size;
+               mem_limit = BL32_SRAM_LIMIT;
+       } else if (is_mem_free(BL32_DRAM_BASE,
+                              BL32_DRAM_LIMIT - BL32_DRAM_BASE,
+                              init_load_addr, init_mem_usage)) {
+               /*
+                * Running in DRAM.
+                *
+                * The paged part normally empty, but if it isn't,
+                * move it to the end of DRAM before moving the
+                * init part in place.
+                */
+               paged_part = BL32_DRAM_LIMIT - paged_size;
+               if (paged_size) {
+                       if (!is_mem_free(BL32_DRAM_BASE,
+                                        BL32_DRAM_LIMIT - BL32_DRAM_BASE,
+                                        init_load_addr,
+                                        init_mem_usage + paged_size)) {
+                               WARN("Failed to reserve memory 0x%lx - 0x%lx\n",
+                                     init_load_addr,
+                                     init_load_addr + init_mem_usage +
+                                       paged_size);
+                               goto err;
+                       }
+
+                       memcpy((void *)paged_part,
+                               (void *)(payload_addr + init_size),
+                               paged_size);
+                       flush_dcache_range(paged_part, paged_size);
+               }
+
+               memmove((void *)init_load_addr, (void *)payload_addr,
+                       init_size);
+               flush_dcache_range(init_load_addr, init_size);
+               mem_limit = BL32_DRAM_LIMIT;
+       } else {
+               WARN("Failed to reserve memory 0x%lx - 0x%lx\n",
+                       init_load_addr, init_load_addr + init_mem_usage);
+               goto err;
+       }
+
+
+       opteed_init_optee_ep_state(ep_info, opteed_rw, init_load_addr,
+                                  paged_part, mem_limit,
+                                  &opteed_sp_context[linear_id]);
+
+       /*
+        * All OPTEED initialization done. Now register our init function with
+        * BL31 for deferred invocation
+        */
+       bl31_register_bl32_init(&opteed_init);
+
+       return 0;
+
+err:
+       WARN("Booting device without OPTEE initialization.\n");
+       WARN("SMC`s destined for OPTEE will return SMC_UNK\n");
+       return 1;
+}
+
+/*******************************************************************************
+ * This function passes control to the OPTEE image (BL32) for the first time
+ * on the primary cpu after a cold boot. It assumes that a valid secure
+ * context has already been created by opteed_setup() which can be directly
+ * used.  It also assumes that a valid non-secure context has been
+ * initialised by PSCI so it does not need to save and restore any
+ * non-secure state. This function performs a synchronous entry into
+ * OPTEE. OPTEE passes control back to this routine through a SMC.
+ ******************************************************************************/
+static int32_t opteed_init(void)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+       entry_point_info_t *optee_entry_point;
+       uint64_t rc;
+
+       /*
+        * Get information about the OPTEE (BL32) image. Its
+        * absence is a critical failure.
+        */
+       optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
+       assert(optee_entry_point);
+
+       cm_init_context(mpidr, optee_entry_point);
+
+       /*
+        * Arrange for an entry into OPTEE. It will be returned via
+        * OPTEE_ENTRY_DONE case
+        */
+       rc = opteed_synchronous_sp_entry(optee_ctx);
+       assert(rc != 0);
+
+       return rc;
+}
+
+
+/*******************************************************************************
+ * This function is responsible for handling all SMCs in the Trusted OS/App
+ * range from the non-secure state as defined in the SMC Calling Convention
+ * Document. It is also responsible for communicating with the Secure
+ * payload to delegate work and return results back to the non-secure
+ * state. Lastly it will also return any information that OPTEE needs to do
+ * the work assigned to it.
+ ******************************************************************************/
+uint64_t opteed_smc_handler(uint32_t smc_fid,
+                        uint64_t x1,
+                        uint64_t x2,
+                        uint64_t x3,
+                        uint64_t x4,
+                        void *cookie,
+                        void *handle,
+                        uint64_t flags)
+{
+       cpu_context_t *ns_cpu_context;
+       unsigned long mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+       uint64_t rc;
+
+       /*
+        * Determine which security state this SMC originated from
+        */
+
+       if (is_caller_non_secure(flags)) {
+               gp_regs_t *sec_gpregs = get_gpregs_ctx(&optee_ctx->cpu_ctx);
+               gp_regs_t *ns_gpregs = get_gpregs_ctx(handle);
+
+               /*
+                * This is a fresh request from the non-secure client.
+                * The parameters are in x1 and x2. Figure out which
+                * registers need to be preserved, save the non-secure
+                * state and send the request to the secure payload.
+                */
+               assert(handle == cm_get_context(NON_SECURE));
+
+               cm_el1_sysregs_context_save(NON_SECURE);
+
+               /*
+                * We are done stashing the non-secure context. Ask the
+                * OPTEE to do the work now.
+                */
+
+               /*
+                * Verify if there is a valid context to use, copy the
+                * operation type and parameters to the secure context
+                * and jump to the fast smc entry point in the secure
+                * payload. Entry into S-EL1 will take place upon exit
+                * from this function.
+                */
+               assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE));
+
+               /* Set appropriate entry for SMC.
+                * We expect OPTEE to manage the PSTATE.I and PSTATE.F
+                * flags as appropriate.
+                */
+               if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) {
+                       cm_set_elr_el3(SECURE, (uint64_t)
+                                       &optee_vectors->fast_smc_entry);
+               } else {
+                       cm_set_elr_el3(SECURE, (uint64_t)
+                                       &optee_vectors->std_smc_entry);
+               }
+
+               cm_el1_sysregs_context_restore(SECURE);
+               cm_set_next_eret_context(SECURE);
+
+               /* Propagate X4-X7 */
+               write_ctx_reg(sec_gpregs, CTX_GPREG_X4,
+                             read_ctx_reg(ns_gpregs, CTX_GPREG_X4));
+               write_ctx_reg(sec_gpregs, CTX_GPREG_X5,
+                             read_ctx_reg(ns_gpregs, CTX_GPREG_X5));
+               write_ctx_reg(sec_gpregs, CTX_GPREG_X6,
+                             read_ctx_reg(ns_gpregs, CTX_GPREG_X6));
+               write_ctx_reg(sec_gpregs, CTX_GPREG_X7,
+                             read_ctx_reg(ns_gpregs, CTX_GPREG_X7));
+
+               SMC_RET4(&optee_ctx->cpu_ctx, smc_fid, x1, x2, x3);
+       }
+
+       /*
+        * Returning from OPTEE
+        */
+
+       switch (smc_fid) {
+       /*
+        * OPTEE has finished initialising itself after a cold boot
+        */
+       case TEESMC_OPTEED_RETURN_ENTRY_DONE:
+               /*
+                * Stash the OPTEE entry points information. This is done
+                * only once on the primary cpu
+                */
+               assert(optee_vectors == NULL);
+               optee_vectors = (optee_vectors_t *) x1;
+
+               if (optee_vectors) {
+                       set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
+
+                       /*
+                        * OPTEE has been successfully initialized.
+                        * Register power management hooks with PSCI
+                        */
+                       psci_register_spd_pm_hook(&opteed_pm);
+
+                       /*
+                        * Register an interrupt handler for S-EL1 interrupts
+                        * when generated during code executing in the
+                        * non-secure state.
+                        */
+                       flags = 0;
+                       set_interrupt_rm_flag(flags, NON_SECURE);
+                       rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+                                               opteed_sel1_interrupt_handler,
+                                               flags);
+                       if (rc)
+                               panic();
+               }
+
+               /*
+                * OPTEE reports completion. The OPTEED must have initiated
+                * the original request through a synchronous entry into
+                * OPTEE. Jump back to the original C runtime context.
+                */
+               opteed_synchronous_sp_exit(optee_ctx, x1);
+
+
+       /*
+        * These function IDs is used only by OP-TEE to indicate it has
+        * finished:
+        * 1. turning itself on in response to an earlier psci
+        *    cpu_on request
+        * 2. resuming itself after an earlier psci cpu_suspend
+        *    request.
+        */
+       case TEESMC_OPTEED_RETURN_ON_DONE:
+       case TEESMC_OPTEED_RETURN_RESUME_DONE:
+
+
+       /*
+        * These function IDs is used only by the SP to indicate it has
+        * finished:
+        * 1. suspending itself after an earlier psci cpu_suspend
+        *    request.
+        * 2. turning itself off in response to an earlier psci
+        *    cpu_off request.
+        */
+       case TEESMC_OPTEED_RETURN_OFF_DONE:
+       case TEESMC_OPTEED_RETURN_SUSPEND_DONE:
+       case TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE:
+       case TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE:
+
+               /*
+                * OPTEE reports completion. The OPTEED must have initiated the
+                * original request through a synchronous entry into OPTEE.
+                * Jump back to the original C runtime context, and pass x1 as
+                * return value to the caller
+                */
+               opteed_synchronous_sp_exit(optee_ctx, x1);
+
+       /*
+        * OPTEE is returning from a call or being preempted from a call, in
+        * either case execution should resume in the normal world.
+        */
+       case TEESMC_OPTEED_RETURN_CALL_DONE:
+               /*
+                * This is the result from the secure client of an
+                * earlier request. The results are in x0-x3. Copy it
+                * into the non-secure context, save the secure state
+                * and return to the non-secure state.
+                */
+               assert(handle == cm_get_context(SECURE));
+               cm_el1_sysregs_context_save(SECURE);
+
+               /* Get a reference to the non-secure context */
+               ns_cpu_context = cm_get_context(NON_SECURE);
+               assert(ns_cpu_context);
+
+               /* Restore non-secure state */
+               cm_el1_sysregs_context_restore(NON_SECURE);
+               cm_set_next_eret_context(NON_SECURE);
+
+               SMC_RET4(ns_cpu_context, x1, x2, x3, x4);
+
+       /*
+        * OPTEE has finished handling a S-EL1 FIQ interrupt. Execution
+        * should resume in the normal world.
+        */
+       case TEESMC_OPTEED_RETURN_FIQ_DONE:
+               /* Get a reference to the non-secure context */
+               ns_cpu_context = cm_get_context(NON_SECURE);
+               assert(ns_cpu_context);
+
+               /*
+                * Restore non-secure state. There is no need to save the
+                * secure system register context since OPTEE was supposed
+                * to preserve it during S-EL1 interrupt handling.
+                */
+               cm_el1_sysregs_context_restore(NON_SECURE);
+               cm_set_next_eret_context(NON_SECURE);
+
+               SMC_RET0((uint64_t) ns_cpu_context);
+
+       default:
+               panic();
+       }
+}
+
+/* Define an OPTEED runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+       opteed_fast,
+
+       OEN_TOS_START,
+       OEN_TOS_END,
+       SMC_TYPE_FAST,
+       opteed_setup,
+       opteed_smc_handler
+);
+
+/* Define an OPTEED runtime service descriptor for standard SMC calls */
+DECLARE_RT_SVC(
+       opteed_std,
+
+       OEN_TOS_START,
+       OEN_TOS_END,
+       SMC_TYPE_STD,
+       NULL,
+       opteed_smc_handler
+);
diff --git a/services/spd/opteed/opteed_pm.c b/services/spd/opteed/opteed_pm.c
new file mode 100644 (file)
index 0000000..bce0d2f
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <platform.h>
+#include "opteed_private.h"
+
+/*******************************************************************************
+ * The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any
+ * actions needed. Nothing at the moment.
+ ******************************************************************************/
+static void opteed_cpu_on_handler(uint64_t target_cpu)
+{
+}
+
+/*******************************************************************************
+ * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions
+ * needed
+ ******************************************************************************/
+static int32_t opteed_cpu_off_handler(uint64_t unused)
+{
+       int32_t rc = 0;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+
+       assert(optee_vectors);
+       assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
+
+       /* Program the entry point and enter OPTEE */
+       cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_off_entry);
+       rc = opteed_synchronous_sp_entry(optee_ctx);
+
+       /*
+        * Read the response from OPTEE. A non-zero return means that
+        * something went wrong while communicating with OPTEE.
+        */
+       if (rc != 0)
+               panic();
+
+       /*
+        * Reset OPTEE's context for a fresh start when this cpu is turned on
+        * subsequently.
+        */
+       set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF);
+
+        return 0;
+}
+
+/*******************************************************************************
+ * This cpu is being suspended. S-EL1 state must have been saved in the
+ * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
+ ******************************************************************************/
+static void opteed_cpu_suspend_handler(uint64_t unused)
+{
+       int32_t rc = 0;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+
+       assert(optee_vectors);
+       assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
+
+       /* Program the entry point and enter OPTEE */
+       cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_suspend_entry);
+       rc = opteed_synchronous_sp_entry(optee_ctx);
+
+       /*
+        * Read the response from OPTEE. A non-zero return means that
+        * something went wrong while communicating with OPTEE.
+        */
+       if (rc != 0)
+               panic();
+
+       /* Update its context to reflect the state OPTEE is in */
+       set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND);
+}
+
+/*******************************************************************************
+ * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits
+ * before passing control back to the Secure Monitor. Entry in S-El1 is done
+ * after initialising minimal architectural state that guarantees safe
+ * execution.
+ ******************************************************************************/
+static void opteed_cpu_on_finish_handler(uint64_t unused)
+{
+       int32_t rc = 0;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+       entry_point_info_t optee_on_entrypoint;
+
+       assert(optee_vectors);
+       assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF);
+
+       opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
+                               (uint64_t)&optee_vectors->cpu_on_entry,
+                               0, 0, optee_ctx);
+
+       /* Initialise this cpu's secure context */
+       cm_init_context(mpidr, &optee_on_entrypoint);
+
+       /* Enter OPTEE */
+       rc = opteed_synchronous_sp_entry(optee_ctx);
+
+       /*
+        * Read the response from OPTEE. A non-zero return means that
+        * something went wrong while communicating with OPTEE.
+        */
+       if (rc != 0)
+               panic();
+
+       /* Update its context to reflect the state OPTEE is in */
+       set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
+}
+
+/*******************************************************************************
+ * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it
+ * completed the preceding suspend call. Use that context to program an entry
+ * into OPTEE to allow it to do any remaining book keeping
+ ******************************************************************************/
+static void opteed_cpu_suspend_finish_handler(uint64_t suspend_level)
+{
+       int32_t rc = 0;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+
+       assert(optee_vectors);
+       assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND);
+
+       /* Program the entry point, suspend_level and enter the SP */
+       write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
+                     CTX_GPREG_X0,
+                     suspend_level);
+       cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_resume_entry);
+       rc = opteed_synchronous_sp_entry(optee_ctx);
+
+       /*
+        * Read the response from OPTEE. A non-zero return means that
+        * something went wrong while communicating with OPTEE.
+        */
+       if (rc != 0)
+               panic();
+
+       /* Update its context to reflect the state OPTEE is in */
+       set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
+}
+
+/*******************************************************************************
+ * Return the type of OPTEE the OPTEED is dealing with. Report the current
+ * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
+ ******************************************************************************/
+static int32_t opteed_cpu_migrate_info(uint64_t *resident_cpu)
+{
+       return OPTEE_MIGRATE_INFO;
+}
+
+/*******************************************************************************
+ * System is about to be switched off. Allow the OPTEED/OPTEE to perform
+ * any actions needed.
+ ******************************************************************************/
+static void opteed_system_off(void)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+
+       assert(optee_vectors);
+       assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
+
+       /* Program the entry point */
+       cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->system_off_entry);
+
+       /* Enter OPTEE. We do not care about the return value because we
+        * must continue the shutdown anyway */
+       opteed_synchronous_sp_entry(optee_ctx);
+}
+
+/*******************************************************************************
+ * System is about to be reset. Allow the OPTEED/OPTEE to perform
+ * any actions needed.
+ ******************************************************************************/
+static void opteed_system_reset(void)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+
+       assert(optee_vectors);
+       assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
+
+       /* Program the entry point */
+       cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->system_reset_entry);
+
+       /* Enter OPTEE. We do not care about the return value because we
+        * must continue the reset anyway */
+       opteed_synchronous_sp_entry(optee_ctx);
+}
+
+
+/*******************************************************************************
+ * Structure populated by the OPTEE Dispatcher to be given a chance to
+ * perform any OPTEE bookkeeping before PSCI executes a power mgmt.
+ * operation.
+ ******************************************************************************/
+const spd_pm_ops_t opteed_pm = {
+       .svc_on = opteed_cpu_on_handler,
+       .svc_off = opteed_cpu_off_handler,
+       .svc_suspend = opteed_cpu_suspend_handler,
+       .svc_on_finish = opteed_cpu_on_finish_handler,
+       .svc_suspend_finish = opteed_cpu_suspend_finish_handler,
+       .svc_migrate = NULL,
+       .svc_migrate_info = opteed_cpu_migrate_info,
+       .svc_system_off = opteed_system_off,
+       .svc_system_reset = opteed_system_reset,
+};
+
diff --git a/services/spd/opteed/opteed_private.h b/services/spd/opteed/opteed_private.h
new file mode 100644 (file)
index 0000000..72fd97a
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OPTEED_PRIVATE_H__
+#define __OPTEED_PRIVATE_H__
+
+#include <arch.h>
+#include <context.h>
+#include <interrupt_mgmt.h>
+#include <platform_def.h>
+#include <psci.h>
+
+/*******************************************************************************
+ * OPTEE PM state information e.g. OPTEE is suspended, uninitialised etc
+ * and macros to access the state information in the per-cpu 'state' flags
+ ******************************************************************************/
+#define OPTEE_PSTATE_OFF               0
+#define OPTEE_PSTATE_ON                        1
+#define OPTEE_PSTATE_SUSPEND           2
+#define OPTEE_PSTATE_SHIFT             0
+#define OPTEE_PSTATE_MASK              0x3
+#define get_optee_pstate(state)        ((state >> OPTEE_PSTATE_SHIFT) & \
+                                OPTEE_PSTATE_MASK)
+#define clr_optee_pstate(state)        (state &= ~(OPTEE_PSTATE_MASK \
+                                           << OPTEE_PSTATE_SHIFT))
+#define set_optee_pstate(st, pst) do {                                        \
+                                       clr_optee_pstate(st);                  \
+                                       st |= (pst & OPTEE_PSTATE_MASK) <<     \
+                                               OPTEE_PSTATE_SHIFT;            \
+                               } while (0)
+
+
+/*******************************************************************************
+ * OPTEE execution state information i.e. aarch32 or aarch64
+ ******************************************************************************/
+#define OPTEE_AARCH32          MODE_RW_32
+#define OPTEE_AARCH64          MODE_RW_64
+
+/*******************************************************************************
+ * The OPTEED should know the type of OPTEE
+ ******************************************************************************/
+#define OPTEE_TYPE_UP          PSCI_TOS_NOT_UP_MIG_CAP
+#define OPTEE_TYPE_UPM         PSCI_TOS_UP_MIG_CAP
+#define OPTEE_TYPE_MP          PSCI_TOS_NOT_PRESENT_MP
+
+/*******************************************************************************
+ * OPTEE migrate type information as known to the OPTEED. We assume that
+ * the OPTEED is dealing with an MP Secure Payload.
+ ******************************************************************************/
+#define OPTEE_MIGRATE_INFO             OPTEE_TYPE_MP
+
+/*******************************************************************************
+ * Number of cpus that the present on this platform. TODO: Rely on a topology
+ * tree to determine this in the future to avoid assumptions about mpidr
+ * allocation
+ ******************************************************************************/
+#define OPTEED_CORE_COUNT              PLATFORM_CORE_COUNT
+
+/*******************************************************************************
+ * Constants that allow assembler code to preserve callee-saved registers of the
+ * C runtime context while performing a security state switch.
+ ******************************************************************************/
+#define OPTEED_C_RT_CTX_X19            0x0
+#define OPTEED_C_RT_CTX_X20            0x8
+#define OPTEED_C_RT_CTX_X21            0x10
+#define OPTEED_C_RT_CTX_X22            0x18
+#define OPTEED_C_RT_CTX_X23            0x20
+#define OPTEED_C_RT_CTX_X24            0x28
+#define OPTEED_C_RT_CTX_X25            0x30
+#define OPTEED_C_RT_CTX_X26            0x38
+#define OPTEED_C_RT_CTX_X27            0x40
+#define OPTEED_C_RT_CTX_X28            0x48
+#define OPTEED_C_RT_CTX_X29            0x50
+#define OPTEED_C_RT_CTX_X30            0x58
+#define OPTEED_C_RT_CTX_SIZE           0x60
+#define OPTEED_C_RT_CTX_ENTRIES                (OPTEED_C_RT_CTX_SIZE >> DWORD_SHIFT)
+
+#ifndef __ASSEMBLY__
+
+#include <cassert.h>
+#include <stdint.h>
+
+typedef uint32_t optee_vector_isn_t;
+
+typedef struct optee_vectors {
+       optee_vector_isn_t std_smc_entry;
+       optee_vector_isn_t fast_smc_entry;
+       optee_vector_isn_t cpu_on_entry;
+       optee_vector_isn_t cpu_off_entry;
+       optee_vector_isn_t cpu_resume_entry;
+       optee_vector_isn_t cpu_suspend_entry;
+       optee_vector_isn_t fiq_entry;
+       optee_vector_isn_t system_off_entry;
+       optee_vector_isn_t system_reset_entry;
+} optee_vectors_t;
+
+/*
+ * The number of arguments to save during a SMC call for OPTEE.
+ * Currently only x1 and x2 are used by OPTEE.
+ */
+#define OPTEE_NUM_ARGS 0x2
+
+/* AArch64 callee saved general purpose register context structure. */
+DEFINE_REG_STRUCT(c_rt_regs, OPTEED_C_RT_CTX_ENTRIES);
+
+/*
+ * Compile time assertion to ensure that both the compiler and linker
+ * have the same double word aligned view of the size of the C runtime
+ * register context.
+ */
+CASSERT(OPTEED_C_RT_CTX_SIZE == sizeof(c_rt_regs_t),   \
+       assert_spd_c_rt_regs_size_mismatch);
+
+/*******************************************************************************
+ * Structure which helps the OPTEED to maintain the per-cpu state of OPTEE.
+ * 'state'          - collection of flags to track OPTEE state e.g. on/off
+ * 'mpidr'          - mpidr to associate a context with a cpu
+ * 'c_rt_ctx'       - stack address to restore C runtime context from after
+ *                    returning from a synchronous entry into OPTEE.
+ * 'cpu_ctx'        - space to maintain OPTEE architectural state
+ ******************************************************************************/
+typedef struct optee_context {
+       uint32_t state;
+       uint64_t mpidr;
+       uint64_t c_rt_ctx;
+       cpu_context_t cpu_ctx;
+} optee_context_t;
+
+/* OPTEED power management handlers */
+extern const spd_pm_ops_t opteed_pm;
+
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+struct optee_vectors;
+
+/*******************************************************************************
+ * Function & Data prototypes
+ ******************************************************************************/
+uint64_t opteed_enter_sp(uint64_t *c_rt_ctx);
+void __dead2 opteed_exit_sp(uint64_t c_rt_ctx, uint64_t ret);
+uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx);
+void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret);
+void opteed_init_optee_ep_state(struct entry_point_info *optee_ep,
+                               uint32_t rw, uint64_t pc,
+                               uint64_t paged_part, uint64_t mem_limit,
+                               optee_context_t *optee_ctx);
+
+extern optee_context_t opteed_sp_context[OPTEED_CORE_COUNT];
+extern uint32_t opteed_rw;
+extern struct optee_vectors *optee_vectors;
+#endif /*__ASSEMBLY__*/
+
+#endif /* __OPTEED_PRIVATE_H__ */
diff --git a/services/spd/opteed/teesmc_opteed.h b/services/spd/opteed/teesmc_opteed.h
new file mode 100644 (file)
index 0000000..7968d1f
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/* Copyright (c) 2014, Linaro Limited. All rights reserved. */
+
+#ifndef TEESMC_OPTEED_H
+#define TEESMC_OPTEED_H
+
+/*
+ * This file specify SMC function IDs used when returning from TEE to the
+ * secure monitor.
+ *
+ * All SMC Function IDs indicates SMC32 Calling Convention but will carry
+ * full 64 bit values in the argument registers if invoked from Aarch64
+ * mode. This violates the SMC Calling Convention, but since this
+ * convention only coveres API towards Normwal World it's something that
+ * only concerns the OP-TEE Dispatcher in ARM Trusted Firmware and OP-TEE
+ * OS at Secure EL1.
+ */
+
+/*
+ * Issued when returning from initial entry.
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_ENTRY_DONE
+ * r1/x1       Pointer to entry vector
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE         0
+#define TEESMC_OPTEED_RETURN_ENTRY_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE)
+
+
+
+/*
+ * Issued when returning from "cpu_on" vector
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_ON_DONE
+ * r1/x1       0 on success and anything else to indicate error condition
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_ON_DONE            1
+#define TEESMC_OPTEED_RETURN_ON_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ON_DONE)
+
+/*
+ * Issued when returning from "cpu_off" vector
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_OFF_DONE
+ * r1/x1       0 on success and anything else to indicate error condition
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE           2
+#define TEESMC_OPTEED_RETURN_OFF_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE)
+
+/*
+ * Issued when returning from "cpu_suspend" vector
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_SUSPEND_DONE
+ * r1/x1       0 on success and anything else to indicate error condition
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE       3
+#define TEESMC_OPTEED_RETURN_SUSPEND_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE)
+
+/*
+ * Issued when returning from "cpu_resume" vector
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_RESUME_DONE
+ * r1/x1       0 on success and anything else to indicate error condition
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE                4
+#define TEESMC_OPTEED_RETURN_RESUME_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE)
+
+/*
+ * Issued when returning from "std_smc" or "fast_smc" vector
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_CALL_DONE
+ * r1-4/x1-4   Return value 0-3 which will passed to normal world in
+ *             r0-3/x0-3
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE          5
+#define TEESMC_OPTEED_RETURN_CALL_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE)
+
+/*
+ * Issued when returning from "fiq" vector
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_FIQ_DONE
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE           6
+#define TEESMC_OPTEED_RETURN_FIQ_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE)
+
+/*
+ * Issued when returning from "system_off" vector
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE    7
+#define TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE)
+
+/*
+ * Issued when returning from "system_reset" vector
+ *
+ * Register usage:
+ * r0/x0       SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE
+ */
+#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE  8
+#define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \
+       TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE)
+
+#endif /*TEESMC_OPTEED_H*/
diff --git a/services/spd/opteed/teesmc_opteed_macros.h b/services/spd/opteed/teesmc_opteed_macros.h
new file mode 100644 (file)
index 0000000..2453c9a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __TEESMC_OPTEED_MACROS_H__
+#define __TEESMC_OPTEED_MACROS_H__
+
+#include <runtime_svc.h>
+
+#define TEESMC_OPTEED_RV(func_num) \
+               ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+                ((SMC_32) << FUNCID_CC_SHIFT) | \
+                (62 << FUNCID_OEN_SHIFT) | \
+                ((func_num) & FUNCID_NUM_MASK))
+
+#endif /*__TEESMC_OPTEED_MACROS_H__*/
diff --git a/services/spd/tspd/tspd.mk b/services/spd/tspd/tspd.mk
new file mode 100644 (file)
index 0000000..139c7d7
--- /dev/null
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2013-2014, 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.
+#
+
+TSPD_DIR               :=      services/spd/tspd
+SPD_INCLUDES           :=      -Iinclude/bl32/tsp
+
+SPD_SOURCES            :=      services/spd/tspd/tspd_common.c         \
+                               services/spd/tspd/tspd_helpers.S        \
+                               services/spd/tspd/tspd_main.c           \
+                               services/spd/tspd/tspd_pm.c
+
+# This dispatcher is paired with a Test Secure Payload source and we intend to
+# build the Test Secure Payload along with this dispatcher.
+#
+# In cases where an associated Secure Payload lies outside this build
+# system/source tree, the the dispatcher Makefile can either invoke an external
+# build command or assume it pre-built
+
+BL32_ROOT              :=      bl32/tsp
+
+# Include SP's Makefile. The assumption is that the TSP's build system is
+# compatible with that of Trusted Firmware, and it'll add and populate necessary
+# build targets and variables
+include ${BL32_ROOT}/tsp.mk
+
+# Let the top-level Makefile know that we intend to build the SP from source
+NEED_BL32              :=      yes
+
+# Flag used to enable routing of non-secure interrupts to EL3 when they are
+# generated while the code is executing in S-EL1/0.
+TSPD_ROUTE_IRQ_TO_EL3  :=      0
+
+$(eval $(call assert_boolean,TSPD_ROUTE_IRQ_TO_EL3))
+$(eval $(call add_define,TSPD_ROUTE_IRQ_TO_EL3))
diff --git a/services/spd/tspd/tspd_common.c b/services/spd/tspd/tspd_common.c
new file mode 100644 (file)
index 0000000..322413c
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <context_mgmt.h>
+#include <string.h>
+#include "tspd_private.h"
+
+/*******************************************************************************
+ * Given a secure payload entrypoint info pointer, entry point PC, register
+ * width, cpu id & pointer to a context data structure, this function will
+ * initialize tsp context and entry point info for the secure payload
+ ******************************************************************************/
+void tspd_init_tsp_ep_state(struct entry_point_info *tsp_entry_point,
+                               uint32_t rw,
+                               uint64_t pc,
+                               tsp_context_t *tsp_ctx)
+{
+       uint32_t ep_attr;
+
+       /* Passing a NULL context is a critical programming error */
+       assert(tsp_ctx);
+       assert(tsp_entry_point);
+       assert(pc);
+
+       /*
+        * We support AArch64 TSP for now.
+        * TODO: Add support for AArch32 TSP
+        */
+       assert(rw == TSP_AARCH64);
+
+       /* Associate this context with the cpu specified */
+       tsp_ctx->mpidr = read_mpidr_el1();
+       tsp_ctx->state = 0;
+       set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
+       clr_std_smc_active_flag(tsp_ctx->state);
+
+       cm_set_context(&tsp_ctx->cpu_ctx, SECURE);
+
+       /* initialise an entrypoint to set up the CPU context */
+       ep_attr = SECURE | EP_ST_ENABLE;
+       if (read_sctlr_el3() & SCTLR_EE_BIT)
+               ep_attr |= EP_EE_BIG;
+       SET_PARAM_HEAD(tsp_entry_point, PARAM_EP, VERSION_1, ep_attr);
+
+       tsp_entry_point->pc = pc;
+       tsp_entry_point->spsr = SPSR_64(MODE_EL1,
+                                       MODE_SP_ELX,
+                                       DISABLE_ALL_EXCEPTIONS);
+       memset(&tsp_entry_point->args, 0, sizeof(tsp_entry_point->args));
+}
+
+/*******************************************************************************
+ * This function takes an SP context pointer and:
+ * 1. Applies the S-EL1 system register context from tsp_ctx->cpu_ctx.
+ * 2. Saves the current C runtime state (callee saved registers) on the stack
+ *    frame and saves a reference to this state.
+ * 3. Calls el3_exit() so that the EL3 system and general purpose registers
+ *    from the tsp_ctx->cpu_ctx are used to enter the secure payload image.
+ ******************************************************************************/
+uint64_t tspd_synchronous_sp_entry(tsp_context_t *tsp_ctx)
+{
+       uint64_t rc;
+
+       assert(tsp_ctx != NULL);
+       assert(tsp_ctx->c_rt_ctx == 0);
+
+       /* Apply the Secure EL1 system register context and switch to it */
+       assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx);
+       cm_el1_sysregs_context_restore(SECURE);
+       cm_set_next_eret_context(SECURE);
+
+       rc = tspd_enter_sp(&tsp_ctx->c_rt_ctx);
+#if DEBUG
+       tsp_ctx->c_rt_ctx = 0;
+#endif
+
+       return rc;
+}
+
+
+/*******************************************************************************
+ * This function takes an SP context pointer and:
+ * 1. Saves the S-EL1 system register context tp tsp_ctx->cpu_ctx.
+ * 2. Restores the current C runtime state (callee saved registers) from the
+ *    stack frame using the reference to this state saved in tspd_enter_sp().
+ * 3. It does not need to save any general purpose or EL3 system register state
+ *    as the generic smc entry routine should have saved those.
+ ******************************************************************************/
+void tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret)
+{
+       assert(tsp_ctx != NULL);
+       /* Save the Secure EL1 system register context */
+       assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx);
+       cm_el1_sysregs_context_save(SECURE);
+
+       assert(tsp_ctx->c_rt_ctx != 0);
+       tspd_exit_sp(tsp_ctx->c_rt_ctx, ret);
+
+       /* Should never reach here */
+       assert(0);
+}
diff --git a/services/spd/tspd/tspd_helpers.S b/services/spd/tspd/tspd_helpers.S
new file mode 100644 (file)
index 0000000..dd3b07b
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm_macros.S>
+#include "tspd_private.h"
+
+       .global tspd_enter_sp
+       /* ---------------------------------------------
+        * This function is called with SP_EL0 as stack.
+        * Here we stash our EL3 callee-saved registers
+        * on to the stack as a part of saving the C
+        * runtime and enter the secure payload.
+        * 'x0' contains a pointer to the memory where
+        * the address of the C runtime context is to be
+        * saved.
+        * ---------------------------------------------
+        */
+func tspd_enter_sp
+       /* Make space for the registers that we're going to save */
+       mov     x3, sp
+       str     x3, [x0, #0]
+       sub     sp, sp, #TSPD_C_RT_CTX_SIZE
+
+       /* Save callee-saved registers on to the stack */
+       stp     x19, x20, [sp, #TSPD_C_RT_CTX_X19]
+       stp     x21, x22, [sp, #TSPD_C_RT_CTX_X21]
+       stp     x23, x24, [sp, #TSPD_C_RT_CTX_X23]
+       stp     x25, x26, [sp, #TSPD_C_RT_CTX_X25]
+       stp     x27, x28, [sp, #TSPD_C_RT_CTX_X27]
+       stp     x29, x30, [sp, #TSPD_C_RT_CTX_X29]
+
+       /* ---------------------------------------------
+        * Everything is setup now. el3_exit() will
+        * use the secure context to restore to the
+        * general purpose and EL3 system registers to
+        * ERET into the secure payload.
+        * ---------------------------------------------
+        */
+       b       el3_exit
+
+       /* ---------------------------------------------
+        * This function is called 'x0' pointing to a C
+        * runtime context saved in tspd_enter_sp().  It
+        * restores the saved registers and jumps to
+        * that runtime with 'x0' as the new sp. This
+        * destroys the C runtime context that had been
+        * built on the stack below the saved context by
+        * the caller. Later the second parameter 'x1'
+        * is passed as return value to the caller
+        * ---------------------------------------------
+        */
+       .global tspd_exit_sp
+func tspd_exit_sp
+       /* Restore the previous stack */
+       mov     sp, x0
+
+       /* Restore callee-saved registers on to the stack */
+       ldp     x19, x20, [x0, #(TSPD_C_RT_CTX_X19 - TSPD_C_RT_CTX_SIZE)]
+       ldp     x21, x22, [x0, #(TSPD_C_RT_CTX_X21 - TSPD_C_RT_CTX_SIZE)]
+       ldp     x23, x24, [x0, #(TSPD_C_RT_CTX_X23 - TSPD_C_RT_CTX_SIZE)]
+       ldp     x25, x26, [x0, #(TSPD_C_RT_CTX_X25 - TSPD_C_RT_CTX_SIZE)]
+       ldp     x27, x28, [x0, #(TSPD_C_RT_CTX_X27 - TSPD_C_RT_CTX_SIZE)]
+       ldp     x29, x30, [x0, #(TSPD_C_RT_CTX_X29 - TSPD_C_RT_CTX_SIZE)]
+
+       /* ---------------------------------------------
+        * This should take us back to the instruction
+        * after the call to the last tspd_enter_sp().
+        * Place the second parameter to x0 so that the
+        * caller will see it as a return value from the
+        * original entry call
+        * ---------------------------------------------
+        */
+       mov     x0, x1
+       ret
diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
new file mode 100644 (file)
index 0000000..ee17483
--- /dev/null
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+
+/*******************************************************************************
+ * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a
+ * plug-in component to the Secure Monitor, registered as a runtime service. The
+ * SPD is expected to be a functional extension of the Secure Payload (SP) that
+ * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting
+ * the Trusted OS/Applications range to the dispatcher. The SPD will either
+ * handle the request locally or delegate it to the Secure Payload. It is also
+ * responsible for initialising and maintaining communication with the SP.
+ ******************************************************************************/
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <errno.h>
+#include <platform.h>
+#include <runtime_svc.h>
+#include <stddef.h>
+#include <string.h>
+#include <tsp.h>
+#include <uuid.h>
+#include "tspd_private.h"
+
+/*******************************************************************************
+ * Address of the entrypoint vector table in the Secure Payload. It is
+ * initialised once on the primary core after a cold boot.
+ ******************************************************************************/
+tsp_vectors_t *tsp_vectors;
+
+/*******************************************************************************
+ * Array to keep track of per-cpu Secure Payload state
+ ******************************************************************************/
+tsp_context_t tspd_sp_context[TSPD_CORE_COUNT];
+
+
+/* TSP UID */
+DEFINE_SVC_UUID(tsp_uuid,
+               0x5b3056a0, 0x3291, 0x427b, 0x98, 0x11,
+               0x71, 0x68, 0xca, 0x50, 0xf3, 0xfa);
+
+int32_t tspd_init(void);
+
+uint64_t tspd_handle_sp_preemption(void *handle)
+{
+       cpu_context_t *ns_cpu_context;
+       assert(handle == cm_get_context(SECURE));
+       cm_el1_sysregs_context_save(SECURE);
+       /* Get a reference to the non-secure context */
+       ns_cpu_context = cm_get_context(NON_SECURE);
+       assert(ns_cpu_context);
+
+       /*
+        * Restore non-secure state. The secure system
+        * register context will be saved when required.
+        */
+       cm_el1_sysregs_context_restore(NON_SECURE);
+       cm_set_next_eret_context(NON_SECURE);
+
+       SMC_RET1(ns_cpu_context, SMC_PREEMPTED);
+}
+/*******************************************************************************
+ * This function is the handler registered for S-EL1 interrupts by the TSPD. It
+ * validates the interrupt and upon success arranges entry into the TSP at
+ * 'tsp_fiq_entry()' for handling the interrupt.
+ ******************************************************************************/
+static uint64_t tspd_sel1_interrupt_handler(uint32_t id,
+                                           uint32_t flags,
+                                           void *handle,
+                                           void *cookie)
+{
+       uint32_t linear_id;
+       uint64_t mpidr;
+       tsp_context_t *tsp_ctx;
+
+       /* Check the security state when the exception was generated */
+       assert(get_interrupt_src_ss(flags) == NON_SECURE);
+
+#if IMF_READ_INTERRUPT_ID
+       /* Check the security status of the interrupt */
+       assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_S_EL1);
+#endif
+
+       /* Sanity check the pointer to this cpu's context */
+       mpidr = read_mpidr();
+       assert(handle == cm_get_context(NON_SECURE));
+
+       /* Save the non-secure context before entering the TSP */
+       cm_el1_sysregs_context_save(NON_SECURE);
+
+       /* Get a reference to this cpu's TSP context */
+       linear_id = platform_get_core_pos(mpidr);
+       tsp_ctx = &tspd_sp_context[linear_id];
+       assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE));
+
+       /*
+        * Determine if the TSP was previously preempted. Its last known
+        * context has to be preserved in this case.
+        * The TSP should return control to the TSPD after handling this
+        * FIQ. Preserve essential EL3 context to allow entry into the
+        * TSP at the FIQ entry point using the 'cpu_context' structure.
+        * There is no need to save the secure system register context
+        * since the TSP is supposed to preserve it during S-EL1 interrupt
+        * handling.
+        */
+       if (get_std_smc_active_flag(tsp_ctx->state)) {
+               tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
+                                                     CTX_SPSR_EL3);
+               tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
+                                                    CTX_ELR_EL3);
+#if TSPD_ROUTE_IRQ_TO_EL3
+               /*Need to save the previously interrupted secure context */
+               memcpy(&tsp_ctx->sp_ctx, &tsp_ctx->cpu_ctx, TSPD_SP_CTX_SIZE);
+#endif
+       }
+
+       cm_el1_sysregs_context_restore(SECURE);
+       cm_set_elr_spsr_el3(SECURE, (uint64_t) &tsp_vectors->fiq_entry,
+                   SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS));
+
+       cm_set_next_eret_context(SECURE);
+
+       /*
+        * Tell the TSP that it has to handle an FIQ synchronously. Also the
+        * instruction in normal world where the interrupt was generated is
+        * passed for debugging purposes. It is safe to retrieve this address
+        * from ELR_EL3 as the secure context will not take effect until
+        * el3_exit().
+        */
+       SMC_RET2(&tsp_ctx->cpu_ctx, TSP_HANDLE_FIQ_AND_RETURN, read_elr_el3());
+}
+
+#if TSPD_ROUTE_IRQ_TO_EL3
+/*******************************************************************************
+ * This function is the handler registered for S-EL1 interrupts by the TSPD. It
+ * validates the interrupt and upon success arranges entry into the TSP at
+ * 'tsp_fiq_entry()' for handling the interrupt.
+ ******************************************************************************/
+static uint64_t tspd_ns_interrupt_handler(uint32_t id,
+                                           uint32_t flags,
+                                           void *handle,
+                                           void *cookie)
+{
+       /* Check the security state when the exception was generated */
+       assert(get_interrupt_src_ss(flags) == SECURE);
+
+#if IMF_READ_INTERRUPT_ID
+       /* Check the security status of the interrupt */
+       assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_NS);
+#endif
+       /*
+        * Disable the routing of NS interrupts from secure world to EL3 while
+        * interrupted on this core.
+        */
+       disable_intr_rm_local(INTR_TYPE_NS, SECURE);
+
+       return tspd_handle_sp_preemption(handle);
+}
+#endif
+
+/*******************************************************************************
+ * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type
+ * (aarch32/aarch64) if not already known and initialises the context for entry
+ * into the SP for its initialisation.
+ ******************************************************************************/
+int32_t tspd_setup(void)
+{
+       entry_point_info_t *tsp_ep_info;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id;
+
+       linear_id = platform_get_core_pos(mpidr);
+
+       /*
+        * Get information about the Secure Payload (BL32) image. Its
+        * absence is a critical failure.  TODO: Add support to
+        * conditionally include the SPD service
+        */
+       tsp_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+       if (!tsp_ep_info) {
+               WARN("No TSP provided by BL2 boot loader, Booting device"
+                       " without TSP initialization. SMC`s destined for TSP"
+                       " will return SMC_UNK\n");
+               return 1;
+       }
+
+       /*
+        * If there's no valid entry point for SP, we return a non-zero value
+        * signalling failure initializing the service. We bail out without
+        * registering any handlers
+        */
+       if (!tsp_ep_info->pc)
+               return 1;
+
+       /*
+        * We could inspect the SP image and determine it's execution
+        * state i.e whether AArch32 or AArch64. Assuming it's AArch64
+        * for the time being.
+        */
+       tspd_init_tsp_ep_state(tsp_ep_info,
+                               TSP_AARCH64,
+                               tsp_ep_info->pc,
+                               &tspd_sp_context[linear_id]);
+
+#if TSP_INIT_ASYNC
+       bl31_set_next_image_type(SECURE);
+#else
+       /*
+        * All TSPD initialization done. Now register our init function with
+        * BL31 for deferred invocation
+        */
+       bl31_register_bl32_init(&tspd_init);
+#endif
+       return 0;
+}
+
+/*******************************************************************************
+ * This function passes control to the Secure Payload image (BL32) for the first
+ * time on the primary cpu after a cold boot. It assumes that a valid secure
+ * context has already been created by tspd_setup() which can be directly used.
+ * It also assumes that a valid non-secure context has been initialised by PSCI
+ * so it does not need to save and restore any non-secure state. This function
+ * performs a synchronous entry into the Secure payload. The SP passes control
+ * back to this routine through a SMC.
+ ******************************************************************************/
+int32_t tspd_init(void)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
+       entry_point_info_t *tsp_entry_point;
+       uint64_t rc;
+
+       /*
+        * Get information about the Secure Payload (BL32) image. Its
+        * absence is a critical failure.
+        */
+       tsp_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
+       assert(tsp_entry_point);
+
+       cm_init_context(mpidr, tsp_entry_point);
+
+       /*
+        * Arrange for an entry into the test secure payload. It will be
+        * returned via TSP_ENTRY_DONE case
+        */
+       rc = tspd_synchronous_sp_entry(tsp_ctx);
+       assert(rc != 0);
+
+       return rc;
+}
+
+
+/*******************************************************************************
+ * This function is responsible for handling all SMCs in the Trusted OS/App
+ * range from the non-secure state as defined in the SMC Calling Convention
+ * Document. It is also responsible for communicating with the Secure payload
+ * to delegate work and return results back to the non-secure state. Lastly it
+ * will also return any information that the secure payload needs to do the
+ * work assigned to it.
+ ******************************************************************************/
+uint64_t tspd_smc_handler(uint32_t smc_fid,
+                        uint64_t x1,
+                        uint64_t x2,
+                        uint64_t x3,
+                        uint64_t x4,
+                        void *cookie,
+                        void *handle,
+                        uint64_t flags)
+{
+       cpu_context_t *ns_cpu_context;
+       unsigned long mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr), ns;
+       tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
+       uint64_t rc;
+#if TSP_INIT_ASYNC
+       entry_point_info_t *next_image_info;
+#endif
+
+       /* Determine which security state this SMC originated from */
+       ns = is_caller_non_secure(flags);
+
+       switch (smc_fid) {
+
+       /*
+        * This function ID is used by TSP to indicate that it was
+        * preempted by a normal world IRQ.
+        *
+        */
+       case TSP_PREEMPTED:
+               if (ns)
+                       SMC_RET1(handle, SMC_UNK);
+
+               return tspd_handle_sp_preemption(handle);
+
+       /*
+        * This function ID is used only by the TSP to indicate that it has
+        * finished handling a S-EL1 FIQ interrupt. Execution should resume
+        * in the normal world.
+        */
+       case TSP_HANDLED_S_EL1_FIQ:
+               if (ns)
+                       SMC_RET1(handle, SMC_UNK);
+
+               assert(handle == cm_get_context(SECURE));
+
+               /*
+                * Restore the relevant EL3 state which saved to service
+                * this SMC.
+                */
+               if (get_std_smc_active_flag(tsp_ctx->state)) {
+                       SMC_SET_EL3(&tsp_ctx->cpu_ctx,
+                                   CTX_SPSR_EL3,
+                                   tsp_ctx->saved_spsr_el3);
+                       SMC_SET_EL3(&tsp_ctx->cpu_ctx,
+                                   CTX_ELR_EL3,
+                                   tsp_ctx->saved_elr_el3);
+#if TSPD_ROUTE_IRQ_TO_EL3
+                       /*
+                        * Need to restore the previously interrupted
+                        * secure context.
+                        */
+                       memcpy(&tsp_ctx->cpu_ctx, &tsp_ctx->sp_ctx,
+                               TSPD_SP_CTX_SIZE);
+#endif
+               }
+
+               /* Get a reference to the non-secure context */
+               ns_cpu_context = cm_get_context(NON_SECURE);
+               assert(ns_cpu_context);
+
+               /*
+                * Restore non-secure state. There is no need to save the
+                * secure system register context since the TSP was supposed
+                * to preserve it during S-EL1 interrupt handling.
+                */
+               cm_el1_sysregs_context_restore(NON_SECURE);
+               cm_set_next_eret_context(NON_SECURE);
+
+               SMC_RET0((uint64_t) ns_cpu_context);
+
+
+       /*
+        * This function ID is used only by the TSP to indicate that it was
+        * interrupted due to a EL3 FIQ interrupt. Execution should resume
+        * in the normal world.
+        */
+       case TSP_EL3_FIQ:
+               if (ns)
+                       SMC_RET1(handle, SMC_UNK);
+
+               assert(handle == cm_get_context(SECURE));
+
+               /* Assert that standard SMC execution has been preempted */
+               assert(get_std_smc_active_flag(tsp_ctx->state));
+
+               /* Save the secure system register state */
+               cm_el1_sysregs_context_save(SECURE);
+
+               /* Get a reference to the non-secure context */
+               ns_cpu_context = cm_get_context(NON_SECURE);
+               assert(ns_cpu_context);
+
+               /* Restore non-secure state */
+               cm_el1_sysregs_context_restore(NON_SECURE);
+               cm_set_next_eret_context(NON_SECURE);
+
+               SMC_RET1(ns_cpu_context, TSP_EL3_FIQ);
+
+
+       /*
+        * This function ID is used only by the SP to indicate it has
+        * finished initialising itself after a cold boot
+        */
+       case TSP_ENTRY_DONE:
+               if (ns)
+                       SMC_RET1(handle, SMC_UNK);
+
+               /*
+                * Stash the SP entry points information. This is done
+                * only once on the primary cpu
+                */
+               assert(tsp_vectors == NULL);
+               tsp_vectors = (tsp_vectors_t *) x1;
+
+               if (tsp_vectors) {
+                       set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
+
+                       /*
+                        * TSP has been successfully initialized. Register power
+                        * managemnt hooks with PSCI
+                        */
+                       psci_register_spd_pm_hook(&tspd_pm);
+
+                       /*
+                        * Register an interrupt handler for S-EL1 interrupts
+                        * when generated during code executing in the
+                        * non-secure state.
+                        */
+                       flags = 0;
+                       set_interrupt_rm_flag(flags, NON_SECURE);
+                       rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+                                               tspd_sel1_interrupt_handler,
+                                               flags);
+                       if (rc)
+                               panic();
+
+#if TSPD_ROUTE_IRQ_TO_EL3
+                       /*
+                        * Register an interrupt handler for NS interrupts when
+                        * generated during code executing in secure state are
+                        * routed to EL3.
+                        */
+                       flags = 0;
+                       set_interrupt_rm_flag(flags, SECURE);
+
+                       rc = register_interrupt_type_handler(INTR_TYPE_NS,
+                                               tspd_ns_interrupt_handler,
+                                               flags);
+                       if (rc)
+                               panic();
+
+                       /*
+                        * Disable the interrupt NS locally since it will be enabled globally
+                        * within cm_init_context.
+                        */
+                       disable_intr_rm_local(INTR_TYPE_NS, SECURE);
+#endif
+               }
+
+
+#if TSP_INIT_ASYNC
+               /* Save the Secure EL1 system register context */
+               assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx);
+               cm_el1_sysregs_context_save(SECURE);
+
+               /* Program EL3 registers to enable entry into the next EL */
+               next_image_info = bl31_plat_get_next_image_ep_info(NON_SECURE);
+               assert(next_image_info);
+               assert(NON_SECURE ==
+                               GET_SECURITY_STATE(next_image_info->h.attr));
+
+               cm_init_context(read_mpidr_el1(), next_image_info);
+               cm_prepare_el3_exit(NON_SECURE);
+               SMC_RET0(cm_get_context(NON_SECURE));
+#else
+               /*
+                * SP reports completion. The SPD must have initiated
+                * the original request through a synchronous entry
+                * into the SP. Jump back to the original C runtime
+                * context.
+                */
+               tspd_synchronous_sp_exit(tsp_ctx, x1);
+#endif
+
+       /*
+        * These function IDs is used only by the SP to indicate it has
+        * finished:
+        * 1. turning itself on in response to an earlier psci
+        *    cpu_on request
+        * 2. resuming itself after an earlier psci cpu_suspend
+        *    request.
+        */
+       case TSP_ON_DONE:
+       case TSP_RESUME_DONE:
+
+       /*
+        * These function IDs is used only by the SP to indicate it has
+        * finished:
+        * 1. suspending itself after an earlier psci cpu_suspend
+        *    request.
+        * 2. turning itself off in response to an earlier psci
+        *    cpu_off request.
+        */
+       case TSP_OFF_DONE:
+       case TSP_SUSPEND_DONE:
+       case TSP_SYSTEM_OFF_DONE:
+       case TSP_SYSTEM_RESET_DONE:
+               if (ns)
+                       SMC_RET1(handle, SMC_UNK);
+
+               /*
+                * SP reports completion. The SPD must have initiated the
+                * original request through a synchronous entry into the SP.
+                * Jump back to the original C runtime context, and pass x1 as
+                * return value to the caller
+                */
+               tspd_synchronous_sp_exit(tsp_ctx, x1);
+
+               /*
+                * Request from non-secure client to perform an
+                * arithmetic operation or response from secure
+                * payload to an earlier request.
+                */
+       case TSP_FAST_FID(TSP_ADD):
+       case TSP_FAST_FID(TSP_SUB):
+       case TSP_FAST_FID(TSP_MUL):
+       case TSP_FAST_FID(TSP_DIV):
+
+       case TSP_STD_FID(TSP_ADD):
+       case TSP_STD_FID(TSP_SUB):
+       case TSP_STD_FID(TSP_MUL):
+       case TSP_STD_FID(TSP_DIV):
+               if (ns) {
+                       /*
+                        * This is a fresh request from the non-secure client.
+                        * The parameters are in x1 and x2. Figure out which
+                        * registers need to be preserved, save the non-secure
+                        * state and send the request to the secure payload.
+                        */
+                       assert(handle == cm_get_context(NON_SECURE));
+
+                       /* Check if we are already preempted */
+                       if (get_std_smc_active_flag(tsp_ctx->state))
+                               SMC_RET1(handle, SMC_UNK);
+
+                       cm_el1_sysregs_context_save(NON_SECURE);
+
+                       /* Save x1 and x2 for use by TSP_GET_ARGS call below */
+                       store_tsp_args(tsp_ctx, x1, x2);
+
+                       /*
+                        * We are done stashing the non-secure context. Ask the
+                        * secure payload to do the work now.
+                        */
+
+                       /*
+                        * Verify if there is a valid context to use, copy the
+                        * operation type and parameters to the secure context
+                        * and jump to the fast smc entry point in the secure
+                        * payload. Entry into S-EL1 will take place upon exit
+                        * from this function.
+                        */
+                       assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE));
+
+                       /* Set appropriate entry for SMC.
+                        * We expect the TSP to manage the PSTATE.I and PSTATE.F
+                        * flags as appropriate.
+                        */
+                       if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) {
+                               cm_set_elr_el3(SECURE, (uint64_t)
+                                               &tsp_vectors->fast_smc_entry);
+                       } else {
+                               set_std_smc_active_flag(tsp_ctx->state);
+                               cm_set_elr_el3(SECURE, (uint64_t)
+                                               &tsp_vectors->std_smc_entry);
+#if TSPD_ROUTE_IRQ_TO_EL3
+                               /*
+                                * Enable the routing of NS interrupts to EL3
+                                * during STD SMC processing on this core.
+                                */
+                               enable_intr_rm_local(INTR_TYPE_NS, SECURE);
+#endif
+                       }
+
+                       cm_el1_sysregs_context_restore(SECURE);
+                       cm_set_next_eret_context(SECURE);
+                       SMC_RET3(&tsp_ctx->cpu_ctx, smc_fid, x1, x2);
+               } else {
+                       /*
+                        * This is the result from the secure client of an
+                        * earlier request. The results are in x1-x3. Copy it
+                        * into the non-secure context, save the secure state
+                        * and return to the non-secure state.
+                        */
+                       assert(handle == cm_get_context(SECURE));
+                       cm_el1_sysregs_context_save(SECURE);
+
+                       /* Get a reference to the non-secure context */
+                       ns_cpu_context = cm_get_context(NON_SECURE);
+                       assert(ns_cpu_context);
+
+                       /* Restore non-secure state */
+                       cm_el1_sysregs_context_restore(NON_SECURE);
+                       cm_set_next_eret_context(NON_SECURE);
+                       if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_STD) {
+                               clr_std_smc_active_flag(tsp_ctx->state);
+#if TSPD_ROUTE_IRQ_TO_EL3
+                               /*
+                                * Disable the routing of NS interrupts to EL3
+                                * after STD SMC processing is finished on this
+                                * core.
+                                */
+                               disable_intr_rm_local(INTR_TYPE_NS, SECURE);
+#endif
+                       }
+
+                       SMC_RET3(ns_cpu_context, x1, x2, x3);
+               }
+
+               break;
+
+               /*
+                * Request from non secure world to resume the preempted
+                * Standard SMC call.
+                */
+       case TSP_FID_RESUME:
+               /* RESUME should be invoked only by normal world */
+               if (!ns) {
+                       assert(0);
+                       break;
+               }
+
+               /*
+                * This is a resume request from the non-secure client.
+                * save the non-secure state and send the request to
+                * the secure payload.
+                */
+               assert(handle == cm_get_context(NON_SECURE));
+
+               /* Check if we are already preempted before resume */
+               if (!get_std_smc_active_flag(tsp_ctx->state))
+                       SMC_RET1(handle, SMC_UNK);
+
+               cm_el1_sysregs_context_save(NON_SECURE);
+
+               /*
+                * We are done stashing the non-secure context. Ask the
+                * secure payload to do the work now.
+                */
+#if TSPD_ROUTE_IRQ_TO_EL3
+               /*
+                * Enable the routing of NS interrupts to EL3 during resumption
+                * of STD SMC call on this core.
+                */
+               enable_intr_rm_local(INTR_TYPE_NS, SECURE);
+#endif
+
+
+
+               /* We just need to return to the preempted point in
+                * TSP and the execution will resume as normal.
+                */
+               cm_el1_sysregs_context_restore(SECURE);
+               cm_set_next_eret_context(SECURE);
+               SMC_RET0(&tsp_ctx->cpu_ctx);
+
+               /*
+                * This is a request from the secure payload for more arguments
+                * for an ongoing arithmetic operation requested by the
+                * non-secure world. Simply return the arguments from the non-
+                * secure client in the original call.
+                */
+       case TSP_GET_ARGS:
+               if (ns)
+                       SMC_RET1(handle, SMC_UNK);
+
+               get_tsp_args(tsp_ctx, x1, x2);
+               SMC_RET2(handle, x1, x2);
+
+       case TOS_CALL_COUNT:
+               /*
+                * Return the number of service function IDs implemented to
+                * provide service to non-secure
+                */
+               SMC_RET1(handle, TSP_NUM_FID);
+
+       case TOS_UID:
+               /* Return TSP UID to the caller */
+               SMC_UUID_RET(handle, tsp_uuid);
+
+       case TOS_CALL_VERSION:
+               /* Return the version of current implementation */
+               SMC_RET2(handle, TSP_VERSION_MAJOR, TSP_VERSION_MINOR);
+
+       default:
+               break;
+       }
+
+       SMC_RET1(handle, SMC_UNK);
+}
+
+/* Define a SPD runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+       tspd_fast,
+
+       OEN_TOS_START,
+       OEN_TOS_END,
+       SMC_TYPE_FAST,
+       tspd_setup,
+       tspd_smc_handler
+);
+
+/* Define a SPD runtime service descriptor for standard SMC calls */
+DECLARE_RT_SVC(
+       tspd_std,
+
+       OEN_TOS_START,
+       OEN_TOS_END,
+       SMC_TYPE_STD,
+       NULL,
+       tspd_smc_handler
+);
diff --git a/services/spd/tspd/tspd_pm.c b/services/spd/tspd/tspd_pm.c
new file mode 100644 (file)
index 0000000..009ff5f
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <platform.h>
+#include <tsp.h>
+#include "tspd_private.h"
+
+/*******************************************************************************
+ * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
+ * needed. Nothing at the moment.
+ ******************************************************************************/
+static void tspd_cpu_on_handler(uint64_t target_cpu)
+{
+}
+
+/*******************************************************************************
+ * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
+ * needed
+ ******************************************************************************/
+static int32_t tspd_cpu_off_handler(uint64_t unused)
+{
+       int32_t rc = 0;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
+
+       assert(tsp_vectors);
+       assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
+
+       /* Program the entry point and enter the TSP */
+       cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry);
+       rc = tspd_synchronous_sp_entry(tsp_ctx);
+
+       /*
+        * Read the response from the TSP. A non-zero return means that
+        * something went wrong while communicating with the TSP.
+        */
+       if (rc != 0)
+               panic();
+
+       /*
+        * Reset TSP's context for a fresh start when this cpu is turned on
+        * subsequently.
+        */
+       set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
+
+        return 0;
+}
+
+/*******************************************************************************
+ * This cpu is being suspended. S-EL1 state must have been saved in the
+ * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
+ ******************************************************************************/
+static void tspd_cpu_suspend_handler(uint64_t unused)
+{
+       int32_t rc = 0;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
+
+       assert(tsp_vectors);
+       assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
+
+       /* Program the entry point and enter the TSP */
+       cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry);
+       rc = tspd_synchronous_sp_entry(tsp_ctx);
+
+       /*
+        * Read the response from the TSP. A non-zero return means that
+        * something went wrong while communicating with the TSP.
+        */
+       if (rc != 0)
+               panic();
+
+       /* Update its context to reflect the state the TSP is in */
+       set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_SUSPEND);
+}
+
+/*******************************************************************************
+ * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
+ * before passing control back to the Secure Monitor. Entry in S-El1 is done
+ * after initialising minimal architectural state that guarantees safe
+ * execution.
+ ******************************************************************************/
+static void tspd_cpu_on_finish_handler(uint64_t unused)
+{
+       int32_t rc = 0;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
+       entry_point_info_t tsp_on_entrypoint;
+
+       assert(tsp_vectors);
+       assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF);
+
+       tspd_init_tsp_ep_state(&tsp_on_entrypoint,
+                               TSP_AARCH64,
+                               (uint64_t) &tsp_vectors->cpu_on_entry,
+                               tsp_ctx);
+
+       /* Initialise this cpu's secure context */
+       cm_init_context(mpidr, &tsp_on_entrypoint);
+
+#if TSPD_ROUTE_IRQ_TO_EL3
+       /*
+        * Disable the NS interrupt locally since it will be enabled globally
+        * within cm_init_context.
+        */
+       disable_intr_rm_local(INTR_TYPE_NS, SECURE);
+#endif
+
+       /* Enter the TSP */
+       rc = tspd_synchronous_sp_entry(tsp_ctx);
+
+       /*
+        * Read the response from the TSP. A non-zero return means that
+        * something went wrong while communicating with the SP.
+        */
+       if (rc != 0)
+               panic();
+
+       /* Update its context to reflect the state the SP is in */
+       set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
+}
+
+/*******************************************************************************
+ * This cpu has resumed from suspend. The SPD saved the TSP context when it
+ * completed the preceding suspend call. Use that context to program an entry
+ * into the TSP to allow it to do any remaining book keeping
+ ******************************************************************************/
+static void tspd_cpu_suspend_finish_handler(uint64_t suspend_level)
+{
+       int32_t rc = 0;
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
+
+       assert(tsp_vectors);
+       assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_SUSPEND);
+
+       /* Program the entry point, suspend_level and enter the SP */
+       write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
+                     CTX_GPREG_X0,
+                     suspend_level);
+       cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_resume_entry);
+       rc = tspd_synchronous_sp_entry(tsp_ctx);
+
+       /*
+        * Read the response from the TSP. A non-zero return means that
+        * something went wrong while communicating with the TSP.
+        */
+       if (rc != 0)
+               panic();
+
+       /* Update its context to reflect the state the SP is in */
+       set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
+}
+
+/*******************************************************************************
+ * Return the type of TSP the TSPD is dealing with. Report the current resident
+ * cpu (mpidr format) if it is a UP/UP migratable TSP.
+ ******************************************************************************/
+static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
+{
+       return TSP_MIGRATE_INFO;
+}
+
+/*******************************************************************************
+ * System is about to be switched off. Allow the TSPD/TSP to perform
+ * any actions needed.
+ ******************************************************************************/
+static void tspd_system_off(void)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
+
+       assert(tsp_vectors);
+       assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
+
+       /* Program the entry point */
+       cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry);
+
+       /* Enter the TSP. We do not care about the return value because we
+        * must continue the shutdown anyway */
+       tspd_synchronous_sp_entry(tsp_ctx);
+}
+
+/*******************************************************************************
+ * System is about to be reset. Allow the TSPD/TSP to perform
+ * any actions needed.
+ ******************************************************************************/
+static void tspd_system_reset(void)
+{
+       uint64_t mpidr = read_mpidr();
+       uint32_t linear_id = platform_get_core_pos(mpidr);
+       tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
+
+       assert(tsp_vectors);
+       assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
+
+       /* Program the entry point */
+       cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry);
+
+       /* Enter the TSP. We do not care about the return value because we
+        * must continue the reset anyway */
+       tspd_synchronous_sp_entry(tsp_ctx);
+}
+
+/*******************************************************************************
+ * Structure populated by the TSP Dispatcher to be given a chance to perform any
+ * TSP bookkeeping before PSCI executes a power mgmt.  operation.
+ ******************************************************************************/
+const spd_pm_ops_t tspd_pm = {
+       .svc_on = tspd_cpu_on_handler,
+       .svc_off = tspd_cpu_off_handler,
+       .svc_suspend = tspd_cpu_suspend_handler,
+       .svc_on_finish = tspd_cpu_on_finish_handler,
+       .svc_suspend_finish = tspd_cpu_suspend_finish_handler,
+       .svc_migrate = NULL,
+       .svc_migrate_info = tspd_cpu_migrate_info,
+       .svc_system_off = tspd_system_off,
+       .svc_system_reset = tspd_system_reset
+};
diff --git a/services/spd/tspd/tspd_private.h b/services/spd/tspd/tspd_private.h
new file mode 100644 (file)
index 0000000..5f6fb2b
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TSPD_PRIVATE_H__
+#define __TSPD_PRIVATE_H__
+
+#include <arch.h>
+#include <context.h>
+#include <interrupt_mgmt.h>
+#include <platform_def.h>
+#include <psci.h>
+
+/*******************************************************************************
+ * Secure Payload PM state information e.g. SP is suspended, uninitialised etc
+ * and macros to access the state information in the per-cpu 'state' flags
+ ******************************************************************************/
+#define TSP_PSTATE_OFF         0
+#define TSP_PSTATE_ON          1
+#define TSP_PSTATE_SUSPEND     2
+#define TSP_PSTATE_SHIFT       0
+#define TSP_PSTATE_MASK        0x3
+#define get_tsp_pstate(state)  ((state >> TSP_PSTATE_SHIFT) & TSP_PSTATE_MASK)
+#define clr_tsp_pstate(state)  (state &= ~(TSP_PSTATE_MASK \
+                                           << TSP_PSTATE_SHIFT))
+#define set_tsp_pstate(st, pst)        do {                                           \
+                                       clr_tsp_pstate(st);                    \
+                                       st |= (pst & TSP_PSTATE_MASK) <<       \
+                                               TSP_PSTATE_SHIFT;              \
+                               } while (0);
+
+
+/*
+ * This flag is used by the TSPD to determine if the TSP is servicing a standard
+ * SMC request prior to programming the next entry into the TSP e.g. if TSP
+ * execution is preempted by a non-secure interrupt and handed control to the
+ * normal world. If another request which is distinct from what the TSP was
+ * previously doing arrives, then this flag will be help the TSPD to either
+ * reject the new request or service it while ensuring that the previous context
+ * is not corrupted.
+ */
+#define STD_SMC_ACTIVE_FLAG_SHIFT      2
+#define STD_SMC_ACTIVE_FLAG_MASK       1
+#define get_std_smc_active_flag(state) ((state >> STD_SMC_ACTIVE_FLAG_SHIFT) \
+                                        & STD_SMC_ACTIVE_FLAG_MASK)
+#define set_std_smc_active_flag(state) (state |=                             \
+                                        1 << STD_SMC_ACTIVE_FLAG_SHIFT)
+#define clr_std_smc_active_flag(state) (state &=                             \
+                                        ~(STD_SMC_ACTIVE_FLAG_MASK           \
+                                          << STD_SMC_ACTIVE_FLAG_SHIFT))
+
+/*******************************************************************************
+ * Secure Payload execution state information i.e. aarch32 or aarch64
+ ******************************************************************************/
+#define TSP_AARCH32            MODE_RW_32
+#define TSP_AARCH64            MODE_RW_64
+
+/*******************************************************************************
+ * The SPD should know the type of Secure Payload.
+ ******************************************************************************/
+#define TSP_TYPE_UP            PSCI_TOS_NOT_UP_MIG_CAP
+#define TSP_TYPE_UPM           PSCI_TOS_UP_MIG_CAP
+#define TSP_TYPE_MP            PSCI_TOS_NOT_PRESENT_MP
+
+/*******************************************************************************
+ * Secure Payload migrate type information as known to the SPD. We assume that
+ * the SPD is dealing with an MP Secure Payload.
+ ******************************************************************************/
+#define TSP_MIGRATE_INFO               TSP_TYPE_MP
+
+/*******************************************************************************
+ * Number of cpus that the present on this platform. TODO: Rely on a topology
+ * tree to determine this in the future to avoid assumptions about mpidr
+ * allocation
+ ******************************************************************************/
+#define TSPD_CORE_COUNT                PLATFORM_CORE_COUNT
+
+/*******************************************************************************
+ * Constants that allow assembler code to preserve callee-saved registers of the
+ * C runtime context while performing a security state switch.
+ ******************************************************************************/
+#define TSPD_C_RT_CTX_X19              0x0
+#define TSPD_C_RT_CTX_X20              0x8
+#define TSPD_C_RT_CTX_X21              0x10
+#define TSPD_C_RT_CTX_X22              0x18
+#define TSPD_C_RT_CTX_X23              0x20
+#define TSPD_C_RT_CTX_X24              0x28
+#define TSPD_C_RT_CTX_X25              0x30
+#define TSPD_C_RT_CTX_X26              0x38
+#define TSPD_C_RT_CTX_X27              0x40
+#define TSPD_C_RT_CTX_X28              0x48
+#define TSPD_C_RT_CTX_X29              0x50
+#define TSPD_C_RT_CTX_X30              0x58
+#define TSPD_C_RT_CTX_SIZE             0x60
+#define TSPD_C_RT_CTX_ENTRIES          (TSPD_C_RT_CTX_SIZE >> DWORD_SHIFT)
+
+/*******************************************************************************
+ * Constants that allow assembler code to preserve caller-saved registers of the
+ * SP context while performing a TSP preemption.
+ * Note: These offsets have to match with the offsets for the corresponding
+ * registers in cpu_context as we are using memcpy to copy the values from
+ * cpu_context to sp_ctx.
+ ******************************************************************************/
+#define TSPD_SP_CTX_X0         0x0
+#define TSPD_SP_CTX_X1         0x8
+#define TSPD_SP_CTX_X2         0x10
+#define TSPD_SP_CTX_X3         0x18
+#define TSPD_SP_CTX_X4         0x20
+#define TSPD_SP_CTX_X5         0x28
+#define TSPD_SP_CTX_X6         0x30
+#define TSPD_SP_CTX_X7         0x38
+#define TSPD_SP_CTX_X8         0x40
+#define TSPD_SP_CTX_X9         0x48
+#define TSPD_SP_CTX_X10                0x50
+#define TSPD_SP_CTX_X11                0x58
+#define TSPD_SP_CTX_X12                0x60
+#define TSPD_SP_CTX_X13                0x68
+#define TSPD_SP_CTX_X14                0x70
+#define TSPD_SP_CTX_X15                0x78
+#define TSPD_SP_CTX_X16                0x80
+#define TSPD_SP_CTX_X17                0x88
+#define TSPD_SP_CTX_SIZE       0x90
+#define TSPD_SP_CTX_ENTRIES            (TSPD_SP_CTX_SIZE >> DWORD_SHIFT)
+
+#ifndef __ASSEMBLY__
+
+#include <cassert.h>
+#include <stdint.h>
+
+/*
+ * The number of arguments to save during a SMC call for TSP.
+ * Currently only x1 and x2 are used by TSP.
+ */
+#define TSP_NUM_ARGS   0x2
+
+/* AArch64 callee saved general purpose register context structure. */
+DEFINE_REG_STRUCT(c_rt_regs, TSPD_C_RT_CTX_ENTRIES);
+
+/*
+ * Compile time assertion to ensure that both the compiler and linker
+ * have the same double word aligned view of the size of the C runtime
+ * register context.
+ */
+CASSERT(TSPD_C_RT_CTX_SIZE == sizeof(c_rt_regs_t),     \
+       assert_spd_c_rt_regs_size_mismatch);
+
+/* SEL1 Secure payload (SP) caller saved register context structure. */
+DEFINE_REG_STRUCT(sp_ctx_regs, TSPD_SP_CTX_ENTRIES);
+
+/*
+ * Compile time assertion to ensure that both the compiler and linker
+ * have the same double word aligned view of the size of the C runtime
+ * register context.
+ */
+CASSERT(TSPD_SP_CTX_SIZE == sizeof(sp_ctx_regs_t),     \
+       assert_spd_sp_regs_size_mismatch);
+
+/*******************************************************************************
+ * Structure which helps the SPD to maintain the per-cpu state of the SP.
+ * 'saved_spsr_el3' - temporary copy to allow FIQ handling when the TSP has been
+ *                    preempted.
+ * 'saved_elr_el3'  - temporary copy to allow FIQ handling when the TSP has been
+ *                    preempted.
+ * 'state'          - collection of flags to track SP state e.g. on/off
+ * 'mpidr'          - mpidr to associate a context with a cpu
+ * 'c_rt_ctx'       - stack address to restore C runtime context from after
+ *                    returning from a synchronous entry into the SP.
+ * 'cpu_ctx'        - space to maintain SP architectural state
+ * 'saved_tsp_args' - space to store arguments for TSP arithmetic operations
+ *                    which will queried using the TSP_GET_ARGS SMC by TSP.
+ * 'sp_ctx'         - space to save the SEL1 Secure Payload(SP) caller saved
+ *                    register context after it has been preempted by an EL3
+ *                    routed NS interrupt and when a Secure Interrupt is taken
+ *                    to SP.
+ ******************************************************************************/
+typedef struct tsp_context {
+       uint64_t saved_elr_el3;
+       uint32_t saved_spsr_el3;
+       uint32_t state;
+       uint64_t mpidr;
+       uint64_t c_rt_ctx;
+       cpu_context_t cpu_ctx;
+       uint64_t saved_tsp_args[TSP_NUM_ARGS];
+#if TSPD_ROUTE_IRQ_TO_EL3
+       sp_ctx_regs_t sp_ctx;
+#endif
+} tsp_context_t;
+
+/* Helper macros to store and retrieve tsp args from tsp_context */
+#define store_tsp_args(tsp_ctx, x1, x2)                do {\
+                               tsp_ctx->saved_tsp_args[0] = x1;\
+                               tsp_ctx->saved_tsp_args[1] = x2;\
+                       } while (0)
+
+#define get_tsp_args(tsp_ctx, x1, x2)  do {\
+                               x1 = tsp_ctx->saved_tsp_args[0];\
+                               x2 = tsp_ctx->saved_tsp_args[1];\
+                       } while (0)
+
+/* TSPD power management handlers */
+extern const spd_pm_ops_t tspd_pm;
+
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+struct tsp_vectors;
+
+/*******************************************************************************
+ * Function & Data prototypes
+ ******************************************************************************/
+uint64_t tspd_enter_sp(uint64_t *c_rt_ctx);
+void __dead2 tspd_exit_sp(uint64_t c_rt_ctx, uint64_t ret);
+uint64_t tspd_synchronous_sp_entry(tsp_context_t *tsp_ctx);
+void __dead2 tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret);
+void tspd_init_tsp_ep_state(struct entry_point_info *tsp_ep,
+                               uint32_t rw,
+                               uint64_t pc,
+                               tsp_context_t *tsp_ctx);
+
+extern tsp_context_t tspd_sp_context[TSPD_CORE_COUNT];
+extern struct tsp_vectors *tsp_vectors;
+#endif /*__ASSEMBLY__*/
+
+#endif /* __TSPD_PRIVATE_H__ */
diff --git a/services/std_svc/psci/psci_afflvl_off.c b/services/std_svc/psci/psci_afflvl_off.c
new file mode 100644 (file)
index 0000000..7eb9688
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <string.h>
+#include "psci_private.h"
+
+typedef void (*afflvl_off_handler_t)(aff_map_node_t *node);
+
+/*******************************************************************************
+ * The next three functions implement a handler for each supported affinity
+ * level which is called when that affinity level is turned off.
+ ******************************************************************************/
+static void psci_afflvl0_off(aff_map_node_t *cpu_node)
+{
+       assert(cpu_node->level == MPIDR_AFFLVL0);
+
+       /*
+        * Arch. management. Perform the necessary steps to flush all
+        * cpu caches.
+        */
+       psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL0);
+
+       /*
+        * Plat. management: Perform platform specific actions to turn this
+        * cpu off e.g. exit cpu coherency, program the power controller etc.
+        */
+       psci_plat_pm_ops->affinst_off(cpu_node->level,
+                                    psci_get_phys_state(cpu_node));
+}
+
+static void psci_afflvl1_off(aff_map_node_t *cluster_node)
+{
+       /* Sanity check the cluster level */
+       assert(cluster_node->level == MPIDR_AFFLVL1);
+
+       /*
+        * Arch. Management. Flush all levels of caches to PoC if
+        * the cluster is to be shutdown.
+        */
+       psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL1);
+
+       /*
+        * Plat. Management. Allow the platform to do its cluster
+        * specific bookeeping e.g. turn off interconnect coherency,
+        * program the power controller etc.
+        */
+       psci_plat_pm_ops->affinst_off(cluster_node->level,
+                                            psci_get_phys_state(cluster_node));
+}
+
+static void psci_afflvl2_off(aff_map_node_t *system_node)
+{
+       /* Cannot go beyond this level */
+       assert(system_node->level == MPIDR_AFFLVL2);
+
+       /*
+        * Keep the physical state of the system handy to decide what
+        * action needs to be taken
+        */
+
+       /*
+        * Arch. Management. Flush all levels of caches to PoC if
+        * the system is to be shutdown.
+        */
+       psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL2);
+
+       /*
+        * Plat. Management : Allow the platform to do its bookeeping
+        * at this affinity level
+        */
+       psci_plat_pm_ops->affinst_off(system_node->level,
+                                            psci_get_phys_state(system_node));
+}
+
+static const afflvl_off_handler_t psci_afflvl_off_handlers[] = {
+       psci_afflvl0_off,
+       psci_afflvl1_off,
+       psci_afflvl2_off,
+};
+
+/*******************************************************************************
+ * This function takes an array of pointers to affinity instance nodes in the
+ * topology tree and calls the off handler for the corresponding affinity
+ * levels
+ ******************************************************************************/
+static void psci_call_off_handlers(aff_map_node_t *mpidr_nodes[],
+                                 int start_afflvl,
+                                 int end_afflvl)
+{
+       int level;
+       aff_map_node_t *node;
+
+       for (level = start_afflvl; level <= end_afflvl; level++) {
+               node = mpidr_nodes[level];
+               if (node == NULL)
+                       continue;
+
+               psci_afflvl_off_handlers[level](node);
+       }
+}
+
+/*******************************************************************************
+ * Top level handler which is called when a cpu wants to power itself down.
+ * It's assumed that along with turning the cpu off, higher affinity levels will
+ * be turned off as far as possible. It traverses through all the affinity
+ * levels performing generic, architectural, platform setup and state management
+ * e.g. for a cluster that's to be powered off, it will call the platform
+ * specific code which will disable coherency at the interconnect level if the
+ * cpu is the last in the cluster. For a cpu it could mean programming the power
+ * the power controller etc.
+ *
+ * The state of all the relevant affinity levels is changed prior to calling the
+ * affinity level specific handlers as their actions would depend upon the state
+ * the affinity level is about to enter.
+ *
+ * The affinity level specific handlers are called in ascending order i.e. from
+ * the lowest to the highest affinity level implemented by the platform because
+ * to turn off affinity level X it is neccesary to turn off affinity level X - 1
+ * first.
+ ******************************************************************************/
+int psci_afflvl_off(int start_afflvl,
+                   int end_afflvl)
+{
+       int rc;
+       mpidr_aff_map_nodes_t mpidr_nodes;
+       unsigned int max_phys_off_afflvl;
+
+       /*
+        * This function must only be called on platforms where the
+        * CPU_OFF platform hooks have been implemented.
+        */
+       assert(psci_plat_pm_ops->affinst_off);
+
+       /*
+        * Collect the pointers to the nodes in the topology tree for
+        * each affinity instance in the mpidr. If this function does
+        * not return successfully then either the mpidr or the affinity
+        * levels are incorrect. Either way, this an internal TF error
+        * therefore assert.
+        */
+       rc = psci_get_aff_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
+                                   start_afflvl,
+                                   end_afflvl,
+                                   mpidr_nodes);
+       assert(rc == PSCI_E_SUCCESS);
+
+       /*
+        * This function acquires the lock corresponding to each affinity
+        * level so that by the time all locks are taken, the system topology
+        * is snapshot and state management can be done safely.
+        */
+       psci_acquire_afflvl_locks(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes);
+
+
+       /*
+        * Call the cpu off handler registered by the Secure Payload Dispatcher
+        * to let it do any bookkeeping. Assume that the SPD always reports an
+        * E_DENIED error if SP refuse to power down
+        */
+       if (psci_spd_pm && psci_spd_pm->svc_off) {
+               rc = psci_spd_pm->svc_off(0);
+               if (rc)
+                       goto exit;
+       }
+
+       /*
+        * This function updates the state of each affinity instance
+        * corresponding to the mpidr in the range of affinity levels
+        * specified.
+        */
+       psci_do_afflvl_state_mgmt(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes,
+                                 PSCI_STATE_OFF);
+
+       max_phys_off_afflvl = psci_find_max_phys_off_afflvl(start_afflvl,
+                                                          end_afflvl,
+                                                          mpidr_nodes);
+       assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
+
+       /* Stash the highest affinity level that will enter the OFF state. */
+       psci_set_max_phys_off_afflvl(max_phys_off_afflvl);
+
+       /* Perform generic, architecture and platform specific handling */
+       psci_call_off_handlers(mpidr_nodes,
+                                   start_afflvl,
+                                   end_afflvl);
+
+       /*
+        * Invalidate the entry for the highest affinity level stashed earlier.
+        * This ensures that any reads of this variable outside the power
+        * up/down sequences return PSCI_INVALID_DATA.
+        *
+        */
+       psci_set_max_phys_off_afflvl(PSCI_INVALID_DATA);
+
+exit:
+       /*
+        * Release the locks corresponding to each affinity level in the
+        * reverse order to which they were acquired.
+        */
+       psci_release_afflvl_locks(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes);
+
+       /*
+        * Check if all actions needed to safely power down this cpu have
+        * successfully completed. Enter a wfi loop which will allow the
+        * power controller to physically power down this cpu.
+        */
+       if (rc == PSCI_E_SUCCESS)
+               psci_power_down_wfi();
+
+       return rc;
+}
diff --git a/services/std_svc/psci/psci_afflvl_on.c b/services/std_svc/psci/psci_afflvl_on.c
new file mode 100644 (file)
index 0000000..0ee03cb
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <debug.h>
+#include <context_mgmt.h>
+#include <platform.h>
+#include <runtime_svc.h>
+#include <stddef.h>
+#include "psci_private.h"
+
+typedef int (*afflvl_on_handler_t)(unsigned long target_cpu,
+                                aff_map_node_t *node);
+
+/*******************************************************************************
+ * This function checks whether a cpu which has been requested to be turned on
+ * is OFF to begin with.
+ ******************************************************************************/
+static int cpu_on_validate_state(unsigned int psci_state)
+{
+       if (psci_state == PSCI_STATE_ON || psci_state == PSCI_STATE_SUSPEND)
+               return PSCI_E_ALREADY_ON;
+
+       if (psci_state == PSCI_STATE_ON_PENDING)
+               return PSCI_E_ON_PENDING;
+
+       assert(psci_state == PSCI_STATE_OFF);
+       return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Handler routine to turn a cpu on. It takes care of any generic, architectural
+ * or platform specific setup required.
+ * TODO: Split this code across separate handlers for each type of setup?
+ ******************************************************************************/
+static int psci_afflvl0_on(unsigned long target_cpu,
+                          aff_map_node_t *cpu_node)
+{
+       unsigned long psci_entrypoint;
+
+       /* Sanity check to safeguard against data corruption */
+       assert(cpu_node->level == MPIDR_AFFLVL0);
+
+       /* Set the secure world (EL3) re-entry point after BL1 */
+       psci_entrypoint = (unsigned long) psci_aff_on_finish_entry;
+
+       /*
+        * Plat. management: Give the platform the current state
+        * of the target cpu to allow it to perform the necessary
+        * steps to power on.
+        */
+       return psci_plat_pm_ops->affinst_on(target_cpu,
+                                           psci_entrypoint,
+                                           cpu_node->level,
+                                           psci_get_phys_state(cpu_node));
+}
+
+/*******************************************************************************
+ * Handler routine to turn a cluster on. It takes care or any generic, arch.
+ * or platform specific setup required.
+ * TODO: Split this code across separate handlers for each type of setup?
+ ******************************************************************************/
+static int psci_afflvl1_on(unsigned long target_cpu,
+                          aff_map_node_t *cluster_node)
+{
+       unsigned long psci_entrypoint;
+
+       assert(cluster_node->level == MPIDR_AFFLVL1);
+
+       /*
+        * There is no generic and arch. specific cluster
+        * management required
+        */
+
+       /* State management: Is not required while turning a cluster on */
+
+       /*
+        * Plat. management: Give the platform the current state
+        * of the target cpu to allow it to perform the necessary
+        * steps to power on.
+        */
+       psci_entrypoint = (unsigned long) psci_aff_on_finish_entry;
+       return psci_plat_pm_ops->affinst_on(target_cpu,
+                                           psci_entrypoint,
+                                           cluster_node->level,
+                                           psci_get_phys_state(cluster_node));
+}
+
+/*******************************************************************************
+ * Handler routine to turn a cluster of clusters on. It takes care or any
+ * generic, arch. or platform specific setup required.
+ * TODO: Split this code across separate handlers for each type of setup?
+ ******************************************************************************/
+static int psci_afflvl2_on(unsigned long target_cpu,
+                          aff_map_node_t *system_node)
+{
+       unsigned long psci_entrypoint;
+
+       /* Cannot go beyond affinity level 2 in this psci imp. */
+       assert(system_node->level == MPIDR_AFFLVL2);
+
+       /*
+        * There is no generic and arch. specific system management
+        * required
+        */
+
+       /* State management: Is not required while turning a system on */
+
+       /*
+        * Plat. management: Give the platform the current state
+        * of the target cpu to allow it to perform the necessary
+        * steps to power on.
+        */
+       psci_entrypoint = (unsigned long) psci_aff_on_finish_entry;
+       return psci_plat_pm_ops->affinst_on(target_cpu,
+                                           psci_entrypoint,
+                                           system_node->level,
+                                           psci_get_phys_state(system_node));
+}
+
+/* Private data structure to make this handlers accessible through indexing */
+static const afflvl_on_handler_t psci_afflvl_on_handlers[] = {
+       psci_afflvl0_on,
+       psci_afflvl1_on,
+       psci_afflvl2_on,
+};
+
+/*******************************************************************************
+ * This function takes an array of pointers to affinity instance nodes in the
+ * topology tree and calls the on handler for the corresponding affinity
+ * levels
+ ******************************************************************************/
+static int psci_call_on_handlers(aff_map_node_t *target_cpu_nodes[],
+                                int start_afflvl,
+                                int end_afflvl,
+                                unsigned long target_cpu)
+{
+       int rc = PSCI_E_INVALID_PARAMS, level;
+       aff_map_node_t *node;
+
+       for (level = end_afflvl; level >= start_afflvl; level--) {
+               node = target_cpu_nodes[level];
+               if (node == NULL)
+                       continue;
+
+               /*
+                * TODO: In case of an error should there be a way
+                * of undoing what we might have setup at higher
+                * affinity levels.
+                */
+               rc = psci_afflvl_on_handlers[level](target_cpu,
+                                                   node);
+               if (rc != PSCI_E_SUCCESS)
+                       break;
+       }
+
+       return rc;
+}
+
+/*******************************************************************************
+ * Generic handler which is called to physically power on a cpu identified by
+ * its mpidr. It traverses through all the affinity levels performing generic,
+ * architectural, platform setup and state management e.g. for a cpu that is
+ * to be powered on, it will ensure that enough information is stashed for it
+ * to resume execution in the non-secure security state.
+ *
+ * The state of all the relevant affinity levels is changed after calling the
+ * affinity level specific handlers as their actions would depend upon the state
+ * the affinity level is currently in.
+ *
+ * The affinity level specific handlers are called in descending order i.e. from
+ * the highest to the lowest affinity level implemented by the platform because
+ * to turn on affinity level X it is necessary to turn on affinity level X + 1
+ * first.
+ ******************************************************************************/
+int psci_afflvl_on(unsigned long target_cpu,
+                  entry_point_info_t *ep,
+                  int start_afflvl,
+                  int end_afflvl)
+{
+       int rc;
+       mpidr_aff_map_nodes_t target_cpu_nodes;
+
+       /*
+        * This function must only be called on platforms where the
+        * CPU_ON platform hooks have been implemented.
+        */
+       assert(psci_plat_pm_ops->affinst_on &&
+                       psci_plat_pm_ops->affinst_on_finish);
+
+       /*
+        * Collect the pointers to the nodes in the topology tree for
+        * each affinity instance in the mpidr. If this function does
+        * not return successfully then either the mpidr or the affinity
+        * levels are incorrect.
+        */
+       rc = psci_get_aff_map_nodes(target_cpu,
+                                   start_afflvl,
+                                   end_afflvl,
+                                   target_cpu_nodes);
+       assert(rc == PSCI_E_SUCCESS);
+
+       /*
+        * This function acquires the lock corresponding to each affinity
+        * level so that by the time all locks are taken, the system topology
+        * is snapshot and state management can be done safely.
+        */
+       psci_acquire_afflvl_locks(start_afflvl,
+                                 end_afflvl,
+                                 target_cpu_nodes);
+
+       /*
+        * Generic management: Ensure that the cpu is off to be
+        * turned on.
+        */
+       rc = cpu_on_validate_state(psci_get_state(
+                                   target_cpu_nodes[MPIDR_AFFLVL0]));
+       if (rc != PSCI_E_SUCCESS)
+               goto exit;
+
+       /*
+        * Call the cpu on handler registered by the Secure Payload Dispatcher
+        * to let it do any bookeeping. If the handler encounters an error, it's
+        * expected to assert within
+        */
+       if (psci_spd_pm && psci_spd_pm->svc_on)
+               psci_spd_pm->svc_on(target_cpu);
+
+       /* Perform generic, architecture and platform specific handling. */
+       rc = psci_call_on_handlers(target_cpu_nodes,
+                                  start_afflvl,
+                                  end_afflvl,
+                                  target_cpu);
+
+       assert(rc == PSCI_E_SUCCESS || rc == PSCI_E_INTERN_FAIL);
+
+       /*
+        * This function updates the state of each affinity instance
+        * corresponding to the mpidr in the range of affinity levels
+        * specified.
+        */
+       if (rc == PSCI_E_SUCCESS) {
+               psci_do_afflvl_state_mgmt(start_afflvl,
+                                         end_afflvl,
+                                         target_cpu_nodes,
+                                         PSCI_STATE_ON_PENDING);
+
+               /*
+                * Store the re-entry information for the non-secure world.
+                */
+               cm_init_context(target_cpu, ep);
+       }
+
+exit:
+       /*
+        * This loop releases the lock corresponding to each affinity level
+        * in the reverse order to which they were acquired.
+        */
+       psci_release_afflvl_locks(start_afflvl,
+                                 end_afflvl,
+                                 target_cpu_nodes);
+
+       return rc;
+}
+
+/*******************************************************************************
+ * The following functions finish an earlier affinity power on request. They
+ * are called by the common finisher routine in psci_common.c.
+ ******************************************************************************/
+static void psci_afflvl0_on_finish(aff_map_node_t *cpu_node)
+{
+       unsigned int plat_state, state;
+
+       assert(cpu_node->level == MPIDR_AFFLVL0);
+
+       /* Ensure we have been explicitly woken up by another cpu */
+       state = psci_get_state(cpu_node);
+       assert(state == PSCI_STATE_ON_PENDING);
+
+       /*
+        * Plat. management: Perform the platform specific actions
+        * for this cpu e.g. enabling the gic or zeroing the mailbox
+        * register. The actual state of this cpu has already been
+        * changed.
+        */
+
+       /* Get the physical state of this cpu */
+       plat_state = get_phys_state(state);
+       psci_plat_pm_ops->affinst_on_finish(cpu_node->level,
+                                                        plat_state);
+
+       /*
+        * Arch. management: Enable data cache and manage stack memory
+        */
+       psci_do_pwrup_cache_maintenance();
+
+       /*
+        * All the platform specific actions for turning this cpu
+        * on have completed. Perform enough arch.initialization
+        * to run in the non-secure address space.
+        */
+       bl31_arch_setup();
+
+       /*
+        * Call the cpu on finish handler registered by the Secure Payload
+        * Dispatcher to let it do any bookeeping. If the handler encounters an
+        * error, it's expected to assert within
+        */
+       if (psci_spd_pm && psci_spd_pm->svc_on_finish)
+               psci_spd_pm->svc_on_finish(0);
+
+       /*
+        * Generic management: Now we just need to retrieve the
+        * information that we had stashed away during the cpu_on
+        * call to set this cpu on its way.
+        */
+       cm_prepare_el3_exit(NON_SECURE);
+
+       /* Clean caches before re-entering normal world */
+       dcsw_op_louis(DCCSW);
+}
+
+static void psci_afflvl1_on_finish(aff_map_node_t *cluster_node)
+{
+       unsigned int plat_state;
+
+       assert(cluster_node->level == MPIDR_AFFLVL1);
+
+       /*
+        * Plat. management: Perform the platform specific actions
+        * as per the old state of the cluster e.g. enabling
+        * coherency at the interconnect depends upon the state with
+        * which this cluster was powered up. If anything goes wrong
+        * then assert as there is no way to recover from this
+        * situation.
+        */
+       plat_state = psci_get_phys_state(cluster_node);
+       psci_plat_pm_ops->affinst_on_finish(cluster_node->level,
+                                                plat_state);
+}
+
+
+static void psci_afflvl2_on_finish(aff_map_node_t *system_node)
+{
+       unsigned int plat_state;
+
+       /* Cannot go beyond this affinity level */
+       assert(system_node->level == MPIDR_AFFLVL2);
+
+       /*
+        * Currently, there are no architectural actions to perform
+        * at the system level.
+        */
+
+       /*
+        * Plat. management: Perform the platform specific actions
+        * as per the old state of the cluster e.g. enabling
+        * coherency at the interconnect depends upon the state with
+        * which this cluster was powered up. If anything goes wrong
+        * then assert as there is no way to recover from this
+        * situation.
+        */
+       plat_state = psci_get_phys_state(system_node);
+       psci_plat_pm_ops->affinst_on_finish(system_node->level,
+                                                  plat_state);
+}
+
+const afflvl_power_on_finisher_t psci_afflvl_on_finishers[] = {
+       psci_afflvl0_on_finish,
+       psci_afflvl1_on_finish,
+       psci_afflvl2_on_finish,
+};
diff --git a/services/std_svc/psci/psci_afflvl_suspend.c b/services/std_svc/psci/psci_afflvl_suspend.c
new file mode 100644 (file)
index 0000000..dad0cef
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <arch.h>
+#include <arch_helpers.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <cpu_data.h>
+#include <debug.h>
+#include <platform.h>
+#include <runtime_svc.h>
+#include <stddef.h>
+#include "psci_private.h"
+
+typedef void (*afflvl_suspend_handler_t)(aff_map_node_t *node);
+
+/*******************************************************************************
+ * This function saves the power state parameter passed in the current PSCI
+ * cpu_suspend call in the per-cpu data array.
+ ******************************************************************************/
+void psci_set_suspend_power_state(unsigned int power_state)
+{
+       set_cpu_data(psci_svc_cpu_data.power_state, power_state);
+       flush_cpu_data(psci_svc_cpu_data.power_state);
+}
+
+/*******************************************************************************
+ * This function gets the affinity level till which the current cpu could be
+ * powered down during a cpu_suspend call. Returns PSCI_INVALID_DATA if the
+ * power state is invalid.
+ ******************************************************************************/
+int psci_get_suspend_afflvl()
+{
+       unsigned int power_state;
+
+       power_state = get_cpu_data(psci_svc_cpu_data.power_state);
+
+       return ((power_state == PSCI_INVALID_DATA) ?
+               power_state : psci_get_pstate_afflvl(power_state));
+}
+
+/*******************************************************************************
+ * This function gets the state id of the current cpu from the power state
+ * parameter saved in the per-cpu data array. Returns PSCI_INVALID_DATA if the
+ * power state saved is invalid.
+ ******************************************************************************/
+int psci_get_suspend_stateid()
+{
+       unsigned int power_state;
+
+       power_state = get_cpu_data(psci_svc_cpu_data.power_state);
+
+       return ((power_state == PSCI_INVALID_DATA) ?
+               power_state : psci_get_pstate_id(power_state));
+}
+
+/*******************************************************************************
+ * This function gets the state id of the cpu specified by the 'mpidr' parameter
+ * from the power state parameter saved in the per-cpu data array. Returns
+ * PSCI_INVALID_DATA if the power state saved is invalid.
+ ******************************************************************************/
+int psci_get_suspend_stateid_by_mpidr(unsigned long mpidr)
+{
+       unsigned int power_state;
+
+       power_state = get_cpu_data_by_mpidr(mpidr,
+                                           psci_svc_cpu_data.power_state);
+
+       return ((power_state == PSCI_INVALID_DATA) ?
+               power_state : psci_get_pstate_id(power_state));
+}
+
+/*******************************************************************************
+ * The next three functions implement a handler for each supported affinity
+ * level which is called when that affinity level is about to be suspended.
+ ******************************************************************************/
+static void psci_afflvl0_suspend(aff_map_node_t *cpu_node)
+{
+       unsigned long psci_entrypoint;
+
+       /* Sanity check to safeguard against data corruption */
+       assert(cpu_node->level == MPIDR_AFFLVL0);
+
+       /* Set the secure world (EL3) re-entry point after BL1 */
+       psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
+
+       /*
+        * Arch. management. Perform the necessary steps to flush all
+        * cpu caches.
+        */
+       psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL0);
+
+       /*
+        * Plat. management: Allow the platform to perform the
+        * necessary actions to turn off this cpu e.g. set the
+        * platform defined mailbox with the psci entrypoint,
+        * program the power controller etc.
+        */
+       psci_plat_pm_ops->affinst_suspend(psci_entrypoint,
+                                                cpu_node->level,
+                                                psci_get_phys_state(cpu_node));
+}
+
+static void psci_afflvl1_suspend(aff_map_node_t *cluster_node)
+{
+       unsigned int plat_state;
+       unsigned long psci_entrypoint;
+
+       /* Sanity check the cluster level */
+       assert(cluster_node->level == MPIDR_AFFLVL1);
+
+       /*
+        * Arch. management: Flush all levels of caches to PoC if the
+        * cluster is to be shutdown.
+        */
+       psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL1);
+
+       /*
+        * Plat. Management. Allow the platform to do its cluster specific
+        * bookeeping e.g. turn off interconnect coherency, program the power
+        * controller etc. Sending the psci entrypoint is currently redundant
+        * beyond affinity level 0 but one never knows what a platform might
+        * do. Also it allows us to keep the platform handler prototype the
+        * same.
+        */
+       plat_state = psci_get_phys_state(cluster_node);
+       psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
+       psci_plat_pm_ops->affinst_suspend(psci_entrypoint,
+                                                cluster_node->level,
+                                                plat_state);
+}
+
+
+static void psci_afflvl2_suspend(aff_map_node_t *system_node)
+{
+       unsigned int plat_state;
+       unsigned long psci_entrypoint;
+
+       /* Cannot go beyond this */
+       assert(system_node->level == MPIDR_AFFLVL2);
+
+       /*
+        * Keep the physical state of the system handy to decide what
+        * action needs to be taken
+        */
+       plat_state = psci_get_phys_state(system_node);
+
+       /*
+        * Arch. management: Flush all levels of caches to PoC if the
+        * system is to be shutdown.
+        */
+       psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL2);
+
+       /*
+        * Plat. Management : Allow the platform to do its bookeeping
+        * at this affinity level
+        */
+
+       /*
+        * Sending the psci entrypoint is currently redundant
+        * beyond affinity level 0 but one never knows what a
+        * platform might do. Also it allows us to keep the
+        * platform handler prototype the same.
+        */
+       plat_state = psci_get_phys_state(system_node);
+       psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
+       psci_plat_pm_ops->affinst_suspend(psci_entrypoint,
+                                                system_node->level,
+                                                plat_state);
+}
+
+static const afflvl_suspend_handler_t psci_afflvl_suspend_handlers[] = {
+       psci_afflvl0_suspend,
+       psci_afflvl1_suspend,
+       psci_afflvl2_suspend,
+};
+
+/*******************************************************************************
+ * This function takes an array of pointers to affinity instance nodes in the
+ * topology tree and calls the suspend handler for the corresponding affinity
+ * levels
+ ******************************************************************************/
+static void psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[],
+                                     int start_afflvl,
+                                     int end_afflvl)
+{
+       int level;
+       aff_map_node_t *node;
+
+       for (level = start_afflvl; level <= end_afflvl; level++) {
+               node = mpidr_nodes[level];
+               if (node == NULL)
+                       continue;
+
+               psci_afflvl_suspend_handlers[level](node);
+       }
+}
+
+/*******************************************************************************
+ * Top level handler which is called when a cpu wants to suspend its execution.
+ * It is assumed that along with turning the cpu off, higher affinity levels
+ * until the target affinity level will be turned off as well. It traverses
+ * through all the affinity levels performing generic, architectural, platform
+ * setup and state management e.g. for a cluster that's to be suspended, it will
+ * call the platform specific code which will disable coherency at the
+ * interconnect level if the cpu is the last in the cluster. For a cpu it could
+ * mean programming the power controller etc.
+ *
+ * The state of all the relevant affinity levels is changed prior to calling the
+ * affinity level specific handlers as their actions would depend upon the state
+ * the affinity level is about to enter.
+ *
+ * The affinity level specific handlers are called in ascending order i.e. from
+ * the lowest to the highest affinity level implemented by the platform because
+ * to turn off affinity level X it is neccesary to turn off affinity level X - 1
+ * first.
+ *
+ * All the required parameter checks are performed at the beginning and after
+ * the state transition has been done, no further error is expected and it
+ * is not possible to undo any of the actions taken beyond that point.
+ ******************************************************************************/
+void psci_afflvl_suspend(entry_point_info_t *ep,
+                       int start_afflvl,
+                       int end_afflvl)
+{
+       int skip_wfi = 0;
+       mpidr_aff_map_nodes_t mpidr_nodes;
+       unsigned int max_phys_off_afflvl;
+
+       /*
+        * This function must only be called on platforms where the
+        * CPU_SUSPEND platform hooks have been implemented.
+        */
+       assert(psci_plat_pm_ops->affinst_suspend &&
+                       psci_plat_pm_ops->affinst_suspend_finish);
+
+       /*
+        * Collect the pointers to the nodes in the topology tree for
+        * each affinity instance in the mpidr. If this function does
+        * not return successfully then either the mpidr or the affinity
+        * levels are incorrect. Either way, this an internal TF error
+        * therefore assert.
+        */
+       if (psci_get_aff_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
+                  start_afflvl, end_afflvl, mpidr_nodes) != PSCI_E_SUCCESS)
+               assert(0);
+
+       /*
+        * This function acquires the lock corresponding to each affinity
+        * level so that by the time all locks are taken, the system topology
+        * is snapshot and state management can be done safely.
+        */
+       psci_acquire_afflvl_locks(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes);
+
+       /*
+        * We check if there are any pending interrupts after the delay
+        * introduced by lock contention to increase the chances of early
+        * detection that a wake-up interrupt has fired.
+        */
+       if (read_isr_el1()) {
+               skip_wfi = 1;
+               goto exit;
+       }
+
+       /*
+        * Call the cpu suspend handler registered by the Secure Payload
+        * Dispatcher to let it do any bookeeping. If the handler encounters an
+        * error, it's expected to assert within
+        */
+       if (psci_spd_pm && psci_spd_pm->svc_suspend)
+               psci_spd_pm->svc_suspend(0);
+
+       /*
+        * This function updates the state of each affinity instance
+        * corresponding to the mpidr in the range of affinity levels
+        * specified.
+        */
+       psci_do_afflvl_state_mgmt(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes,
+                                 PSCI_STATE_SUSPEND);
+
+       max_phys_off_afflvl = psci_find_max_phys_off_afflvl(start_afflvl,
+                                                           end_afflvl,
+                                                           mpidr_nodes);
+       assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
+
+       /* Stash the highest affinity level that will be turned off */
+       psci_set_max_phys_off_afflvl(max_phys_off_afflvl);
+
+       /*
+        * Store the re-entry information for the non-secure world.
+        */
+       cm_init_context(read_mpidr_el1(), ep);
+
+       /* Perform generic, architecture and platform specific handling */
+       psci_call_suspend_handlers(mpidr_nodes,
+                                       start_afflvl,
+                                       end_afflvl);
+
+       /*
+        * Invalidate the entry for the highest affinity level stashed earlier.
+        * This ensures that any reads of this variable outside the power
+        * up/down sequences return PSCI_INVALID_DATA.
+        */
+       psci_set_max_phys_off_afflvl(PSCI_INVALID_DATA);
+
+exit:
+       /*
+        * Release the locks corresponding to each affinity level in the
+        * reverse order to which they were acquired.
+        */
+       psci_release_afflvl_locks(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes);
+       if (!skip_wfi)
+               psci_power_down_wfi();
+}
+
+/*******************************************************************************
+ * The following functions finish an earlier affinity suspend request. They
+ * are called by the common finisher routine in psci_common.c.
+ ******************************************************************************/
+static void psci_afflvl0_suspend_finish(aff_map_node_t *cpu_node)
+{
+       unsigned int plat_state, state;
+       int32_t suspend_level;
+       uint64_t counter_freq;
+
+       assert(cpu_node->level == MPIDR_AFFLVL0);
+
+       /* Ensure we have been woken up from a suspended state */
+       state = psci_get_state(cpu_node);
+       assert(state == PSCI_STATE_SUSPEND);
+
+       /*
+        * Plat. management: Perform the platform specific actions
+        * before we change the state of the cpu e.g. enabling the
+        * gic or zeroing the mailbox register. If anything goes
+        * wrong then assert as there is no way to recover from this
+        * situation.
+        */
+
+       /* Get the physical state of this cpu */
+       plat_state = get_phys_state(state);
+       psci_plat_pm_ops->affinst_suspend_finish(cpu_node->level,
+                                                             plat_state);
+
+       /*
+        * Arch. management: Enable the data cache, manage stack memory and
+        * restore the stashed EL3 architectural context from the 'cpu_context'
+        * structure for this cpu.
+        */
+       psci_do_pwrup_cache_maintenance();
+
+       /* Re-init the cntfrq_el0 register */
+       counter_freq = plat_get_syscnt_freq();
+       write_cntfrq_el0(counter_freq);
+
+       /*
+        * Call the cpu suspend finish handler registered by the Secure Payload
+        * Dispatcher to let it do any bookeeping. If the handler encounters an
+        * error, it's expected to assert within
+        */
+       if (psci_spd_pm && psci_spd_pm->svc_suspend) {
+               suspend_level = psci_get_suspend_afflvl();
+               assert (suspend_level != PSCI_INVALID_DATA);
+               psci_spd_pm->svc_suspend_finish(suspend_level);
+       }
+
+       /* Invalidate the suspend context for the node */
+       psci_set_suspend_power_state(PSCI_INVALID_DATA);
+
+       /*
+        * Generic management: Now we just need to retrieve the
+        * information that we had stashed away during the suspend
+        * call to set this cpu on its way.
+        */
+       cm_prepare_el3_exit(NON_SECURE);
+
+       /* Clean caches before re-entering normal world */
+       dcsw_op_louis(DCCSW);
+}
+
+static void psci_afflvl1_suspend_finish(aff_map_node_t *cluster_node)
+{
+       unsigned int plat_state;
+
+       assert(cluster_node->level == MPIDR_AFFLVL1);
+
+       /*
+        * Plat. management: Perform the platform specific actions
+        * as per the old state of the cluster e.g. enabling
+        * coherency at the interconnect depends upon the state with
+        * which this cluster was powered up. If anything goes wrong
+        * then assert as there is no way to recover from this
+        * situation.
+        */
+
+       /* Get the physical state of this cpu */
+       plat_state = psci_get_phys_state(cluster_node);
+       psci_plat_pm_ops->affinst_suspend_finish(cluster_node->level,
+                                                     plat_state);
+}
+
+
+static void psci_afflvl2_suspend_finish(aff_map_node_t *system_node)
+{
+       unsigned int plat_state;
+
+       /* Cannot go beyond this affinity level */
+       assert(system_node->level == MPIDR_AFFLVL2);
+
+       /*
+        * Currently, there are no architectural actions to perform
+        * at the system level.
+        */
+
+       /*
+        * Plat. management: Perform the platform specific actions
+        * as per the old state of the cluster e.g. enabling
+        * coherency at the interconnect depends upon the state with
+        * which this cluster was powered up. If anything goes wrong
+        * then assert as there is no way to recover from this
+        * situation.
+        */
+
+       /* Get the physical state of the system */
+       plat_state = psci_get_phys_state(system_node);
+       psci_plat_pm_ops->affinst_suspend_finish(system_node->level,
+                                                     plat_state);
+}
+
+const afflvl_power_on_finisher_t psci_afflvl_suspend_finishers[] = {
+       psci_afflvl0_suspend_finish,
+       psci_afflvl1_suspend_finish,
+       psci_afflvl2_suspend_finish,
+};
diff --git a/services/std_svc/psci/psci_common.c b/services/std_svc/psci/psci_common.c
new file mode 100644 (file)
index 0000000..f01f306
--- /dev/null
@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <platform.h>
+#include <string.h>
+#include "psci_private.h"
+
+/*
+ * SPD power management operations, expected to be supplied by the registered
+ * SPD on successful SP initialization
+ */
+const spd_pm_ops_t *psci_spd_pm;
+
+/*******************************************************************************
+ * Grand array that holds the platform's topology information for state
+ * management of affinity instances. Each node (aff_map_node) in the array
+ * corresponds to an affinity instance e.g. cluster, cpu within an mpidr
+ ******************************************************************************/
+aff_map_node_t psci_aff_map[PSCI_NUM_AFFS]
+#if USE_COHERENT_MEM
+__attribute__ ((section("tzfw_coherent_mem")))
+#endif
+;
+
+/*******************************************************************************
+ * Pointer to functions exported by the platform to complete power mgmt. ops
+ ******************************************************************************/
+const plat_pm_ops_t *psci_plat_pm_ops;
+
+/*******************************************************************************
+ * This function is passed an array of pointers to affinity level nodes in the
+ * topology tree for an mpidr. It iterates through the nodes to find the highest
+ * affinity level which is marked as physically powered off.
+ ******************************************************************************/
+uint32_t psci_find_max_phys_off_afflvl(uint32_t start_afflvl,
+                                      uint32_t end_afflvl,
+                                      aff_map_node_t *mpidr_nodes[])
+{
+       uint32_t max_afflvl = PSCI_INVALID_DATA;
+
+       for (; start_afflvl <= end_afflvl; start_afflvl++) {
+               if (mpidr_nodes[start_afflvl] == NULL)
+                       continue;
+
+               if (psci_get_phys_state(mpidr_nodes[start_afflvl]) ==
+                   PSCI_STATE_OFF)
+                       max_afflvl = start_afflvl;
+       }
+
+       return max_afflvl;
+}
+
+/*******************************************************************************
+ * This function verifies that the all the other cores in the system have been
+ * turned OFF and the current CPU is the last running CPU in the system.
+ * Returns 1 (true) if the current CPU is the last ON CPU or 0 (false)
+ * otherwise.
+ ******************************************************************************/
+unsigned int psci_is_last_on_cpu(void)
+{
+       unsigned long mpidr = read_mpidr_el1() & MPIDR_AFFINITY_MASK;
+       unsigned int i;
+
+       for (i = psci_aff_limits[MPIDR_AFFLVL0].min;
+                       i <= psci_aff_limits[MPIDR_AFFLVL0].max; i++) {
+
+               assert(psci_aff_map[i].level == MPIDR_AFFLVL0);
+
+               if (!(psci_aff_map[i].state & PSCI_AFF_PRESENT))
+                       continue;
+
+               if (psci_aff_map[i].mpidr == mpidr) {
+                       assert(psci_get_state(&psci_aff_map[i])
+                                       == PSCI_STATE_ON);
+                       continue;
+               }
+
+               if (psci_get_state(&psci_aff_map[i]) != PSCI_STATE_OFF)
+                       return 0;
+       }
+
+       return 1;
+}
+
+/*******************************************************************************
+ * This function saves the highest affinity level which is in OFF state. The
+ * affinity instance with which the level is associated is determined by the
+ * caller.
+ ******************************************************************************/
+void psci_set_max_phys_off_afflvl(uint32_t afflvl)
+{
+       set_cpu_data(psci_svc_cpu_data.max_phys_off_afflvl, afflvl);
+
+       /*
+        * Ensure that the saved value is flushed to main memory and any
+        * speculatively pre-fetched stale copies are invalidated from the
+        * caches of other cpus in the same coherency domain. This ensures that
+        * the value can be safely read irrespective of the state of the data
+        * cache.
+        */
+       flush_cpu_data(psci_svc_cpu_data.max_phys_off_afflvl);
+}
+
+/*******************************************************************************
+ * This function reads the saved highest affinity level which is in OFF
+ * state. The affinity instance with which the level is associated is determined
+ * by the caller.
+ ******************************************************************************/
+uint32_t psci_get_max_phys_off_afflvl(void)
+{
+       /*
+        * Ensure that the last update of this value in this cpu's cache is
+        * flushed to main memory and any speculatively pre-fetched stale copies
+        * are invalidated from the caches of other cpus in the same coherency
+        * domain. This ensures that the value is always read from the main
+        * memory when it was written before the data cache was enabled.
+        */
+       flush_cpu_data(psci_svc_cpu_data.max_phys_off_afflvl);
+       return get_cpu_data(psci_svc_cpu_data.max_phys_off_afflvl);
+}
+
+/*******************************************************************************
+ * Routine to return the maximum affinity level to traverse to after a cpu has
+ * been physically powered up. It is expected to be called immediately after
+ * reset from assembler code.
+ ******************************************************************************/
+int get_power_on_target_afflvl()
+{
+       int afflvl;
+
+#if DEBUG
+       unsigned int state;
+       aff_map_node_t *node;
+
+       /* Retrieve our node from the topology tree */
+       node = psci_get_aff_map_node(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
+                                    MPIDR_AFFLVL0);
+       assert(node);
+
+       /*
+        * Sanity check the state of the cpu. It should be either suspend or "on
+        * pending"
+        */
+       state = psci_get_state(node);
+       if (node->mpidr != 0) {
+         assert(state == PSCI_STATE_SUSPEND || state == PSCI_STATE_ON_PENDING);
+       }
+#endif
+
+       /*
+        * Assume that this cpu was suspended and retrieve its target affinity
+        * level. If it is invalid then it could only have been turned off
+        * earlier. get_max_afflvl() will return the highest affinity level a
+        * cpu can be turned off to.
+        */
+       afflvl = psci_get_suspend_afflvl();
+       if (afflvl == PSCI_INVALID_DATA)
+               afflvl = get_max_afflvl();
+       return afflvl;
+}
+
+/*******************************************************************************
+ * Simple routine to retrieve the maximum affinity level supported by the
+ * platform and check that it makes sense.
+ ******************************************************************************/
+int get_max_afflvl(void)
+{
+       int aff_lvl;
+
+       aff_lvl = plat_get_max_afflvl();
+       assert(aff_lvl <= MPIDR_MAX_AFFLVL && aff_lvl >= MPIDR_AFFLVL0);
+
+       return aff_lvl;
+}
+
+/*******************************************************************************
+ * Simple routine to set the id of an affinity instance at a given level in the
+ * mpidr.
+ ******************************************************************************/
+unsigned long mpidr_set_aff_inst(unsigned long mpidr,
+                                unsigned char aff_inst,
+                                int aff_lvl)
+{
+       unsigned long aff_shift;
+
+       assert(aff_lvl <= MPIDR_AFFLVL3);
+
+       /*
+        * Decide the number of bits to shift by depending upon
+        * the affinity level
+        */
+       aff_shift = get_afflvl_shift(aff_lvl);
+
+       /* Clear the existing affinity instance & set the new one*/
+       mpidr &= ~(MPIDR_AFFLVL_MASK << aff_shift);
+       mpidr |= aff_inst << aff_shift;
+
+       return mpidr;
+}
+
+/*******************************************************************************
+ * This function sanity checks a range of affinity levels.
+ ******************************************************************************/
+int psci_check_afflvl_range(int start_afflvl, int end_afflvl)
+{
+       /* Sanity check the parameters passed */
+       if (end_afflvl > get_max_afflvl())
+               return PSCI_E_INVALID_PARAMS;
+
+       if (start_afflvl < MPIDR_AFFLVL0)
+               return PSCI_E_INVALID_PARAMS;
+
+       if (end_afflvl < start_afflvl)
+               return PSCI_E_INVALID_PARAMS;
+
+       return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * This function is passed an array of pointers to affinity level nodes in the
+ * topology tree for an mpidr and the state which each node should transition
+ * to. It updates the state of each node between the specified affinity levels.
+ ******************************************************************************/
+void psci_do_afflvl_state_mgmt(uint32_t start_afflvl,
+                              uint32_t end_afflvl,
+                              aff_map_node_t *mpidr_nodes[],
+                              uint32_t state)
+{
+       uint32_t level;
+
+       for (level = start_afflvl; level <= end_afflvl; level++) {
+               if (mpidr_nodes[level] == NULL)
+                       continue;
+               psci_set_state(mpidr_nodes[level], state);
+       }
+}
+
+/*******************************************************************************
+ * This function is passed an array of pointers to affinity level nodes in the
+ * topology tree for an mpidr. It picks up locks for each affinity level bottom
+ * up in the range specified.
+ ******************************************************************************/
+void psci_acquire_afflvl_locks(int start_afflvl,
+                              int end_afflvl,
+                              aff_map_node_t *mpidr_nodes[])
+{
+       int level;
+
+       for (level = start_afflvl; level <= end_afflvl; level++) {
+               if (mpidr_nodes[level] == NULL)
+                       continue;
+
+               psci_lock_get(mpidr_nodes[level]);
+       }
+}
+
+/*******************************************************************************
+ * This function is passed an array of pointers to affinity level nodes in the
+ * topology tree for an mpidr. It releases the lock for each affinity level top
+ * down in the range specified.
+ ******************************************************************************/
+void psci_release_afflvl_locks(int start_afflvl,
+                              int end_afflvl,
+                              aff_map_node_t *mpidr_nodes[])
+{
+       int level;
+
+       for (level = end_afflvl; level >= start_afflvl; level--) {
+               if (mpidr_nodes[level] == NULL)
+                       continue;
+
+               psci_lock_release(mpidr_nodes[level]);
+       }
+}
+
+/*******************************************************************************
+ * Simple routine to determine whether an affinity instance at a given level
+ * in an mpidr exists or not.
+ ******************************************************************************/
+int psci_validate_mpidr(unsigned long mpidr, int level)
+{
+       aff_map_node_t *node;
+
+       node = psci_get_aff_map_node(mpidr, level);
+       if (node && (node->state & PSCI_AFF_PRESENT))
+               return PSCI_E_SUCCESS;
+       else
+               return PSCI_E_INVALID_PARAMS;
+}
+
+/*******************************************************************************
+ * This function determines the full entrypoint information for the requested
+ * PSCI entrypoint on power on/resume and returns it.
+ ******************************************************************************/
+int psci_get_ns_ep_info(entry_point_info_t *ep,
+                      uint64_t entrypoint, uint64_t context_id)
+{
+       uint32_t ep_attr, mode, sctlr, daif, ee;
+       uint32_t ns_scr_el3 = read_scr_el3();
+       uint32_t ns_sctlr_el1 = read_sctlr_el1();
+
+       sctlr = ns_scr_el3 & SCR_HCE_BIT ? read_sctlr_el2() : ns_sctlr_el1;
+       ee = 0;
+
+       ep_attr = NON_SECURE | EP_ST_DISABLE;
+       if (sctlr & SCTLR_EE_BIT) {
+               ep_attr |= EP_EE_BIG;
+               ee = 1;
+       }
+       SET_PARAM_HEAD(ep, PARAM_EP, VERSION_1, ep_attr);
+
+       ep->pc = entrypoint;
+       memset(&ep->args, 0, sizeof(ep->args));
+       ep->args.arg0 = context_id;
+
+       /*
+        * Figure out whether the cpu enters the non-secure address space
+        * in aarch32 or aarch64
+        */
+       if (ns_scr_el3 & SCR_RW_BIT) {
+
+               /*
+                * Check whether a Thumb entry point has been provided for an
+                * aarch64 EL
+                */
+               if (entrypoint & 0x1)
+                       return PSCI_E_INVALID_PARAMS;
+
+               mode = ns_scr_el3 & SCR_HCE_BIT ? MODE_EL2 : MODE_EL1;
+
+               ep->spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+       } else {
+
+               mode = ns_scr_el3 & SCR_HCE_BIT ? MODE32_hyp : MODE32_svc;
+
+               /*
+                * TODO: Choose async. exception bits if HYP mode is not
+                * implemented according to the values of SCR.{AW, FW} bits
+                */
+               daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT;
+
+               ep->spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, daif);
+       }
+
+       return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * This function takes a pointer to an affinity node in the topology tree and
+ * returns its state. State of a non-leaf node needs to be calculated.
+ ******************************************************************************/
+unsigned short psci_get_state(aff_map_node_t *node)
+{
+#if !USE_COHERENT_MEM
+       flush_dcache_range((uint64_t) node, sizeof(*node));
+#endif
+
+       assert(node->level >= MPIDR_AFFLVL0 && node->level <= MPIDR_MAX_AFFLVL);
+
+       /* A cpu node just contains the state which can be directly returned */
+       if (node->level == MPIDR_AFFLVL0)
+               return (node->state >> PSCI_STATE_SHIFT) & PSCI_STATE_MASK;
+
+       /*
+        * For an affinity level higher than a cpu, the state has to be
+        * calculated. It depends upon the value of the reference count
+        * which is managed by each node at the next lower affinity level
+        * e.g. for a cluster, each cpu increments/decrements the reference
+        * count. If the reference count is 0 then the affinity level is
+        * OFF else ON.
+        */
+       if (node->ref_count)
+               return PSCI_STATE_ON;
+       else
+               return PSCI_STATE_OFF;
+}
+
+/*******************************************************************************
+ * This function takes a pointer to an affinity node in the topology tree and
+ * a target state. State of a non-leaf node needs to be converted to a reference
+ * count. State of a leaf node can be set directly.
+ ******************************************************************************/
+void psci_set_state(aff_map_node_t *node, unsigned short state)
+{
+       assert(node->level >= MPIDR_AFFLVL0 && node->level <= MPIDR_MAX_AFFLVL);
+
+       /*
+        * For an affinity level higher than a cpu, the state is used
+        * to decide whether the reference count is incremented or
+        * decremented. Entry into the ON_PENDING state does not have
+        * effect.
+        */
+       if (node->level > MPIDR_AFFLVL0) {
+               switch (state) {
+               case PSCI_STATE_ON:
+                       node->ref_count++;
+                       break;
+               case PSCI_STATE_OFF:
+               case PSCI_STATE_SUSPEND:
+                       node->ref_count--;
+                       break;
+               case PSCI_STATE_ON_PENDING:
+                       /*
+                        * An affinity level higher than a cpu will not undergo
+                        * a state change when it is about to be turned on
+                        */
+                       return;
+               default:
+                       assert(0);
+               }
+       } else {
+               node->state &= ~(PSCI_STATE_MASK << PSCI_STATE_SHIFT);
+               node->state |= (state & PSCI_STATE_MASK) << PSCI_STATE_SHIFT;
+       }
+
+#if !USE_COHERENT_MEM
+       flush_dcache_range((uint64_t) node, sizeof(*node));
+#endif
+}
+
+/*******************************************************************************
+ * An affinity level could be on, on_pending, suspended or off. These are the
+ * logical states it can be in. Physically either it is off or on. When it is in
+ * the state on_pending then it is about to be turned on. It is not possible to
+ * tell whether that's actually happenned or not. So we err on the side of
+ * caution & treat the affinity level as being turned off.
+ ******************************************************************************/
+unsigned short psci_get_phys_state(aff_map_node_t *node)
+{
+       unsigned int state;
+
+       state = psci_get_state(node);
+       return get_phys_state(state);
+}
+
+/*******************************************************************************
+ * This function takes an array of pointers to affinity instance nodes in the
+ * topology tree and calls the physical power on handler for the corresponding
+ * affinity levels
+ ******************************************************************************/
+static void psci_call_power_on_handlers(aff_map_node_t *mpidr_nodes[],
+                                      int start_afflvl,
+                                      int end_afflvl,
+                                      afflvl_power_on_finisher_t *pon_handlers)
+{
+       int level;
+       aff_map_node_t *node;
+
+       for (level = end_afflvl; level >= start_afflvl; level--) {
+               node = mpidr_nodes[level];
+               if (node == NULL)
+                       continue;
+
+               /*
+                * If we run into any trouble while powering up an
+                * affinity instance, then there is no recovery path
+                * so simply return an error and let the caller take
+                * care of the situation.
+                */
+               pon_handlers[level](node);
+       }
+}
+
+/*******************************************************************************
+ * Generic handler which is called when a cpu is physically powered on. It
+ * traverses through all the affinity levels performing generic, architectural,
+ * platform setup and state management e.g. for a cluster that's been powered
+ * on, it will call the platform specific code which will enable coherency at
+ * the interconnect level. For a cpu it could mean turning on the MMU etc.
+ *
+ * The state of all the relevant affinity levels is changed after calling the
+ * affinity level specific handlers as their actions would depend upon the state
+ * the affinity level is exiting from.
+ *
+ * The affinity level specific handlers are called in descending order i.e. from
+ * the highest to the lowest affinity level implemented by the platform because
+ * to turn on affinity level X it is neccesary to turn on affinity level X + 1
+ * first.
+ ******************************************************************************/
+void psci_afflvl_power_on_finish(int start_afflvl,
+                                int end_afflvl,
+                                afflvl_power_on_finisher_t *pon_handlers)
+{
+       mpidr_aff_map_nodes_t mpidr_nodes;
+       int rc;
+       unsigned int max_phys_off_afflvl;
+
+
+       /*
+        * Collect the pointers to the nodes in the topology tree for
+        * each affinity instance in the mpidr. If this function does
+        * not return successfully then either the mpidr or the affinity
+        * levels are incorrect. Either case is an irrecoverable error.
+        */
+       rc = psci_get_aff_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
+                                   start_afflvl,
+                                   end_afflvl,
+                                   mpidr_nodes);
+       if (rc != PSCI_E_SUCCESS)
+               panic();
+
+       /*
+        * This function acquires the lock corresponding to each affinity
+        * level so that by the time all locks are taken, the system topology
+        * is snapshot and state management can be done safely.
+        */
+       psci_acquire_afflvl_locks(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes);
+
+       max_phys_off_afflvl = psci_find_max_phys_off_afflvl(start_afflvl,
+                                                           end_afflvl,
+                                                           mpidr_nodes);
+       assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
+
+       /*
+        * Stash the highest affinity level that will come out of the OFF or
+        * SUSPEND states.
+        */
+       psci_set_max_phys_off_afflvl(max_phys_off_afflvl);
+
+       /* Perform generic, architecture and platform specific handling */
+       psci_call_power_on_handlers(mpidr_nodes,
+                                        start_afflvl,
+                                        end_afflvl,
+                                        pon_handlers);
+
+       /*
+        * This function updates the state of each affinity instance
+        * corresponding to the mpidr in the range of affinity levels
+        * specified.
+        */
+       psci_do_afflvl_state_mgmt(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes,
+                                 PSCI_STATE_ON);
+
+       /*
+        * Invalidate the entry for the highest affinity level stashed earlier.
+        * This ensures that any reads of this variable outside the power
+        * up/down sequences return PSCI_INVALID_DATA
+        */
+       psci_set_max_phys_off_afflvl(PSCI_INVALID_DATA);
+
+       /*
+        * This loop releases the lock corresponding to each affinity level
+        * in the reverse order to which they were acquired.
+        */
+       psci_release_afflvl_locks(start_afflvl,
+                                 end_afflvl,
+                                 mpidr_nodes);
+}
+
+/*******************************************************************************
+ * This function initializes the set of hooks that PSCI invokes as part of power
+ * management operation. The power management hooks are expected to be provided
+ * by the SPD, after it finishes all its initialization
+ ******************************************************************************/
+void psci_register_spd_pm_hook(const spd_pm_ops_t *pm)
+{
+       assert(pm);
+       psci_spd_pm = pm;
+
+       if (pm->svc_migrate)
+               psci_caps |= define_psci_cap(PSCI_MIG_AARCH64);
+
+       if (pm->svc_migrate_info)
+               psci_caps |= define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64)
+                               | define_psci_cap(PSCI_MIG_INFO_TYPE);
+}
+
+/*******************************************************************************
+ * This function invokes the migrate info hook in the spd_pm_ops. It performs
+ * the necessary return value validation. If the Secure Payload is UP and
+ * migrate capable, it returns the mpidr of the CPU on which the Secure payload
+ * is resident through the mpidr parameter. Else the value of the parameter on
+ * return is undefined.
+ ******************************************************************************/
+int psci_spd_migrate_info(uint64_t *mpidr)
+{
+       int rc;
+
+       if (!psci_spd_pm || !psci_spd_pm->svc_migrate_info)
+               return PSCI_E_NOT_SUPPORTED;
+
+       rc = psci_spd_pm->svc_migrate_info(mpidr);
+
+       assert(rc == PSCI_TOS_UP_MIG_CAP || rc == PSCI_TOS_NOT_UP_MIG_CAP \
+               || rc == PSCI_TOS_NOT_PRESENT_MP || rc == PSCI_E_NOT_SUPPORTED);
+
+       return rc;
+}
+
+
+/*******************************************************************************
+ * This function prints the state of all affinity instances present in the
+ * system
+ ******************************************************************************/
+void psci_print_affinity_map(void)
+{
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+       aff_map_node_t *node;
+       unsigned int idx;
+       /* This array maps to the PSCI_STATE_X definitions in psci.h */
+       static const char *psci_state_str[] = {
+               "ON",
+               "OFF",
+               "ON_PENDING",
+               "SUSPEND"
+       };
+
+       INFO("PSCI Affinity Map:\n");
+       for (idx = 0; idx < PSCI_NUM_AFFS ; idx++) {
+               node = &psci_aff_map[idx];
+               if (!(node->state & PSCI_AFF_PRESENT)) {
+                       continue;
+               }
+               INFO("  AffInst: Level %u, MPID 0x%lx, State %s\n",
+                               node->level, node->mpidr,
+                               psci_state_str[psci_get_state(node)]);
+       }
+#endif
+}
diff --git a/services/std_svc/psci/psci_entry.S b/services/std_svc/psci/psci_entry.S
new file mode 100644 (file)
index 0000000..3e67d34
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <psci.h>
+#include <xlat_tables.h>
+
+       .globl  psci_aff_on_finish_entry
+       .globl  psci_aff_suspend_finish_entry
+       .globl  psci_power_down_wfi
+
+       /* -----------------------------------------------------
+        * This cpu has been physically powered up. Depending
+        * upon whether it was resumed from suspend or simply
+        * turned on, call the common power on finisher with
+        * the handlers (chosen depending upon original state).
+        * -----------------------------------------------------
+        */
+func psci_aff_on_finish_entry
+       adr     x23, psci_afflvl_on_finishers
+       b       psci_aff_common_finish_entry
+
+psci_aff_suspend_finish_entry:
+       adr     x23, psci_afflvl_suspend_finishers
+
+psci_aff_common_finish_entry:
+#if !RESET_TO_BL31
+       /* ---------------------------------------------
+        * Perform any processor specific actions which
+        * undo or are in addition to the actions
+        * performed by the reset handler in the BootROM
+        * (BL1) e.g. cache, tlb invalidations, errata
+        * workarounds etc.
+        * ---------------------------------------------
+        */
+       bl      reset_handler
+
+       /* ---------------------------------------------
+        * Enable the instruction cache, stack pointer
+        * and data access alignment checks.
+        * It can be assumed that BL3-1 entrypoint code
+        * will do this when RESET_TO_BL31 is set. The
+        * same  assumption cannot be made when another
+        * boot loader executes before BL3-1 in the warm
+        * boot path e.g. BL1.
+        * ---------------------------------------------
+        */
+       mov     x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
+       mrs     x0, sctlr_el3
+       orr     x0, x0, x1
+       msr     sctlr_el3, x0
+       isb
+#endif
+
+       /* ---------------------------------------------
+        * Initialise the pcpu cache pointer for the CPU
+        * ---------------------------------------------
+        */
+       bl      init_cpu_data_ptr
+
+       /* ---------------------------------------------
+        * Initialize the cpu_ops pointer.
+        * ---------------------------------------------
+        */
+       bl      init_cpu_ops
+
+       /* ---------------------------------------------
+        * Set the exception vectors
+        * ---------------------------------------------
+        */
+       adr     x0, runtime_exceptions
+       msr     vbar_el3, x0
+       isb
+
+       /* ---------------------------------------------
+        * Enable the SError interrupt now that the
+        * exception vectors have been setup.
+        * ---------------------------------------------
+        */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       /* ---------------------------------------------
+        * Use SP_EL0 for the C runtime stack.
+        * ---------------------------------------------
+        */
+       msr     spsel, #0
+
+       /* --------------------------------------------
+        * Give ourselves a stack whose memory will be
+        * marked as Normal-IS-WBWA when the MMU is
+        * enabled.
+        * --------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_set_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      bl31_plat_enable_mmu
+
+       /* ---------------------------------------------
+        * Call the finishers starting from affinity
+        * level 0.
+        * ---------------------------------------------
+        */
+       bl      get_power_on_target_afflvl
+       mov     x2, x23
+       mov     x1, x0
+       mov     x0, #MPIDR_AFFLVL0
+       bl      psci_afflvl_power_on_finish
+
+       b       el3_exit
+
+       /* --------------------------------------------
+        * This function is called to indicate to the
+        * power controller that it is safe to power
+        * down this cpu. It should not exit the wfi
+        * and will be released from reset upon power
+        * up. 'wfi_spill' is used to catch erroneous
+        * exits from wfi.
+        * --------------------------------------------
+        */
+func psci_power_down_wfi
+       dsb     sy              // ensure write buffer empty
+       wfi
+wfi_spill:
+       b       wfi_spill
+
diff --git a/services/std_svc/psci/psci_helpers.S b/services/std_svc/psci/psci_helpers.S
new file mode 100644 (file)
index 0000000..9a51d5c
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <platform_def.h>
+#include <psci.h>
+
+       .globl  psci_do_pwrdown_cache_maintenance
+       .globl  psci_do_pwrup_cache_maintenance
+
+/* -----------------------------------------------------------------------
+ * void psci_do_pwrdown_cache_maintenance(uint32_t affinity level);
+ *
+ * This function performs cache maintenance if the specified affinity
+ * level is the equal to the level of the highest affinity instance which
+ * will be/is physically powered off. The levels of cache affected are
+ * determined by the affinity level which is passed as the argument i.e.
+ * level 0 results in a flush of the L1 cache. Both the L1 and L2 caches
+ * are flushed for a higher affinity level.
+ *
+ * Additionally, this function also ensures that stack memory is correctly
+ * flushed out to avoid coherency issues due to a change in its memory
+ * attributes after the data cache is disabled.
+ * -----------------------------------------------------------------------
+ */
+func psci_do_pwrdown_cache_maintenance
+       stp     x29, x30, [sp,#-16]!
+       stp     x19, x20, [sp,#-16]!
+
+       mov     x19, x0
+       bl      psci_get_max_phys_off_afflvl
+#if ASM_ASSERTION
+       cmp     x0, #PSCI_INVALID_DATA
+       ASM_ASSERT(ne)
+#endif
+       cmp     x0, x19
+       b.ne    1f
+
+       /* ---------------------------------------------
+        * Determine to how many levels of cache will be
+        * subject to cache maintenance. Affinity level
+        * 0 implies that only the cpu is being powered
+        * down. Only the L1 data cache needs to be
+        * flushed to the PoU in this case. For a higher
+        * affinity level we are assuming that a flush
+        * of L1 data and L2 unified cache is enough.
+        * This information should be provided by the
+        * platform.
+        * ---------------------------------------------
+        */
+       cmp     x0, #MPIDR_AFFLVL0
+       b.eq    do_core_pwr_dwn
+       bl      prepare_cluster_pwr_dwn
+       b       do_stack_maintenance
+
+do_core_pwr_dwn:
+       bl      prepare_core_pwr_dwn
+
+       /* ---------------------------------------------
+        * Do stack maintenance by flushing the used
+        * stack to the main memory and invalidating the
+        * remainder.
+        * ---------------------------------------------
+        */
+do_stack_maintenance:
+       mrs     x0, mpidr_el1
+       bl      platform_get_stack
+
+       /* ---------------------------------------------
+        * Calculate and store the size of the used
+        * stack memory in x1.
+        * ---------------------------------------------
+        */
+       mov     x19, x0
+       mov     x1, sp
+       sub     x1, x0, x1
+       mov     x0, sp
+       bl      flush_dcache_range
+
+       /* ---------------------------------------------
+        * Calculate and store the size of the unused
+        * stack memory in x1. Calculate and store the
+        * stack base address in x0.
+        * ---------------------------------------------
+        */
+       sub     x0, x19, #PLATFORM_STACK_SIZE
+       sub     x1, sp, x0
+       bl      inv_dcache_range
+
+1:
+       ldp     x19, x20, [sp], #16
+       ldp     x29, x30, [sp], #16
+       ret
+
+
+/* -----------------------------------------------------------------------
+ * void psci_do_pwrup_cache_maintenance(void);
+ *
+ * This function performs cache maintenance after this cpu is powered up.
+ * Currently, this involves managing the used stack memory before turning
+ * on the data cache.
+ * -----------------------------------------------------------------------
+ */
+func psci_do_pwrup_cache_maintenance
+       stp     x29, x30, [sp,#-16]!
+
+       /* ---------------------------------------------
+        * Ensure any inflight stack writes have made it
+        * to main memory.
+        * ---------------------------------------------
+        */
+       dmb     st
+
+       /* ---------------------------------------------
+        * Calculate and store the size of the used
+        * stack memory in x1. Calculate and store the
+        * stack base address in x0.
+        * ---------------------------------------------
+        */
+       mrs     x0, mpidr_el1
+       bl      platform_get_stack
+       mov     x1, sp
+       sub     x1, x0, x1
+       mov     x0, sp
+       bl      inv_dcache_range
+
+       /* ---------------------------------------------
+        * Enable the data cache.
+        * ---------------------------------------------
+        */
+       mrs     x0, sctlr_el3
+       orr     x0, x0, #SCTLR_C_BIT
+       msr     sctlr_el3, x0
+       isb
+
+       ldp     x29, x30, [sp], #16
+       ret
diff --git a/services/std_svc/psci/psci_main.c b/services/std_svc/psci/psci_main.c
new file mode 100644 (file)
index 0000000..52d252c
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <platform.h>
+#include <runtime_svc.h>
+#include <std_svc.h>
+#include "psci_private.h"
+
+/*******************************************************************************
+ * PSCI frontend api for servicing SMCs. Described in the PSCI spec.
+ ******************************************************************************/
+int psci_cpu_on(unsigned long target_cpu,
+               unsigned long entrypoint,
+               unsigned long context_id)
+
+{
+       int rc;
+       unsigned int start_afflvl, end_afflvl;
+       entry_point_info_t ep;
+
+       /* Determine if the cpu exists of not */
+       rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0);
+       if (rc != PSCI_E_SUCCESS) {
+               return PSCI_E_INVALID_PARAMS;
+       }
+
+       /* Validate the entrypoint using platform pm_ops */
+       if (psci_plat_pm_ops->validate_ns_entrypoint) {
+               rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint);
+               if (rc != PSCI_E_SUCCESS) {
+                       assert(rc == PSCI_E_INVALID_PARAMS);
+                       return PSCI_E_INVALID_PARAMS;
+               }
+       }
+
+       /*
+        * Verify and derive the re-entry information for
+        * the non-secure world from the non-secure state from
+        * where this call originated.
+        */
+       rc = psci_get_ns_ep_info(&ep, entrypoint, context_id);
+       if (rc != PSCI_E_SUCCESS)
+               return rc;
+
+
+       /*
+        * To turn this cpu on, specify which affinity
+        * levels need to be turned on
+        */
+       start_afflvl = MPIDR_AFFLVL0;
+       end_afflvl = get_max_afflvl();
+       rc = psci_afflvl_on(target_cpu,
+                           &ep,
+                           start_afflvl,
+                           end_afflvl);
+
+       return rc;
+}
+
+unsigned int psci_version(void)
+{
+       return PSCI_MAJOR_VER | PSCI_MINOR_VER;
+}
+
+int psci_cpu_suspend(unsigned int power_state,
+                    unsigned long entrypoint,
+                    unsigned long context_id)
+{
+       int rc;
+       unsigned int target_afflvl, pstate_type;
+       entry_point_info_t ep;
+
+       /* Check SBZ bits in power state are zero */
+       if (psci_validate_power_state(power_state))
+               return PSCI_E_INVALID_PARAMS;
+
+       /* Sanity check the requested state */
+       target_afflvl = psci_get_pstate_afflvl(power_state);
+       if (target_afflvl > get_max_afflvl())
+               return PSCI_E_INVALID_PARAMS;
+
+       /* Validate the power_state using platform pm_ops */
+       if (psci_plat_pm_ops->validate_power_state) {
+               rc = psci_plat_pm_ops->validate_power_state(power_state);
+               if (rc != PSCI_E_SUCCESS) {
+                       assert(rc == PSCI_E_INVALID_PARAMS);
+                       return PSCI_E_INVALID_PARAMS;
+               }
+       }
+
+       /* Validate the entrypoint using platform pm_ops */
+       if (psci_plat_pm_ops->validate_ns_entrypoint) {
+               rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint);
+               if (rc != PSCI_E_SUCCESS) {
+                       assert(rc == PSCI_E_INVALID_PARAMS);
+                       return PSCI_E_INVALID_PARAMS;
+               }
+       }
+
+       /* Determine the 'state type' in the 'power_state' parameter */
+       pstate_type = psci_get_pstate_type(power_state);
+
+       /*
+        * Ensure that we have a platform specific handler for entering
+        * a standby state.
+        */
+       if (pstate_type == PSTATE_TYPE_STANDBY) {
+               if  (!psci_plat_pm_ops->affinst_standby)
+                       return PSCI_E_INVALID_PARAMS;
+
+               psci_plat_pm_ops->affinst_standby(power_state);
+               return PSCI_E_SUCCESS;
+       }
+
+       /*
+        * Verify and derive the re-entry information for
+        * the non-secure world from the non-secure state from
+        * where this call originated.
+        */
+       rc = psci_get_ns_ep_info(&ep, entrypoint, context_id);
+       if (rc != PSCI_E_SUCCESS)
+               return rc;
+
+       /* Save PSCI power state parameter for the core in suspend context */
+       psci_set_suspend_power_state(power_state);
+
+       /*
+        * Do what is needed to enter the power down state. Upon success,
+        * enter the final wfi which will power down this CPU.
+        */
+       psci_afflvl_suspend(&ep,
+                           MPIDR_AFFLVL0,
+                           target_afflvl);
+
+       /* Reset PSCI power state parameter for the core. */
+       psci_set_suspend_power_state(PSCI_INVALID_DATA);
+       return PSCI_E_SUCCESS;
+}
+
+int psci_system_suspend(unsigned long entrypoint,
+                       unsigned long context_id)
+{
+       int rc;
+       unsigned int power_state;
+       entry_point_info_t ep;
+
+       /* Validate the entrypoint using platform pm_ops */
+       if (psci_plat_pm_ops->validate_ns_entrypoint) {
+               rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint);
+               if (rc != PSCI_E_SUCCESS) {
+                       assert(rc == PSCI_E_INVALID_PARAMS);
+                       return PSCI_E_INVALID_PARAMS;
+               }
+       }
+
+       /* Check if the current CPU is the last ON CPU in the system */
+       if (!psci_is_last_on_cpu())
+               return PSCI_E_DENIED;
+
+       /*
+        * Verify and derive the re-entry information for
+        * the non-secure world from the non-secure state from
+        * where this call originated.
+        */
+       rc = psci_get_ns_ep_info(&ep, entrypoint, context_id);
+       if (rc != PSCI_E_SUCCESS)
+               return rc;
+
+       /*
+        * Assert that the required pm_ops hook is implemented to ensure that
+        * the capability detected during psci_setup() is valid.
+        */
+       assert(psci_plat_pm_ops->get_sys_suspend_power_state);
+
+       /*
+        * Query the platform for the power_state required for system suspend
+        */
+       power_state = psci_plat_pm_ops->get_sys_suspend_power_state();
+
+       /* Save PSCI power state parameter for the core in suspend context */
+       psci_set_suspend_power_state(power_state);
+
+       /*
+        * Do what is needed to enter the power down state. Upon success,
+        * enter the final wfi which will power down this cpu.
+        */
+       psci_afflvl_suspend(&ep,
+                           MPIDR_AFFLVL0,
+                           PLATFORM_MAX_AFFLVL);
+
+       /* Reset PSCI power state parameter for the core. */
+       psci_set_suspend_power_state(PSCI_INVALID_DATA);
+       return PSCI_E_SUCCESS;
+}
+
+int psci_cpu_off(void)
+{
+       int rc;
+       int target_afflvl = get_max_afflvl();
+
+       /*
+        * Traverse from the highest to the lowest affinity level. When the
+        * lowest affinity level is hit, all the locks are acquired. State
+        * management is done immediately followed by cpu, cluster ...
+        * ..target_afflvl specific actions as this function unwinds back.
+        */
+       rc = psci_afflvl_off(MPIDR_AFFLVL0, target_afflvl);
+
+       /*
+        * The only error cpu_off can return is E_DENIED. So check if that's
+        * indeed the case.
+        */
+       assert (rc == PSCI_E_DENIED);
+
+       return rc;
+}
+
+int psci_affinity_info(unsigned long target_affinity,
+                      unsigned int lowest_affinity_level)
+{
+       int rc = PSCI_E_INVALID_PARAMS;
+       unsigned int aff_state;
+       aff_map_node_t *node;
+
+       if (lowest_affinity_level > get_max_afflvl())
+               return rc;
+
+       node = psci_get_aff_map_node(target_affinity, lowest_affinity_level);
+       if (node && (node->state & PSCI_AFF_PRESENT)) {
+
+               /*
+                * TODO: For affinity levels higher than 0 i.e. cpu, the
+                * state will always be either ON or OFF. Need to investigate
+                * how critical is it to support ON_PENDING here.
+                */
+               aff_state = psci_get_state(node);
+
+               /* A suspended cpu is available & on for the OS */
+               if (aff_state == PSCI_STATE_SUSPEND) {
+                       aff_state = PSCI_STATE_ON;
+               }
+
+               rc = aff_state;
+       }
+
+       return rc;
+}
+
+int psci_migrate(unsigned long target_cpu)
+{
+       int rc;
+       unsigned long resident_cpu_mpidr;
+
+       rc = psci_spd_migrate_info(&resident_cpu_mpidr);
+       if (rc != PSCI_TOS_UP_MIG_CAP)
+               return (rc == PSCI_TOS_NOT_UP_MIG_CAP) ?
+                         PSCI_E_DENIED : PSCI_E_NOT_SUPPORTED;
+
+       /*
+        * Migrate should only be invoked on the CPU where
+        * the Secure OS is resident.
+        */
+       if (resident_cpu_mpidr != read_mpidr_el1())
+               return PSCI_E_NOT_PRESENT;
+
+       /* Check the validity of the specified target cpu */
+       rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0);
+       if (rc != PSCI_E_SUCCESS)
+               return PSCI_E_INVALID_PARAMS;
+
+       assert(psci_spd_pm && psci_spd_pm->svc_migrate);
+
+       rc = psci_spd_pm->svc_migrate(read_mpidr_el1(), target_cpu);
+       assert(rc == PSCI_E_SUCCESS || rc == PSCI_E_INTERN_FAIL);
+
+       return rc;
+}
+
+int psci_migrate_info_type(void)
+{
+       unsigned long resident_cpu_mpidr;
+
+       return psci_spd_migrate_info(&resident_cpu_mpidr);
+}
+
+long psci_migrate_info_up_cpu(void)
+{
+       unsigned long resident_cpu_mpidr;
+       int rc;
+
+       /*
+        * Return value of this depends upon what
+        * psci_spd_migrate_info() returns.
+        */
+       rc = psci_spd_migrate_info(&resident_cpu_mpidr);
+       if (rc != PSCI_TOS_NOT_UP_MIG_CAP && rc != PSCI_TOS_UP_MIG_CAP)
+               return PSCI_E_INVALID_PARAMS;
+
+       return resident_cpu_mpidr;
+}
+
+int psci_features(unsigned int psci_fid)
+{
+       uint32_t local_caps = psci_caps;
+
+       /* Check if it is a 64 bit function */
+       if (((psci_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64)
+               local_caps &= PSCI_CAP_64BIT_MASK;
+
+       /* Check for invalid fid */
+       if (!(is_std_svc_call(psci_fid) && is_valid_fast_smc(psci_fid)
+                       && is_psci_fid(psci_fid)))
+               return PSCI_E_NOT_SUPPORTED;
+
+
+       /* Check if the psci fid is supported or not */
+       if (!(local_caps & define_psci_cap(psci_fid)))
+               return PSCI_E_NOT_SUPPORTED;
+
+       /* Format the feature flags */
+       if (psci_fid == PSCI_CPU_SUSPEND_AARCH32 ||
+                       psci_fid == PSCI_CPU_SUSPEND_AARCH64) {
+               /*
+                * The trusted firmware uses the original power state format
+                * and does not support OS Initiated Mode.
+                */
+               return (FF_PSTATE_ORIG << FF_PSTATE_SHIFT) |
+                       ((!FF_SUPPORTS_OS_INIT_MODE) << FF_MODE_SUPPORT_SHIFT);
+       }
+
+       /* Return 0 for all other fid's */
+       return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * PSCI top level handler for servicing SMCs.
+ ******************************************************************************/
+uint64_t psci_smc_handler(uint32_t smc_fid,
+                         uint64_t x1,
+                         uint64_t x2,
+                         uint64_t x3,
+                         uint64_t x4,
+                         void *cookie,
+                         void *handle,
+                         uint64_t flags)
+{
+       if (is_caller_secure(flags))
+               SMC_RET1(handle, SMC_UNK);
+
+       /* Check the fid against the capabilities */
+       if (!(psci_caps & define_psci_cap(smc_fid)))
+               SMC_RET1(handle, SMC_UNK);
+
+       if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) {
+               /* 32-bit PSCI function, clear top parameter bits */
+
+               x1 = (uint32_t)x1;
+               x2 = (uint32_t)x2;
+               x3 = (uint32_t)x3;
+
+               switch (smc_fid) {
+               case PSCI_VERSION:
+                       SMC_RET1(handle, psci_version());
+
+               case PSCI_CPU_OFF:
+                       SMC_RET1(handle, psci_cpu_off());
+
+               case PSCI_CPU_SUSPEND_AARCH32:
+                       SMC_RET1(handle, psci_cpu_suspend(x1, x2, x3));
+
+               case PSCI_CPU_ON_AARCH32:
+                       SMC_RET1(handle, psci_cpu_on(x1, x2, x3));
+
+               case PSCI_AFFINITY_INFO_AARCH32:
+                       SMC_RET1(handle, psci_affinity_info(x1, x2));
+
+               case PSCI_MIG_AARCH32:
+                       SMC_RET1(handle, psci_migrate(x1));
+
+               case PSCI_MIG_INFO_TYPE:
+                       SMC_RET1(handle, psci_migrate_info_type());
+
+               case PSCI_MIG_INFO_UP_CPU_AARCH32:
+                       SMC_RET1(handle, psci_migrate_info_up_cpu());
+
+               case PSCI_SYSTEM_SUSPEND_AARCH32:
+                       SMC_RET1(handle, psci_system_suspend(x1, x2));
+
+               case PSCI_SYSTEM_OFF:
+                       psci_system_off();
+                       /* We should never return from psci_system_off() */
+
+               case PSCI_SYSTEM_RESET:
+                       psci_system_reset();
+                       /* We should never return from psci_system_reset() */
+
+               case PSCI_FEATURES:
+                       SMC_RET1(handle, psci_features(x1));
+
+               default:
+                       break;
+               }
+       } else {
+               /* 64-bit PSCI function */
+
+               switch (smc_fid) {
+               case PSCI_CPU_SUSPEND_AARCH64:
+                       SMC_RET1(handle, psci_cpu_suspend(x1, x2, x3));
+
+               case PSCI_CPU_ON_AARCH64:
+                       SMC_RET1(handle, psci_cpu_on(x1, x2, x3));
+
+               case PSCI_AFFINITY_INFO_AARCH64:
+                       SMC_RET1(handle, psci_affinity_info(x1, x2));
+
+               case PSCI_MIG_AARCH64:
+                       SMC_RET1(handle, psci_migrate(x1));
+
+               case PSCI_MIG_INFO_UP_CPU_AARCH64:
+                       SMC_RET1(handle, psci_migrate_info_up_cpu());
+
+               case PSCI_SYSTEM_SUSPEND_AARCH64:
+                       SMC_RET1(handle, psci_system_suspend(x1, x2));
+
+               default:
+                       break;
+               }
+       }
+
+       WARN("Unimplemented PSCI Call: 0x%x \n", smc_fid);
+       SMC_RET1(handle, SMC_UNK);
+}
diff --git a/services/std_svc/psci/psci_private.h b/services/std_svc/psci/psci_private.h
new file mode 100644 (file)
index 0000000..f23ed8a
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PSCI_PRIVATE_H__
+#define __PSCI_PRIVATE_H__
+
+#include <arch.h>
+#include <bakery_lock.h>
+#include <bl_common.h>
+#include <psci.h>
+
+/*
+ * The following helper macros abstract the interface to the Bakery
+ * Lock API.
+ */
+#if USE_COHERENT_MEM
+#define psci_lock_init(aff_map, idx)   bakery_lock_init(&(aff_map)[(idx)].lock)
+#define psci_lock_get(node)            bakery_lock_get(&((node)->lock))
+#define psci_lock_release(node)                bakery_lock_release(&((node)->lock))
+#else
+#define psci_lock_init(aff_map, idx)   ((aff_map)[(idx)].aff_map_index = (idx))
+#define psci_lock_get(node)            bakery_lock_get((node)->aff_map_index,    \
+                                               CPU_DATA_PSCI_LOCK_OFFSET)
+#define psci_lock_release(node)                bakery_lock_release((node)->aff_map_index,\
+                                               CPU_DATA_PSCI_LOCK_OFFSET)
+#endif
+
+/*
+ * The PSCI capability which are provided by the generic code but does not
+ * depend on the platform or spd capabilities.
+ */
+#define PSCI_GENERIC_CAP       \
+                       (define_psci_cap(PSCI_VERSION) |                \
+                       define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) |   \
+                       define_psci_cap(PSCI_FEATURES))
+
+/*
+ * The PSCI capabilities mask for 64 bit functions.
+ */
+#define PSCI_CAP_64BIT_MASK    \
+                       (define_psci_cap(PSCI_CPU_SUSPEND_AARCH64) |    \
+                       define_psci_cap(PSCI_CPU_ON_AARCH64) |          \
+                       define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) |   \
+                       define_psci_cap(PSCI_MIG_AARCH64) |             \
+                       define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) | \
+                       define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64))
+
+
+/*******************************************************************************
+ * The following two data structures hold the topology tree which in turn tracks
+ * the state of the all the affinity instances supported by the platform.
+ ******************************************************************************/
+typedef struct aff_map_node {
+       unsigned long mpidr;
+       unsigned char ref_count;
+       unsigned char state;
+       unsigned char level;
+#if USE_COHERENT_MEM
+       bakery_lock_t lock;
+#else
+       /* For indexing the bakery_info array in per CPU data */
+       unsigned char aff_map_index;
+#endif
+} aff_map_node_t;
+
+typedef struct aff_limits_node {
+       int min;
+       int max;
+} aff_limits_node_t;
+
+typedef aff_map_node_t (*mpidr_aff_map_nodes_t[MPIDR_MAX_AFFLVL + 1]);
+typedef void (*afflvl_power_on_finisher_t)(aff_map_node_t *);
+
+/*******************************************************************************
+ * Data prototypes
+ ******************************************************************************/
+extern const plat_pm_ops_t *psci_plat_pm_ops;
+extern aff_map_node_t psci_aff_map[PSCI_NUM_AFFS];
+extern aff_limits_node_t psci_aff_limits[MPIDR_MAX_AFFLVL + 1];
+extern uint32_t psci_caps;
+
+/*******************************************************************************
+ * SPD's power management hooks registered with PSCI
+ ******************************************************************************/
+extern const spd_pm_ops_t *psci_spd_pm;
+
+/*******************************************************************************
+ * Function prototypes
+ ******************************************************************************/
+/* Private exported functions from psci_common.c */
+int get_max_afflvl(void);
+unsigned short psci_get_state(aff_map_node_t *node);
+unsigned short psci_get_phys_state(aff_map_node_t *node);
+void psci_set_state(aff_map_node_t *node, unsigned short state);
+unsigned long mpidr_set_aff_inst(unsigned long, unsigned char, int);
+int psci_validate_mpidr(unsigned long, int);
+int get_power_on_target_afflvl(void);
+void psci_afflvl_power_on_finish(int,
+                               int,
+                               afflvl_power_on_finisher_t *);
+int psci_get_ns_ep_info(entry_point_info_t *ep,
+                      uint64_t entrypoint, uint64_t context_id);
+int psci_check_afflvl_range(int start_afflvl, int end_afflvl);
+void psci_do_afflvl_state_mgmt(uint32_t start_afflvl,
+                              uint32_t end_afflvl,
+                              aff_map_node_t *mpidr_nodes[],
+                              uint32_t state);
+void psci_acquire_afflvl_locks(int start_afflvl,
+                              int end_afflvl,
+                              aff_map_node_t *mpidr_nodes[]);
+void psci_release_afflvl_locks(int start_afflvl,
+                               int end_afflvl,
+                               mpidr_aff_map_nodes_t mpidr_nodes);
+void psci_print_affinity_map(void);
+void psci_set_max_phys_off_afflvl(uint32_t afflvl);
+uint32_t psci_find_max_phys_off_afflvl(uint32_t start_afflvl,
+                                      uint32_t end_afflvl,
+                                      aff_map_node_t *mpidr_nodes[]);
+unsigned int psci_is_last_on_cpu(void);
+int psci_spd_migrate_info(uint64_t *mpidr);
+
+/* Private exported functions from psci_setup.c */
+int psci_get_aff_map_nodes(unsigned long mpidr,
+                               int start_afflvl,
+                               int end_afflvl,
+                               aff_map_node_t *mpidr_nodes[]);
+aff_map_node_t *psci_get_aff_map_node(unsigned long, int);
+
+/* Private exported functions from psci_affinity_on.c */
+int psci_afflvl_on(unsigned long target_cpu,
+                  entry_point_info_t *ep,
+                  int start_afflvl,
+                  int end_afflvl);
+
+/* Private exported functions from psci_affinity_off.c */
+int psci_afflvl_off(int, int);
+
+/* Private exported functions from psci_affinity_suspend.c */
+void psci_afflvl_suspend(entry_point_info_t *ep,
+                       int start_afflvl,
+                       int end_afflvl);
+
+unsigned int psci_afflvl_suspend_finish(int, int);
+void psci_set_suspend_power_state(unsigned int power_state);
+
+/* Private exported functions from psci_helpers.S */
+void psci_do_pwrdown_cache_maintenance(uint32_t affinity_level);
+void psci_do_pwrup_cache_maintenance(void);
+
+/* Private exported functions from psci_system_off.c */
+void __dead2 psci_system_off(void);
+void __dead2 psci_system_reset(void);
+
+#endif /* __PSCI_PRIVATE_H__ */
diff --git a/services/std_svc/psci/psci_setup.c b/services/std_svc/psci/psci_setup.c
new file mode 100644 (file)
index 0000000..fbd76d0
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <platform.h>
+#include <stddef.h>
+#include "psci_private.h"
+
+/*******************************************************************************
+ * Per cpu non-secure contexts used to program the architectural state prior
+ * return to the normal world.
+ * TODO: Use the memory allocator to set aside memory for the contexts instead
+ * of relying on platform defined constants. Using PSCI_NUM_AFFS will be an
+ * overkill.
+ ******************************************************************************/
+static cpu_context_t psci_ns_context[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * In a system, a certain number of affinity instances are present at an
+ * affinity level. The cumulative number of instances across all levels are
+ * stored in 'psci_aff_map'. The topology tree has been flattenned into this
+ * array. To retrieve nodes, information about the extents of each affinity
+ * level i.e. start index and end index needs to be present. 'psci_aff_limits'
+ * stores this information.
+ ******************************************************************************/
+aff_limits_node_t psci_aff_limits[MPIDR_MAX_AFFLVL + 1];
+
+/******************************************************************************
+ * Define the psci capability variable.
+ *****************************************************************************/
+uint32_t psci_caps;
+
+
+/*******************************************************************************
+ * Routines for retrieving the node corresponding to an affinity level instance
+ * in the mpidr. The first one uses binary search to find the node corresponding
+ * to the mpidr (key) at a particular affinity level. The second routine decides
+ * extents of the binary search at each affinity level.
+ ******************************************************************************/
+static int psci_aff_map_get_idx(unsigned long key,
+                               int min_idx,
+                               int max_idx)
+{
+       int mid;
+
+       /*
+        * Terminating condition: If the max and min indices have crossed paths
+        * during the binary search then the key has not been found.
+        */
+       if (max_idx < min_idx)
+               return PSCI_E_INVALID_PARAMS;
+
+       /*
+        * Make sure we are within array limits.
+        */
+       assert(min_idx >= 0 && max_idx < PSCI_NUM_AFFS);
+
+       /*
+        * Bisect the array around 'mid' and then recurse into the array chunk
+        * where the key is likely to be found. The mpidrs in each node in the
+        * 'psci_aff_map' for a given affinity level are stored in an ascending
+        * order which makes the binary search possible.
+        */
+       mid = min_idx + ((max_idx - min_idx) >> 1);     /* Divide by 2 */
+
+       if (psci_aff_map[mid].mpidr > key)
+               return psci_aff_map_get_idx(key, min_idx, mid - 1);
+       else if (psci_aff_map[mid].mpidr < key)
+               return psci_aff_map_get_idx(key, mid + 1, max_idx);
+       else
+               return mid;
+}
+
+aff_map_node_t *psci_get_aff_map_node(unsigned long mpidr, int aff_lvl)
+{
+       int rc;
+
+       if (aff_lvl > get_max_afflvl())
+               return NULL;
+
+       /* Right shift the mpidr to the required affinity level */
+       mpidr = mpidr_mask_lower_afflvls(mpidr, aff_lvl);
+
+       rc = psci_aff_map_get_idx(mpidr,
+                                 psci_aff_limits[aff_lvl].min,
+                                 psci_aff_limits[aff_lvl].max);
+       if (rc >= 0)
+               return &psci_aff_map[rc];
+       else
+               return NULL;
+}
+
+/*******************************************************************************
+ * This function populates an array with nodes corresponding to a given range of
+ * affinity levels in an mpidr. It returns successfully only when the affinity
+ * levels are correct, the mpidr is valid i.e. no affinity level is absent from
+ * the topology tree & the affinity instance at level 0 is not absent.
+ ******************************************************************************/
+int psci_get_aff_map_nodes(unsigned long mpidr,
+                          int start_afflvl,
+                          int end_afflvl,
+                          aff_map_node_t *mpidr_nodes[])
+{
+       int rc = PSCI_E_INVALID_PARAMS, level;
+       aff_map_node_t *node;
+
+       rc = psci_check_afflvl_range(start_afflvl, end_afflvl);
+       if (rc != PSCI_E_SUCCESS)
+               return rc;
+
+       for (level = start_afflvl; level <= end_afflvl; level++) {
+
+               /*
+                * Grab the node for each affinity level. No affinity level
+                * can be missing as that would mean that the topology tree
+                * is corrupted.
+                */
+               node = psci_get_aff_map_node(mpidr, level);
+               if (node == NULL) {
+                       rc = PSCI_E_INVALID_PARAMS;
+                       break;
+               }
+
+               /*
+                * Skip absent affinity levels unless it's afffinity level 0.
+                * An absent cpu means that the mpidr is invalid. Save the
+                * pointer to the node for the present affinity level
+                */
+               if (!(node->state & PSCI_AFF_PRESENT)) {
+                       if (level == MPIDR_AFFLVL0) {
+                               rc = PSCI_E_INVALID_PARAMS;
+                               break;
+                       }
+
+                       mpidr_nodes[level] = NULL;
+               } else
+                       mpidr_nodes[level] = node;
+       }
+
+       return rc;
+}
+
+/*******************************************************************************
+ * Function which initializes the 'aff_map_node' corresponding to an affinity
+ * level instance. Each node has a unique mpidr, level and bakery lock. The data
+ * field is opaque and holds affinity level specific data e.g. for affinity
+ * level 0 it contains the index into arrays that hold the secure/non-secure
+ * state for a cpu that's been turned on/off
+ ******************************************************************************/
+static void psci_init_aff_map_node(unsigned long mpidr,
+                                  int level,
+                                  unsigned int idx)
+{
+       unsigned char state;
+       uint32_t linear_id;
+       psci_aff_map[idx].mpidr = mpidr;
+       psci_aff_map[idx].level = level;
+       psci_lock_init(psci_aff_map, idx);
+
+       /*
+        * If an affinity instance is present then mark it as OFF to begin with.
+        */
+       state = plat_get_aff_state(level, mpidr);
+       psci_aff_map[idx].state = state;
+
+       if (level == MPIDR_AFFLVL0) {
+
+               /*
+                * Mark the cpu as OFF. Higher affinity level reference counts
+                * have already been memset to 0
+                */
+               if (state & PSCI_AFF_PRESENT)
+                       psci_set_state(&psci_aff_map[idx], PSCI_STATE_OFF);
+
+               /*
+                * Associate a non-secure context with this affinity
+                * instance through the context management library.
+                */
+               linear_id = platform_get_core_pos(mpidr);
+               assert(linear_id < PLATFORM_CORE_COUNT);
+
+               /* Invalidate the suspend context for the node */
+               set_cpu_data_by_index(linear_id,
+                                     psci_svc_cpu_data.power_state,
+                                     PSCI_INVALID_DATA);
+
+               /*
+                * There is no state associated with the current execution
+                * context so ensure that any reads of the highest affinity
+                * level in a powered down state return PSCI_INVALID_DATA.
+                */
+               set_cpu_data_by_index(linear_id,
+                                     psci_svc_cpu_data.max_phys_off_afflvl,
+                                     PSCI_INVALID_DATA);
+
+               flush_cpu_data_by_index(linear_id, psci_svc_cpu_data);
+
+               cm_set_context_by_mpidr(mpidr,
+                                       (void *) &psci_ns_context[linear_id],
+                                       NON_SECURE);
+       }
+
+       return;
+}
+
+/*******************************************************************************
+ * Core routine used by the Breadth-First-Search algorithm to populate the
+ * affinity tree. Each level in the tree corresponds to an affinity level. This
+ * routine's aim is to traverse to the target affinity level and populate nodes
+ * in the 'psci_aff_map' for all the siblings at that level. It uses the current
+ * affinity level to keep track of how many levels from the root of the tree
+ * have been traversed. If the current affinity level != target affinity level,
+ * then the platform is asked to return the number of children that each
+ * affinity instance has at the current affinity level. Traversal is then done
+ * for each child at the next lower level i.e. current affinity level - 1.
+ *
+ * CAUTION: This routine assumes that affinity instance ids are allocated in a
+ * monotonically increasing manner at each affinity level in a mpidr starting
+ * from 0. If the platform breaks this assumption then this code will have to
+ * be reworked accordingly.
+ ******************************************************************************/
+static unsigned int psci_init_aff_map(unsigned long mpidr,
+                                     unsigned int affmap_idx,
+                                     int cur_afflvl,
+                                     int tgt_afflvl)
+{
+       unsigned int ctr, aff_count;
+
+       assert(cur_afflvl >= tgt_afflvl);
+
+       /*
+        * Find the number of siblings at the current affinity level &
+        * assert if there are none 'cause then we have been invoked with
+        * an invalid mpidr.
+        */
+       aff_count = plat_get_aff_count(cur_afflvl, mpidr);
+       assert(aff_count);
+
+       if (tgt_afflvl < cur_afflvl) {
+               for (ctr = 0; ctr < aff_count; ctr++) {
+                       mpidr = mpidr_set_aff_inst(mpidr, ctr, cur_afflvl);
+                       affmap_idx = psci_init_aff_map(mpidr,
+                                                      affmap_idx,
+                                                      cur_afflvl - 1,
+                                                      tgt_afflvl);
+               }
+       } else {
+               for (ctr = 0; ctr < aff_count; ctr++, affmap_idx++) {
+                       mpidr = mpidr_set_aff_inst(mpidr, ctr, cur_afflvl);
+                       psci_init_aff_map_node(mpidr, cur_afflvl, affmap_idx);
+               }
+
+               /* affmap_idx is 1 greater than the max index of cur_afflvl */
+               psci_aff_limits[cur_afflvl].max = affmap_idx - 1;
+       }
+
+       return affmap_idx;
+}
+
+/*******************************************************************************
+ * This function initializes the topology tree by querying the platform. To do
+ * so, it's helper routines implement a Breadth-First-Search. At each affinity
+ * level the platform conveys the number of affinity instances that exist i.e.
+ * the affinity count. The algorithm populates the psci_aff_map recursively
+ * using this information. On a platform that implements two clusters of 4 cpus
+ * each, the populated aff_map_array would look like this:
+ *
+ *            <- cpus cluster0 -><- cpus cluster1 ->
+ * ---------------------------------------------------
+ * | 0  | 1  | 0  | 1  | 2  | 3  | 0  | 1  | 2  | 3  |
+ * ---------------------------------------------------
+ *           ^                                       ^
+ * cluster __|                                 cpu __|
+ * limit                                      limit
+ *
+ * The first 2 entries are of the cluster nodes. The next 4 entries are of cpus
+ * within cluster 0. The last 4 entries are of cpus within cluster 1.
+ * The 'psci_aff_limits' array contains the max & min index of each affinity
+ * level within the 'psci_aff_map' array. This allows restricting search of a
+ * node at an affinity level between the indices in the limits array.
+ ******************************************************************************/
+int32_t psci_setup(void)
+{
+       unsigned long mpidr = read_mpidr();
+       int afflvl, affmap_idx, max_afflvl;
+       aff_map_node_t *node;
+
+       psci_plat_pm_ops = NULL;
+
+       /* Find out the maximum affinity level that the platform implements */
+       max_afflvl = get_max_afflvl();
+       assert(max_afflvl <= MPIDR_MAX_AFFLVL);
+
+       /*
+        * This call traverses the topology tree with help from the platform and
+        * populates the affinity map using a breadth-first-search recursively.
+        * We assume that the platform allocates affinity instance ids from 0
+        * onwards at each affinity level in the mpidr. FIRST_MPIDR = 0.0.0.0
+        */
+       affmap_idx = 0;
+       for (afflvl = max_afflvl; afflvl >= MPIDR_AFFLVL0; afflvl--) {
+               affmap_idx = psci_init_aff_map(FIRST_MPIDR,
+                                              affmap_idx,
+                                              max_afflvl,
+                                              afflvl);
+       }
+
+#if !USE_COHERENT_MEM
+       /*
+        * The psci_aff_map only needs flushing when it's not allocated in
+        * coherent memory.
+        */
+       flush_dcache_range((uint64_t) &psci_aff_map, sizeof(psci_aff_map));
+#endif
+
+       /*
+        * Set the bounds for the affinity counts of each level in the map. Also
+        * flush out the entire array so that it's visible to subsequent power
+        * management operations. The 'psci_aff_limits' array is allocated in
+        * normal memory. It will be accessed when the mmu is off e.g. after
+        * reset. Hence it needs to be flushed.
+        */
+       for (afflvl = MPIDR_AFFLVL0; afflvl < max_afflvl; afflvl++) {
+               psci_aff_limits[afflvl].min =
+                       psci_aff_limits[afflvl + 1].max + 1;
+       }
+
+       flush_dcache_range((unsigned long) psci_aff_limits,
+                          sizeof(psci_aff_limits));
+
+       /*
+        * Mark the affinity instances in our mpidr as ON. No need to lock as
+        * this is the primary cpu.
+        */
+       mpidr &= MPIDR_AFFINITY_MASK;
+       for (afflvl = MPIDR_AFFLVL0; afflvl <= max_afflvl; afflvl++) {
+
+               node = psci_get_aff_map_node(mpidr, afflvl);
+               assert(node);
+
+               /* Mark each present node as ON. */
+               if (node->state & PSCI_AFF_PRESENT)
+                       psci_set_state(node, PSCI_STATE_ON);
+       }
+
+       platform_setup_pm(&psci_plat_pm_ops);
+       assert(psci_plat_pm_ops);
+
+       /* Initialize the psci capability */
+       psci_caps = PSCI_GENERIC_CAP;
+
+       if (psci_plat_pm_ops->affinst_off)
+               psci_caps |=  define_psci_cap(PSCI_CPU_OFF);
+       if (psci_plat_pm_ops->affinst_on && psci_plat_pm_ops->affinst_on_finish)
+               psci_caps |=  define_psci_cap(PSCI_CPU_ON_AARCH64);
+       if (psci_plat_pm_ops->affinst_suspend &&
+                       psci_plat_pm_ops->affinst_suspend_finish) {
+               psci_caps |=  define_psci_cap(PSCI_CPU_SUSPEND_AARCH64);
+               if (psci_plat_pm_ops->get_sys_suspend_power_state)
+                       psci_caps |=  define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64);
+       }
+       if (psci_plat_pm_ops->system_off)
+               psci_caps |=  define_psci_cap(PSCI_SYSTEM_OFF);
+       if (psci_plat_pm_ops->system_reset)
+               psci_caps |=  define_psci_cap(PSCI_SYSTEM_RESET);
+
+       return 0;
+}
diff --git a/services/std_svc/psci/psci_system_off.c b/services/std_svc/psci/psci_system_off.c
new file mode 100644 (file)
index 0000000..970d4bb
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <platform.h>
+#include "psci_private.h"
+
+void psci_system_off(void)
+{
+       psci_print_affinity_map();
+
+       assert(psci_plat_pm_ops->system_off);
+
+       /* Notify the Secure Payload Dispatcher */
+       if (psci_spd_pm && psci_spd_pm->svc_system_off) {
+               psci_spd_pm->svc_system_off();
+       }
+
+       /* Call the platform specific hook */
+       psci_plat_pm_ops->system_off();
+
+       /* This function does not return. We should never get here */
+}
+
+void psci_system_reset(void)
+{
+       psci_print_affinity_map();
+
+       assert(psci_plat_pm_ops->system_reset);
+
+       /* Notify the Secure Payload Dispatcher */
+       if (psci_spd_pm && psci_spd_pm->svc_system_reset) {
+               psci_spd_pm->svc_system_reset();
+       }
+
+       /* Call the platform specific hook */
+       psci_plat_pm_ops->system_reset();
+
+       /* This function does not return. We should never get here */
+}
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
new file mode 100644 (file)
index 0000000..6cb0319
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <psci.h>
+#include <runtime_svc.h>
+#include <std_svc.h>
+#include <stdint.h>
+#include <uuid.h>
+
+/* Standard Service UUID */
+DEFINE_SVC_UUID(arm_svc_uid,
+               0x108d905b, 0xf863, 0x47e8, 0xae, 0x2d,
+               0xc0, 0xfb, 0x56, 0x41, 0xf6, 0xe2);
+
+/* Setup Standard Services */
+static int32_t std_svc_setup(void)
+{
+       /*
+        * PSCI is the only specification implemented as a Standard Service.
+        * Invoke PSCI setup from here
+        */
+       return psci_setup();
+}
+
+/*
+ * Top-level Standard Service SMC handler. This handler will in turn dispatch
+ * calls to PSCI SMC handler
+ */
+uint64_t std_svc_smc_handler(uint32_t smc_fid,
+                            uint64_t x1,
+                            uint64_t x2,
+                            uint64_t x3,
+                            uint64_t x4,
+                            void *cookie,
+                            void *handle,
+                            uint64_t flags)
+{
+       /*
+        * Dispatch PSCI calls to PSCI SMC handler and return its return
+        * value
+        */
+       if (is_psci_fid(smc_fid)) {
+               return psci_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+                               handle, flags);
+       }
+
+       switch (smc_fid) {
+       case ARM_STD_SVC_CALL_COUNT:
+               /*
+                * Return the number of Standard Service Calls. PSCI is the only
+                * standard service implemented; so return number of PSCI calls
+                */
+               SMC_RET1(handle, PSCI_NUM_CALLS);
+
+       case ARM_STD_SVC_UID:
+               /* Return UID to the caller */
+               SMC_UUID_RET(handle, arm_svc_uid);
+
+       case ARM_STD_SVC_VERSION:
+               /* Return the version of current implementation */
+               SMC_RET2(handle, STD_SVC_VERSION_MAJOR, STD_SVC_VERSION_MINOR);
+
+       default:
+               WARN("Unimplemented Standard Service Call: 0x%x \n", smc_fid);
+               SMC_RET1(handle, SMC_UNK);
+       }
+}
+
+/* Register Standard Service Calls as runtime service */
+DECLARE_RT_SVC(
+               std_svc,
+
+               OEN_STD_START,
+               OEN_STD_END,
+               SMC_TYPE_FAST,
+               std_svc_setup,
+               std_svc_smc_handler
+);
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
new file mode 100644 (file)
index 0000000..f1aa797
--- /dev/null
@@ -0,0 +1,92 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+PROJECT                := cert_create
+PLAT           := none
+V              := 0
+DEBUG          := 0
+BINARY         := ${PROJECT}
+
+OBJECTS := src/cert.o \
+           src/ext.o \
+           src/key.o \
+           src/main.o \
+           src/tbb_cert.o \
+           src/tbb_ext.o \
+           src/tbb_key.o \
+           src/sha.o
+
+CFLAGS := -Wall -std=c99
+
+# Check the platform
+ifeq (${PLAT},none)
+  $(error Error: No platform defined. Use PLAT=<platform>.)
+endif
+
+ifeq (${DEBUG},1)
+  CFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40
+else
+  CFLAGS += -O2 -DLOG_LEVEL=20
+endif
+ifeq (${V},0)
+       Q := @
+else
+       Q :=
+endif
+
+# Make soft links and include from local directory otherwise wrong headers
+# could get pulled in from firmware tree.
+INC_DIR := -I ./include -I ../../plat/${PLAT}/include
+LIB_DIR :=
+LIB := -lssl -lcrypto
+
+CC := gcc
+RM := rm -rf
+
+.PHONY: all clean
+
+all: clean ${BINARY}
+
+${BINARY}: ${OBJECTS} Makefile
+       @echo "  LD      $@"
+       @echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \
+                const char platform_msg[] = "${PLAT}";' | \
+                ${CC} -c ${CFLAGS} -xc - -o src/build_msg.o
+       ${Q}${CC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
+
+%.o: %.c
+       @echo "  CC      $<"
+       ${Q}${CC} -c ${CFLAGS} ${INC_DIR} $< -o $@
+
+clean:
+       ${Q}${RM} -f src/build_msg.o ${OBJECTS}
+
+realclean: clean
+       ${Q}${RM} -f ${BINARY}
diff --git a/tools/cert_create/include/cert.h b/tools/cert_create/include/cert.h
new file mode 100644 (file)
index 0000000..48a4146
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CERT_H_
+#define CERT_H_
+
+#include <openssl/ossl_typ.h>
+#include <openssl/x509.h>
+#include "key.h"
+
+/*
+ * This structure contains information related to the generation of the
+ * certificates. All these fields must be known and specified at build time
+ * except for the file name, which is picked up from the command line at
+ * run time.
+ *
+ * One instance of this structure must be created for each of the certificates
+ * present in the chain of trust.
+ *
+ * If the issuer points to this same instance, the generated certificate will
+ * be self-signed.
+ */
+typedef struct cert_s cert_t;
+struct cert_s {
+       int id;                 /* Unique identifier */
+
+       const char *fn;         /* Filename to save the certificate */
+       const char *bin;        /* Image associated to this certificate */
+
+       const char *cn;         /* Subject CN (Company Name) */
+
+       X509 *x;                /* X509 certificate container */
+       key_t *key;             /* Key to be signed */
+
+       cert_t *issuer;         /* Issuer certificate */
+};
+
+int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value);
+
+int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk);
+
+#endif /* CERT_H_ */
diff --git a/tools/cert_create/include/debug.h b/tools/cert_create/include/debug.h
new file mode 100644 (file)
index 0000000..dd0510a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#include <stdio.h>
+
+/* The log output macros print output to the console. These macros produce
+ * compiled log output only if the LOG_LEVEL defined in the makefile (or the
+ * make command line) is greater or equal than the level required for that
+ * type of log output.
+ * The format expected is the same as for printf(). For example:
+ * INFO("Info %s.\n", "message")    -> INFO:    Info message.
+ * WARN("Warning %s.\n", "message") -> WARNING: Warning message.
+ */
+
+#define LOG_LEVEL_NONE                 0
+#define LOG_LEVEL_ERROR                        10
+#define LOG_LEVEL_NOTICE               20
+#define LOG_LEVEL_WARNING              30
+#define LOG_LEVEL_INFO                 40
+#define LOG_LEVEL_VERBOSE              50
+
+
+#if LOG_LEVEL >= LOG_LEVEL_NOTICE
+# define NOTICE(...)   printf("NOTICE:  " __VA_ARGS__)
+#else
+# define NOTICE(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_ERROR
+# define ERROR(...)    printf("ERROR:   " __VA_ARGS__)
+#else
+# define ERROR(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_WARNING
+# define WARN(...)     printf("WARNING: " __VA_ARGS__)
+#else
+# define WARN(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+# define INFO(...)     printf("INFO:    " __VA_ARGS__)
+#else
+# define INFO(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+# define VERBOSE(...)  printf("VERBOSE: " __VA_ARGS__)
+#else
+# define VERBOSE(...)
+#endif
+
+#endif /* __DEBUG_H__ */
diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h
new file mode 100644 (file)
index 0000000..d73f573
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EXT_H_
+#define EXT_H_
+
+#include <openssl/x509v3.h>
+
+/*
+ * This structure contains the relevant information to create the extensions
+ * to be included in the certificates. This extensions will be used to
+ * establish the chain of trust.
+ */
+typedef struct ext_s {
+       const char *oid;        /* OID of the extension */
+       const char *sn;         /* Short name */
+       const char *ln;         /* Long description */
+       int type;               /* OpenSSL ASN1 type of the extension data.
+                                * Supported types are:
+                                *   - V_ASN1_INTEGER
+                                *   - V_ASN1_OCTET_STRING
+                                */
+       int alias;              /* In case OpenSSL provides an standard
+                                * extension of the same type, add the new
+                                * extension as an alias of this one
+                                */
+
+       X509V3_EXT_METHOD method; /* This field may be used to define a custom
+                                  * function to print the contents of the
+                                  * extension */
+} ext_t;
+
+enum {
+       EXT_NON_CRIT = 0,
+       EXT_CRIT = !EXT_NON_CRIT,
+};
+
+int ext_init(ext_t *tbb_ext);
+X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len);
+X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value);
+X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k);
+
+#endif /* EXT_H_ */
diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h
new file mode 100644 (file)
index 0000000..8819750
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KEY_H_
+#define KEY_H_
+
+#include <openssl/ossl_typ.h>
+
+#define RSA_KEY_BITS           2048
+
+/*
+ * This structure contains the relevant information to create the keys
+ * required to sign the certificates.
+ *
+ * One instance of this structure must be created for each key, usually in an
+ * array fashion. The filename is obtained at run time from the command line
+ * parameters
+ */
+typedef struct key_s {
+       int id;                 /* Key id */
+       const char *desc;       /* Key description (debug purposes) */
+       char *fn;               /* Filename to load/store the key */
+       EVP_PKEY *key;          /* Key container */
+} key_t;
+
+int key_new(key_t *key);
+int key_load(key_t *key);
+int key_store(key_t *key);
+
+#endif /* KEY_H_ */
diff --git a/tools/cert_create/include/sha.h b/tools/cert_create/include/sha.h
new file mode 100644 (file)
index 0000000..466d668
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SHA_H_
+#define SHA_H_
+
+int sha_file(const char *filename, unsigned char *md);
+
+#endif /* SHA_H_ */
diff --git a/tools/cert_create/include/tbb_cert.h b/tools/cert_create/include/tbb_cert.h
new file mode 100644 (file)
index 0000000..4e48125
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TBB_CERT_H_
+#define TBB_CERT_H_
+
+#include "cert.h"
+
+/*
+ * Enumerate the certificates that are used to establish the chain of trust
+ */
+enum {
+       BL2_CERT,
+       TRUSTED_KEY_CERT,
+       BL30_KEY_CERT,
+       BL30_CERT,
+       BL31_KEY_CERT,
+       BL31_CERT,
+       BL32_KEY_CERT,
+       BL32_CERT,
+       BL33_KEY_CERT,
+       BL33_CERT,
+       NUM_CERTIFICATES,
+};
+
+/*
+ * Array containing the certificate instances
+ */
+extern cert_t certs[NUM_CERTIFICATES];
+
+#endif /* TBB_CERT_H_ */
diff --git a/tools/cert_create/include/tbb_ext.h b/tools/cert_create/include/tbb_ext.h
new file mode 100644 (file)
index 0000000..155d3cb
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TBB_EXT_H_
+#define TBB_EXT_H_
+
+#include "ext.h"
+
+/* Array containing the extensions used in the chain of trust */
+extern ext_t tbb_ext[];
+
+#endif /* TBB_EXT_H_ */
diff --git a/tools/cert_create/include/tbb_key.h b/tools/cert_create/include/tbb_key.h
new file mode 100644 (file)
index 0000000..cc927d1
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TBB_KEY_H_
+#define TBB_KEY_H_
+
+#include "key.h"
+
+/*
+ * Enumerate the keys that are used to establish the chain of trust
+ */
+enum {
+       ROT_KEY,
+       TRUSTED_WORLD_KEY,
+       NON_TRUSTED_WORLD_KEY,
+       BL30_KEY,
+       BL31_KEY,
+       BL32_KEY,
+       BL33_KEY,
+       NUM_KEYS
+};
+
+/*
+ * Array containing the key instances
+ */
+extern key_t keys[];
+
+#endif /* TBB_KEY_H_ */
diff --git a/tools/cert_create/src/cert.c b/tools/cert_create/src/cert.c
new file mode 100644 (file)
index 0000000..9705643
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/sha.h>
+#include <openssl/x509v3.h>
+
+#include "cert.h"
+#include "debug.h"
+#include "key.h"
+#include "platform_oid.h"
+#include "sha.h"
+
+#define SERIAL_RAND_BITS       64
+
+int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
+{
+       BIGNUM *btmp;
+       int ret = 0;
+       if (b)
+               btmp = b;
+       else
+               btmp = BN_new();
+
+       if (!btmp)
+               return 0;
+
+       if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
+               goto error;
+       if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
+               goto error;
+
+       ret = 1;
+
+error:
+
+       if (!b)
+               BN_free(btmp);
+
+       return ret;
+}
+
+int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value)
+{
+       X509_EXTENSION *ex;
+       X509V3_CTX ctx;
+
+       /* No configuration database */
+       X509V3_set_ctx_nodb(&ctx);
+
+       /* Set issuer and subject certificates in the context */
+       X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0);
+       ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
+       if (!ex) {
+               ERR_print_errors_fp(stdout);
+               return 0;
+       }
+
+       X509_add_ext(subject, ex, -1);
+       X509_EXTENSION_free(ex);
+
+       return 1;
+}
+
+
+int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
+{
+       EVP_PKEY *pkey = cert->key->key;
+       EVP_PKEY *ikey = cert->issuer->key->key;
+       X509 *issuer = cert->issuer->x;
+       X509 *x = NULL;
+       X509_EXTENSION *ex = NULL;
+       X509_NAME *name = NULL;
+       ASN1_INTEGER *sno = NULL;
+       int i, num;
+
+       /* Create the certificate structure */
+       x = X509_new();
+       if (!x) {
+               return 0;
+       }
+
+       /* If we do not have a key, use the issuer key (the certificate will
+        * become self signed). This happens in content certificates. */
+       if (!pkey) {
+               pkey = ikey;
+       }
+
+       /* If we do not have an issuer certificate, use our own (the certificate
+        * will become self signed) */
+       if (!issuer) {
+               issuer = x;
+       }
+
+       /* x509.v3 */
+       X509_set_version(x, 2);
+
+       /* Random serial number */
+       sno = ASN1_INTEGER_new();
+       rand_serial(NULL, sno);
+       X509_set_serialNumber(x, sno);
+       ASN1_INTEGER_free(sno);
+
+       X509_gmtime_adj(X509_get_notBefore(x), 0);
+       X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
+       X509_set_pubkey(x, pkey);
+
+       /* Subject name */
+       name = X509_get_subject_name(x);
+       X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
+                       (const unsigned char *)cert->cn, -1, -1, 0);
+       X509_set_subject_name(x, name);
+
+       /* Issuer name */
+       name = X509_get_issuer_name(x);
+       X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
+                       (const unsigned char *)cert->issuer->cn, -1, -1, 0);
+       X509_set_issuer_name(x, name);
+
+       /* Add various extensions: standard extensions */
+       cert_add_ext(issuer, x, NID_subject_key_identifier, "hash");
+       cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always");
+       if (ca) {
+               cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE");
+               cert_add_ext(issuer, x, NID_key_usage, "keyCertSign");
+       } else {
+               cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE");
+       }
+
+       /* Add custom extensions */
+       if (sk != NULL) {
+               num = sk_X509_EXTENSION_num(sk);
+               for (i = 0; i < num; i++) {
+                       ex = sk_X509_EXTENSION_value(sk, i);
+                       X509_add_ext(x, ex, -1);
+               }
+       }
+
+       /* Sign the certificate with the issuer key */
+       if (!X509_sign(x, ikey, EVP_sha1())) {
+               ERR_print_errors_fp(stdout);
+               return 0;
+       }
+
+       cert->x = x;
+       return 1;
+}
diff --git a/tools/cert_create/src/ext.c b/tools/cert_create/src/ext.c
new file mode 100644 (file)
index 0000000..31f84a8
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+#include "ext.h"
+
+DECLARE_ASN1_ITEM(ASN1_INTEGER)
+DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
+
+/*
+ * This function adds the TBB extensions to the internal extension list
+ * maintained by OpenSSL so they can be used later.
+ *
+ * It also initializes the methods to print the contents of the extension. If an
+ * alias is specified in the TBB extension, we reuse the methods of the alias.
+ * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are
+ * provided. Any other type will be printed as a raw ascii string.
+ *
+ * Return: 0 = success, Otherwise: error
+ */
+int ext_init(ext_t *tbb_ext)
+{
+       ext_t *ext;
+       X509V3_EXT_METHOD *m;
+       int i = 0, nid, ret;
+
+       while ((ext = &tbb_ext[i++]) && ext->oid) {
+               nid = OBJ_create(ext->oid, ext->sn, ext->ln);
+               if (ext->alias) {
+                       X509V3_EXT_add_alias(nid, ext->alias);
+               } else {
+                       m = &ext->method;
+                       memset(m, 0x0, sizeof(X509V3_EXT_METHOD));
+                       switch (ext->type) {
+                       case V_ASN1_INTEGER:
+                               m->it = ASN1_ITEM_ref(ASN1_INTEGER);
+                               m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER;
+                               m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER;
+                               break;
+                       case V_ASN1_OCTET_STRING:
+                               m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING);
+                               m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING;
+                               m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING;
+                               break;
+                       default:
+                               continue;
+                       }
+                       m->ext_nid = nid;
+                       ret = X509V3_EXT_add(m);
+                       if (!ret) {
+                               ERR_print_errors_fp(stdout);
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+/*
+ * Create a new extension
+ *
+ * Extension  ::=  SEQUENCE  {
+ *      id          OBJECT IDENTIFIER,
+ *      critical    BOOLEAN DEFAULT FALSE,
+ *      value       OCTET STRING  }
+ *
+ * Parameters:
+ *   pex: OpenSSL extension pointer (output parameter)
+ *   nid: extension identifier
+ *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
+ *   data: extension data. This data will be encapsulated in an Octet String
+ *
+ * Return: Extension address, NULL if error
+ */
+static
+X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len)
+{
+       X509_EXTENSION *ex;
+       ASN1_OCTET_STRING *ext_data;
+
+       /* Octet string containing the extension data */
+       ext_data = ASN1_OCTET_STRING_new();
+       ASN1_OCTET_STRING_set(ext_data, data, len);
+
+       /* Create the extension */
+       ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data);
+
+       /* The extension makes a copy of the data, so we can free this object */
+       ASN1_OCTET_STRING_free(ext_data);
+
+       return ex;
+}
+
+/*
+ * Creates a x509v3 extension containing a hash encapsulated in an ASN1 Octet
+ * String
+ *
+ * Parameters:
+ *   pex: OpenSSL extension pointer (output parameter)
+ *   nid: extension identifier
+ *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
+ *   buf: pointer to the buffer that contains the hash
+ *   len: size of the hash in bytes
+ *
+ * Return: Extension address, NULL if error
+ */
+X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len)
+{
+       X509_EXTENSION *ex = NULL;
+       ASN1_OCTET_STRING *hash = NULL;
+       unsigned char *p = NULL;
+       int sz = -1;
+
+       /* Encode Hash */
+       hash = ASN1_OCTET_STRING_new();
+       ASN1_OCTET_STRING_set(hash, buf, len);
+       sz = i2d_ASN1_OCTET_STRING(hash, NULL);
+       i2d_ASN1_OCTET_STRING(hash, &p);
+
+       /* Create the extension */
+       ex = ext_new(nid, crit, p, sz);
+
+       /* Clean up */
+       OPENSSL_free(p);
+       ASN1_OCTET_STRING_free(hash);
+
+       return ex;
+}
+
+/*
+ * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
+ * Integer
+ *
+ * Parameters:
+ *   pex: OpenSSL extension pointer (output parameter)
+ *   nid: extension identifier
+ *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
+ *   value: nvcounter value
+ *
+ * Return: Extension address, NULL if error
+ */
+X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
+{
+       X509_EXTENSION *ex = NULL;
+       ASN1_INTEGER *counter = NULL;
+       unsigned char *p = NULL;
+       int sz = -1;
+
+       /* Encode counter */
+       counter = ASN1_INTEGER_new();
+       ASN1_INTEGER_set(counter, value);
+       sz = i2d_ASN1_INTEGER(counter, NULL);
+       i2d_ASN1_INTEGER(counter, &p);
+
+       /* Create the extension */
+       ex = ext_new(nid, crit, p, sz);
+
+       /* Free objects */
+       OPENSSL_free(p);
+       ASN1_INTEGER_free(counter);
+
+       return ex;
+}
+
+/*
+ * Creates a x509v3 extension containing a public key in DER format:
+ *
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
+ *       algorithm            AlgorithmIdentifier,
+ *       subjectPublicKey     BIT STRING }
+ *
+ * Parameters:
+ *   pex: OpenSSL extension pointer (output parameter)
+ *   nid: extension identifier
+ *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
+ *   k: key
+ *
+ * Return: Extension address, NULL if error
+ */
+X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
+{
+       X509_EXTENSION *ex = NULL;
+       unsigned char *p = NULL;
+       int sz = -1;
+
+       /* Encode key */
+       BIO *mem = BIO_new(BIO_s_mem());
+       if (i2d_PUBKEY_bio(mem, k) <= 0) {
+               ERR_print_errors_fp(stderr);
+               return NULL;
+       }
+       p = (unsigned char *)OPENSSL_malloc(4096);
+       sz = BIO_read(mem, p, 4096);
+
+       /* Create the extension */
+       ex = ext_new(nid, crit, p, sz);
+
+       /* Clean up */
+       OPENSSL_free(p);
+
+       return ex;
+}
diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c
new file mode 100644 (file)
index 0000000..b5737d9
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
+#include "cert.h"
+#include "debug.h"
+#include "key.h"
+#include "platform_oid.h"
+#include "sha.h"
+
+#define MAX_FILENAME_LEN               1024
+
+/*
+ * Create a new key
+ */
+int key_new(key_t *key)
+{
+       RSA *rsa = NULL;
+       EVP_PKEY *k = NULL;
+
+       /* Create key pair container */
+       k = EVP_PKEY_new();
+       if (k == NULL) {
+               return 0;
+       }
+
+       /* Generate a new RSA key */
+       rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL);
+       if (EVP_PKEY_assign_RSA(k, rsa)) {
+               key->key = k;
+               return 1;
+       } else {
+               printf("Cannot assign RSA key\n");
+       }
+
+       if (k)
+               EVP_PKEY_free(k);
+       return 0;
+}
+
+int key_load(key_t *key)
+{
+       FILE *fp = NULL;
+       EVP_PKEY *k = NULL;
+
+       /* Create key pair container */
+       k = EVP_PKEY_new();
+       if (k == NULL) {
+               return 0;
+       }
+
+       if (key->fn) {
+               /* Load key from file */
+               fp = fopen(key->fn, "r");
+               if (fp) {
+                       k = PEM_read_PrivateKey(fp, &k, NULL, NULL);
+                       fclose(fp);
+                       if (k) {
+                               key->key = k;
+                               return 1;
+                       } else {
+                               ERROR("Cannot read key from %s\n", key->fn);
+                       }
+               } else {
+                       ERROR("Cannot open file %s\n", key->fn);
+               }
+       } else {
+               ERROR("Key filename not specified\n");
+       }
+
+       if (k)
+               EVP_PKEY_free(k);
+
+       return 0;
+}
+
+int key_store(key_t *key)
+{
+       FILE *fp = NULL;
+
+       if (key->fn) {
+               fp = fopen(key->fn, "w");
+               if (fp) {
+                       PEM_write_PrivateKey(fp, key->key,
+                                       NULL, NULL, 0, NULL, NULL);
+                       fclose(fp);
+                       return 1;
+               } else {
+                       ERROR("Cannot create file %s\n", key->fn);
+               }
+       } else {
+               ERROR("Key filename not specified\n");
+       }
+
+       return 0;
+}
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
new file mode 100644 (file)
index 0000000..6df367a
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/sha.h>
+#include <openssl/x509v3.h>
+
+#include "cert.h"
+#include "debug.h"
+#include "ext.h"
+#include "key.h"
+#include "platform_oid.h"
+#include "sha.h"
+#include "tbb_ext.h"
+#include "tbb_cert.h"
+#include "tbb_key.h"
+
+/*
+ * Helper macros to simplify the code. This macro assigns the return value of
+ * the 'fn' function to 'v' and exits if the value is NULL.
+ */
+#define CHECK_NULL(v, fn) \
+       do { \
+               v = fn; \
+               if (v == NULL) { \
+                       ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
+                       exit(1); \
+               } \
+       } while (0)
+
+/*
+ * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
+ * NID is undefined.
+ */
+#define CHECK_OID(v, oid) \
+       do { \
+               v = OBJ_txt2nid(oid); \
+               if (v == NID_undef) { \
+                       ERROR("Cannot find TBB extension %s\n", oid); \
+                       exit(1); \
+               } \
+       } while (0)
+
+#define MAX_FILENAME_LEN               1024
+#define VAL_DAYS                       7300
+#define ID_TO_BIT_MASK(id)             (1 << id)
+#define NVCOUNTER_VALUE                        0
+
+/* Files */
+enum {
+       /* Image file names (inputs) */
+       BL2_ID = 0,
+       BL30_ID,
+       BL31_ID,
+       BL32_ID,
+       BL33_ID,
+       /* Certificate file names (outputs) */
+       BL2_CERT_ID,
+       TRUSTED_KEY_CERT_ID,
+       BL30_KEY_CERT_ID,
+       BL30_CERT_ID,
+       BL31_KEY_CERT_ID,
+       BL31_CERT_ID,
+       BL32_KEY_CERT_ID,
+       BL32_CERT_ID,
+       BL33_KEY_CERT_ID,
+       BL33_CERT_ID,
+       /* Key file names (input/output) */
+       ROT_KEY_ID,
+       TRUSTED_WORLD_KEY_ID,
+       NON_TRUSTED_WORLD_KEY_ID,
+       BL30_KEY_ID,
+       BL31_KEY_ID,
+       BL32_KEY_ID,
+       BL33_KEY_ID,
+       NUM_OPTS
+};
+
+/* Global options */
+static int new_keys;
+static int save_keys;
+static int print_cert;
+static int bl30_present;
+static int bl32_present;
+
+/* We are not checking nvcounters in TF. Include them in the certificates but
+ * the value will be set to 0 */
+static int tf_nvcounter;
+static int non_tf_nvcounter;
+
+/* Info messages created in the Makefile */
+extern const char build_msg[];
+extern const char platform_msg[];
+
+
+static char *strdup(const char *str)
+{
+       int n = strlen(str) + 1;
+       char *dup = malloc(n);
+       if (dup) {
+               strcpy(dup, str);
+       }
+       return dup;
+}
+
+/* Command line options */
+static const struct option long_opt[] = {
+       /* Binary images */
+       {"bl2", required_argument, 0, BL2_ID},
+       {"bl30", required_argument, 0, BL30_ID},
+       {"bl31", required_argument, 0, BL31_ID},
+       {"bl32", required_argument, 0, BL32_ID},
+       {"bl33", required_argument, 0, BL33_ID},
+       /* Certificate files */
+       {"bl2-cert", required_argument, 0, BL2_CERT_ID},
+       {"trusted-key-cert", required_argument, 0, TRUSTED_KEY_CERT_ID},
+       {"bl30-key-cert", required_argument, 0, BL30_KEY_CERT_ID},
+       {"bl30-cert", required_argument, 0, BL30_CERT_ID},
+       {"bl31-key-cert", required_argument, 0, BL31_KEY_CERT_ID},
+       {"bl31-cert", required_argument, 0, BL31_CERT_ID},
+       {"bl32-key-cert", required_argument, 0, BL32_KEY_CERT_ID},
+       {"bl32-cert", required_argument, 0, BL32_CERT_ID},
+       {"bl33-key-cert", required_argument, 0, BL33_KEY_CERT_ID},
+       {"bl33-cert", required_argument, 0, BL33_CERT_ID},
+       /* Private key files */
+       {"rot-key", required_argument, 0, ROT_KEY_ID},
+       {"trusted-world-key", required_argument, 0, TRUSTED_WORLD_KEY_ID},
+       {"non-trusted-world-key", required_argument, 0, NON_TRUSTED_WORLD_KEY_ID},
+       {"bl30-key", required_argument, 0, BL30_KEY_ID},
+       {"bl31-key", required_argument, 0, BL31_KEY_ID},
+       {"bl32-key", required_argument, 0, BL32_KEY_ID},
+       {"bl33-key", required_argument, 0, BL33_KEY_ID},
+       /* Common options */
+       {"help", no_argument, 0, 'h'},
+       {"save-keys", no_argument, 0, 'k'},
+       {"new-chain", no_argument, 0, 'n'},
+       {"print-cert", no_argument, 0, 'p'},
+       {0, 0, 0, 0}
+};
+
+static void print_help(const char *cmd)
+{
+       int i = 0;
+       printf("\n\n");
+       printf("The certificate generation tool loads the binary images and\n"
+              "optionally the RSA keys, and outputs the key and content\n"
+              "certificates properly signed to implement the chain of trust.\n"
+              "If keys are provided, they must be in PEM format.\n"
+              "Certificates are generated in DER format.\n");
+       printf("\n");
+       printf("Usage:\n\n");
+       printf("    %s [-hknp] \\\n", cmd);
+       for (i = 0; i < NUM_OPTS; i++) {
+               printf("        --%s <file>  \\\n", long_opt[i].name);
+       }
+       printf("\n");
+       printf("-h    Print help and exit\n");
+       printf("-k    Save key pairs into files. Filenames must be provided\n");
+       printf("-n    Generate new key pairs if no key files are provided\n");
+       printf("-p    Print the certificates in the standard output\n");
+       printf("\n");
+
+       exit(0);
+}
+
+static void check_cmd_params(void)
+{
+       /* BL2, BL31 and BL33 are mandatory */
+       if (certs[BL2_CERT].bin == NULL) {
+               ERROR("BL2 image not specified\n");
+               exit(1);
+       }
+
+       if (certs[BL31_CERT].bin == NULL) {
+               ERROR("BL31 image not specified\n");
+               exit(1);
+       }
+
+       if (certs[BL33_CERT].bin == NULL) {
+               ERROR("BL33 image not specified\n");
+               exit(1);
+       }
+
+       /* BL30 and BL32 are optional */
+       if (certs[BL30_CERT].bin != NULL) {
+               bl30_present = 1;
+       }
+
+       if (certs[BL32_CERT].bin != NULL) {
+               bl32_present = 1;
+       }
+
+       /* TODO: Certificate filenames */
+
+       /* Filenames to store keys must be specified */
+       if (save_keys || !new_keys) {
+               if (keys[ROT_KEY].fn == NULL) {
+                       ERROR("ROT key not specified\n");
+                       exit(1);
+               }
+
+               if (keys[TRUSTED_WORLD_KEY].fn == NULL) {
+                       ERROR("Trusted World key not specified\n");
+                       exit(1);
+               }
+
+               if (keys[NON_TRUSTED_WORLD_KEY].fn == NULL) {
+                       ERROR("Non-trusted World key not specified\n");
+                       exit(1);
+               }
+
+               if (keys[BL31_KEY].fn == NULL) {
+                       ERROR("BL31 key not specified\n");
+                       exit(1);
+               }
+
+               if (keys[BL33_KEY].fn == NULL) {
+                       ERROR("BL33 key not specified\n");
+                       exit(1);
+               }
+
+               if (bl30_present && (keys[BL30_KEY].fn == NULL)) {
+                       ERROR("BL30 key not specified\n");
+                       exit(1);
+               }
+
+               if (bl32_present && (keys[BL32_KEY].fn == NULL)) {
+                       ERROR("BL32 key not specified\n");
+                       exit(1);
+               }
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       STACK_OF(X509_EXTENSION) * sk = NULL;
+       X509_EXTENSION *hash_ext = NULL;
+       X509_EXTENSION *nvctr_ext = NULL;
+       X509_EXTENSION *trusted_key_ext = NULL;
+       X509_EXTENSION *non_trusted_key_ext = NULL;
+       FILE *file = NULL;
+       int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid;
+       int c, opt_idx = 0;
+       unsigned char md[SHA256_DIGEST_LENGTH];
+
+       NOTICE("CoT Generation Tool: %s\n", build_msg);
+       NOTICE("Target platform: %s\n", platform_msg);
+
+       while (1) {
+               /* getopt_long stores the option index here. */
+               c = getopt_long(argc, argv, "hknp", long_opt, &opt_idx);
+
+               /* Detect the end of the options. */
+               if (c == -1) {
+                       break;
+               }
+
+               switch (c) {
+               case 'h':
+                       print_help(argv[0]);
+                       break;
+               case 'k':
+                       save_keys = 1;
+                       break;
+               case 'n':
+                       new_keys = 1;
+                       break;
+               case 'p':
+                       print_cert = 1;
+                       break;
+               case BL2_ID:
+                       certs[BL2_CERT].bin = strdup(optarg);
+                       break;
+               case BL30_ID:
+                       certs[BL30_CERT].bin = strdup(optarg);
+                       break;
+               case BL31_ID:
+                       certs[BL31_CERT].bin = strdup(optarg);
+                       break;
+               case BL32_ID:
+                       certs[BL32_CERT].bin = strdup(optarg);
+                       break;
+               case BL33_ID:
+                       certs[BL33_CERT].bin = strdup(optarg);
+                       break;
+               case BL2_CERT_ID:
+                       certs[BL2_CERT].fn = strdup(optarg);
+                       break;
+               case TRUSTED_KEY_CERT_ID:
+                       certs[TRUSTED_KEY_CERT].fn = strdup(optarg);
+                       break;
+               case BL30_KEY_CERT_ID:
+                       certs[BL30_KEY_CERT].fn = strdup(optarg);
+                       break;
+               case BL30_CERT_ID:
+                       certs[BL30_CERT].fn = strdup(optarg);
+                       break;
+               case BL31_KEY_CERT_ID:
+                       certs[BL31_KEY_CERT].fn = strdup(optarg);
+                       break;
+               case BL31_CERT_ID:
+                       certs[BL31_CERT].fn = strdup(optarg);
+                       break;
+               case BL32_KEY_CERT_ID:
+                       certs[BL32_KEY_CERT].fn = strdup(optarg);
+                       break;
+               case BL32_CERT_ID:
+                       certs[BL32_CERT].fn = strdup(optarg);
+                       break;
+               case BL33_KEY_CERT_ID:
+                       certs[BL33_KEY_CERT].fn = strdup(optarg);
+                       break;
+               case BL33_CERT_ID:
+                       certs[BL33_CERT].fn = strdup(optarg);
+                       break;
+               case ROT_KEY_ID:
+                       keys[ROT_KEY].fn = strdup(optarg);
+                       break;
+               case TRUSTED_WORLD_KEY_ID:
+                       keys[TRUSTED_WORLD_KEY].fn = strdup(optarg);
+                       break;
+               case NON_TRUSTED_WORLD_KEY_ID:
+                       keys[NON_TRUSTED_WORLD_KEY].fn = strdup(optarg);
+                       break;
+               case BL30_KEY_ID:
+                       keys[BL30_KEY].fn = strdup(optarg);
+                       break;
+               case BL31_KEY_ID:
+                       keys[BL31_KEY].fn = strdup(optarg);
+                       break;
+               case BL32_KEY_ID:
+                       keys[BL32_KEY].fn = strdup(optarg);
+                       break;
+               case BL33_KEY_ID:
+                       keys[BL33_KEY].fn = strdup(optarg);
+                       break;
+               case '?':
+               default:
+                       printf("%s\n", optarg);
+                       exit(1);
+               }
+       }
+
+       /* Set the value of the NVCounters */
+       tf_nvcounter = NVCOUNTER_VALUE;
+       non_tf_nvcounter = NVCOUNTER_VALUE;
+
+       /* Check command line arguments */
+       check_cmd_params();
+
+       /* Register the new types and OIDs for the extensions */
+       if (ext_init(tbb_ext) != 0) {
+               ERROR("Cannot initialize TBB extensions\n");
+               exit(1);
+       }
+
+       /* Get non-volatile counters NIDs */
+       CHECK_OID(tz_nvctr_nid, TZ_FW_NVCOUNTER_OID);
+       CHECK_OID(ntz_nvctr_nid, NTZ_FW_NVCOUNTER_OID);
+
+       /* Load private keys from files (or generate new ones) */
+       if (new_keys) {
+               for (i = 0 ; i < NUM_KEYS ; i++) {
+                       if (!key_new(&keys[i])) {
+                               ERROR("Error creating %s\n", keys[i].desc);
+                               exit(1);
+                       }
+               }
+       } else {
+               for (i = 0 ; i < NUM_KEYS ; i++) {
+                       if (!key_load(&keys[i])) {
+                               ERROR("Error loading %s\n", keys[i].desc);
+                               exit(1);
+                       }
+               }
+       }
+
+       /* *********************************************************************
+        * BL2 certificate (Trusted Boot Firmware certificate):
+        *     - Self-signed with OEM ROT private key
+        *     - Extensions:
+        *         - TrustedFirmwareNVCounter (TODO)
+        *         - BL2 hash
+        **********************************************************************/
+       CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+
+       /* Add the NVCounter as a critical extension */
+       CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+                       tf_nvcounter));
+       sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+       /* Add hash of BL2 as an extension */
+       if (!sha_file(certs[BL2_CERT].bin, md)) {
+               ERROR("Cannot calculate the hash of %s\n", certs[BL2_CERT].bin);
+               exit(1);
+       }
+       CHECK_OID(hash_nid, BL2_HASH_OID);
+       CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+                       SHA256_DIGEST_LENGTH));
+       sk_X509_EXTENSION_push(sk, hash_ext);
+
+       /* Create certificate. Signed with ROT key */
+       if (!cert_new(&certs[BL2_CERT], VAL_DAYS, 0, sk)) {
+               ERROR("Cannot create %s\n", certs[BL2_CERT].cn);
+               exit(1);
+       }
+       sk_X509_EXTENSION_free(sk);
+
+       /* *********************************************************************
+        * Trusted Key certificate:
+        *     - Self-signed with OEM ROT private key
+        *     - Extensions:
+        *         - TrustedFirmwareNVCounter (TODO)
+        *         - TrustedWorldPK
+        *         - NonTrustedWorldPK
+        **********************************************************************/
+       CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+       CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+                       tf_nvcounter));
+       sk_X509_EXTENSION_push(sk, nvctr_ext);
+       CHECK_OID(pk_nid, TZ_WORLD_PK_OID);
+       CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+                       keys[TRUSTED_WORLD_KEY].key));
+       sk_X509_EXTENSION_push(sk, trusted_key_ext);
+       CHECK_OID(pk_nid, NTZ_WORLD_PK_OID);
+       CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+                       keys[NON_TRUSTED_WORLD_KEY].key));
+       sk_X509_EXTENSION_push(sk, non_trusted_key_ext);
+       if (!cert_new(&certs[TRUSTED_KEY_CERT], VAL_DAYS, 0, sk)) {
+               ERROR("Cannot create %s\n", certs[TRUSTED_KEY_CERT].cn);
+               exit(1);
+       }
+       sk_X509_EXTENSION_free(sk);
+
+       /* *********************************************************************
+        * BL30 Key certificate (Trusted SCP Firmware Key certificate):
+        *     - Self-signed with Trusted World key
+        *     - Extensions:
+        *         - TrustedFirmwareNVCounter (TODO)
+        *         - SCPFirmwareContentCertPK
+        **********************************************************************/
+       if (bl30_present) {
+               CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+               CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+                               tf_nvcounter));
+               sk_X509_EXTENSION_push(sk, nvctr_ext);
+               CHECK_OID(pk_nid, BL30_CONTENT_CERT_PK_OID);
+               CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+                               keys[BL30_KEY].key));
+               sk_X509_EXTENSION_push(sk, trusted_key_ext);
+               if (!cert_new(&certs[BL30_KEY_CERT], VAL_DAYS, 0, sk)) {
+                       ERROR("Cannot create %s\n", certs[BL30_KEY_CERT].cn);
+                       exit(1);
+               }
+               sk_X509_EXTENSION_free(sk);
+       }
+
+       /* *********************************************************************
+        * BL30 certificate (SCP Firmware Content certificate):
+        *     - Signed with Trusted World Key
+        *     - Extensions:
+        *         - TrustedFirmwareNVCounter (TODO)
+        *         - SCPFirmwareHash
+        **********************************************************************/
+       if (bl30_present) {
+               CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+               CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+                               tf_nvcounter));
+               sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+               if (!sha_file(certs[BL30_CERT].bin, md)) {
+                       ERROR("Cannot calculate the hash of %s\n",
+                                       certs[BL30_CERT].bin);
+                       exit(1);
+               }
+               CHECK_OID(hash_nid, BL30_HASH_OID);
+               CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+                               SHA256_DIGEST_LENGTH));
+               sk_X509_EXTENSION_push(sk, hash_ext);
+
+               if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) {
+                       ERROR("Cannot create %s\n", certs[BL30_CERT].cn);
+                       exit(1);
+               }
+
+               sk_X509_EXTENSION_free(sk);
+       }
+
+       /* *********************************************************************
+        * BL31 Key certificate (Trusted SoC Firmware Key certificate):
+        *     - Self-signed with Trusted World key
+        *     - Extensions:
+        *         - TrustedFirmwareNVCounter (TODO)
+        *         - SoCFirmwareContentCertPK
+        **********************************************************************/
+       CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+       CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+                       tf_nvcounter));
+       sk_X509_EXTENSION_push(sk, nvctr_ext);
+       CHECK_OID(pk_nid, BL31_CONTENT_CERT_PK_OID);
+       CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+                       keys[BL31_KEY].key));
+       sk_X509_EXTENSION_push(sk, trusted_key_ext);
+       if (!cert_new(&certs[BL31_KEY_CERT], VAL_DAYS, 0, sk)) {
+               ERROR("Cannot create %s\n", certs[BL31_KEY_CERT].cn);
+               exit(1);
+       }
+       sk_X509_EXTENSION_free(sk);
+
+       /* *********************************************************************
+        * BL31 certificate (SOC Firmware Content certificate):
+        *     - Signed with Trusted World Key
+        *     - Extensions:
+        *         - TrustedFirmwareNVCounter (TODO)
+        *         - BL31 hash
+        **********************************************************************/
+       CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+       CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+                       tf_nvcounter));
+       sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+       if (!sha_file(certs[BL31_CERT].bin, md)) {
+               ERROR("Cannot calculate the hash of %s\n", certs[BL31_CERT].bin);
+               exit(1);
+       }
+       CHECK_OID(hash_nid, BL31_HASH_OID);
+       CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+                       SHA256_DIGEST_LENGTH));
+       sk_X509_EXTENSION_push(sk, hash_ext);
+
+       if (!cert_new(&certs[BL31_CERT], VAL_DAYS, 0, sk)) {
+               ERROR("Cannot create %s\n", certs[BL31_CERT].cn);
+               exit(1);
+       }
+
+       sk_X509_EXTENSION_free(sk);
+
+       /* *********************************************************************
+        * BL32 Key certificate (Trusted OS Firmware Key certificate):
+        *     - Self-signed with Trusted World key
+        *     - Extensions:
+        *         - TrustedFirmwareNVCounter (TODO)
+        *         - TrustedOSFirmwareContentCertPK
+        **********************************************************************/
+       if (bl32_present) {
+               CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+               CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+                               tf_nvcounter));
+               sk_X509_EXTENSION_push(sk, nvctr_ext);
+               CHECK_OID(pk_nid, BL32_CONTENT_CERT_PK_OID);
+               CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+                               keys[BL32_KEY].key));
+               sk_X509_EXTENSION_push(sk, trusted_key_ext);
+               if (!cert_new(&certs[BL32_KEY_CERT], VAL_DAYS, 0, sk)) {
+                       ERROR("Cannot create %s\n", certs[BL32_KEY_CERT].cn);
+                       exit(1);
+               }
+               sk_X509_EXTENSION_free(sk);
+       }
+
+       /* *********************************************************************
+        * BL32 certificate (TrustedOS Firmware Content certificate):
+        *     - Signed with Trusted World Key
+        *     - Extensions:
+        *         - TrustedFirmwareNVCounter (TODO)
+        *         - BL32 hash
+        **********************************************************************/
+       if (bl32_present) {
+               CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+               CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+                               tf_nvcounter));
+               sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+               if (!sha_file(certs[BL32_CERT].bin, md)) {
+                       ERROR("Cannot calculate the hash of %s\n",
+                                       certs[BL32_CERT].bin);
+                       exit(1);
+               }
+               CHECK_OID(hash_nid, BL32_HASH_OID);
+               CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+                               SHA256_DIGEST_LENGTH));
+               sk_X509_EXTENSION_push(sk, hash_ext);
+
+               if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) {
+                       ERROR("Cannot create %s\n", certs[BL32_CERT].cn);
+                       exit(1);
+               }
+
+               sk_X509_EXTENSION_free(sk);
+       }
+
+       /* *********************************************************************
+        * BL33 Key certificate (Non Trusted Firmware Key certificate):
+        *     - Self-signed with Non Trusted World key
+        *     - Extensions:
+        *         - NonTrustedFirmwareNVCounter (TODO)
+        *         - NonTrustedFirmwareContentCertPK
+        **********************************************************************/
+       CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+       CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT,
+                       non_tf_nvcounter));
+       sk_X509_EXTENSION_push(sk, nvctr_ext);
+       CHECK_OID(pk_nid, BL33_CONTENT_CERT_PK_OID);
+       CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+                       keys[BL33_KEY].key));
+       sk_X509_EXTENSION_push(sk, non_trusted_key_ext);
+       if (!cert_new(&certs[BL33_KEY_CERT], VAL_DAYS, 0, sk)) {
+               ERROR("Cannot create %s\n", certs[BL33_KEY_CERT].cn);
+               exit(1);
+       }
+       sk_X509_EXTENSION_free(sk);
+
+       /* *********************************************************************
+        * BL33 certificate (Non-Trusted World Content certificate):
+        *     - Signed with Non-Trusted World Key
+        *     - Extensions:
+        *         - NonTrustedFirmwareNVCounter (TODO)
+        *         - BL33 hash
+        **********************************************************************/
+       CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+       CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT,
+                       non_tf_nvcounter));
+       sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+       if (!sha_file(certs[BL33_CERT].bin, md)) {
+               ERROR("Cannot calculate the hash of %s\n", certs[BL33_CERT].bin);
+               exit(1);
+       }
+       CHECK_OID(hash_nid, BL33_HASH_OID);
+       CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+                       SHA256_DIGEST_LENGTH));
+       sk_X509_EXTENSION_push(sk, hash_ext);
+
+       if (!cert_new(&certs[BL33_CERT], VAL_DAYS, 0, sk)) {
+               ERROR("Cannot create %s\n", certs[BL33_CERT].cn);
+               exit(1);
+       }
+       sk_X509_EXTENSION_free(sk);
+
+       /* Print the certificates */
+       if (print_cert) {
+               for (i = 0 ; i < NUM_CERTIFICATES ; i++) {
+                       if (!certs[i].x) {
+                               continue;
+                       }
+                       printf("\n\n=====================================\n\n");
+                       X509_print_fp(stdout, certs[i].x);
+               }
+       }
+
+       /* Save created certificates to files */
+       for (i = 0 ; i < NUM_CERTIFICATES ; i++) {
+               if (certs[i].x && certs[i].fn) {
+                       file = fopen(certs[i].fn, "w");
+                       if (file != NULL) {
+                               i2d_X509_fp(file, certs[i].x);
+                               fclose(file);
+                       } else {
+                               ERROR("Cannot create file %s\n", certs[i].fn);
+                       }
+               }
+       }
+
+       /* Save keys */
+       if (save_keys) {
+               for (i = 0 ; i < NUM_KEYS ; i++) {
+                       if (!key_store(&keys[i])) {
+                               ERROR("Cannot save %s\n", keys[i].desc);
+                       }
+               }
+       }
+
+       X509_EXTENSION_free(hash_ext);
+       X509_EXTENSION_free(nvctr_ext);
+       X509_EXTENSION_free(trusted_key_ext);
+       X509_EXTENSION_free(non_trusted_key_ext);
+
+#ifndef OPENSSL_NO_ENGINE
+       ENGINE_cleanup();
+#endif
+       CRYPTO_cleanup_all_ex_data();
+
+       return 0;
+}
diff --git a/tools/cert_create/src/sha.c b/tools/cert_create/src/sha.c
new file mode 100644 (file)
index 0000000..57026b5
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <openssl/sha.h>
+
+#include "debug.h"
+
+#define BUFFER_SIZE    256
+
+int sha_file(const char *filename, unsigned char *md)
+{
+       FILE *inFile;
+       SHA256_CTX shaContext;
+       int bytes;
+       unsigned char data[BUFFER_SIZE];
+
+       if ((filename == NULL) || (md == NULL)) {
+               ERROR("%s(): NULL argument\n", __FUNCTION__);
+               return 0;
+       }
+
+       inFile = fopen(filename, "rb");
+       if (inFile == NULL) {
+               ERROR("Cannot read %s\n", filename);
+               return 0;
+       }
+
+       SHA256_Init(&shaContext);
+       while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) {
+               SHA256_Update(&shaContext, data, bytes);
+       }
+       SHA256_Final(md, &shaContext);
+
+       fclose(inFile);
+       return 1;
+}
diff --git a/tools/cert_create/src/tbb_cert.c b/tools/cert_create/src/tbb_cert.c
new file mode 100644 (file)
index 0000000..8dfda60
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tbb_cert.h"
+#include "tbb_key.h"
+
+/*
+ * Certificates used in the chain of trust
+ *
+ * The order of the certificates must follow the enumeration specified in
+ * tbb_cert.h. All certificates are self-signed.
+ */
+cert_t certs[NUM_CERTIFICATES] = {
+       {
+               .id = BL2_CERT,
+               .fn = NULL,
+               .cn = "BL2 Certificate",
+               .key = &keys[ROT_KEY],
+               .issuer = &certs[BL2_CERT],
+       },
+       {
+               .id = TRUSTED_KEY_CERT,
+               .fn = NULL,
+               .cn = "Trusted Key Certificate",
+               .key = &keys[ROT_KEY],
+               .issuer = &certs[TRUSTED_KEY_CERT],
+       },
+       {
+               .id = BL30_KEY_CERT,
+               .fn = NULL,
+               .cn = "BL3-0 Key Certificate",
+               .key = &keys[TRUSTED_WORLD_KEY],
+               .issuer = &certs[BL30_KEY_CERT],
+       },
+       {
+               .id = BL30_CERT,
+               .fn = NULL,
+               .cn = "BL3-0 Content Certificate",
+               .key = &keys[BL30_KEY],
+               .issuer = &certs[BL30_CERT],
+       },
+       {
+               .id = BL31_KEY_CERT,
+               .fn = NULL,
+               .cn = "BL3-1 Key Certificate",
+               .key = &keys[TRUSTED_WORLD_KEY],
+               .issuer = &certs[BL31_KEY_CERT],
+       },
+       {
+               .id = BL31_CERT,
+               .fn = NULL,
+               .cn = "BL3-1 Content Certificate",
+               .key = &keys[BL31_KEY],
+               .issuer = &certs[BL31_CERT],
+       },
+       {
+               .id = BL32_KEY_CERT,
+               .fn = NULL,
+               .cn = "BL3-2 Key Certificate",
+               .key = &keys[TRUSTED_WORLD_KEY],
+               .issuer = &certs[BL32_KEY_CERT],
+       },
+       {
+               .id = BL32_CERT,
+               .fn = NULL,
+               .cn = "BL3-2 Content Certificate",
+               .key = &keys[BL32_KEY],
+               .issuer = &certs[BL32_CERT],
+       },
+       {
+               .id = BL33_KEY_CERT,
+               .fn = NULL,
+               .cn = "BL3-3 Key Certificate",
+               .key = &keys[NON_TRUSTED_WORLD_KEY],
+               .issuer = &certs[BL33_KEY_CERT],
+       },
+       {
+               .id = BL33_CERT,
+               .fn = NULL,
+               .cn = "BL3-3 Content Certificate",
+               .key = &keys[BL33_KEY],
+               .issuer = &certs[BL33_CERT],
+       }
+};
diff --git a/tools/cert_create/src/tbb_ext.c b/tools/cert_create/src/tbb_ext.c
new file mode 100644 (file)
index 0000000..0022611
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+#include "ext.h"
+#include "platform_oid.h"
+
+ext_t tbb_ext[] = {
+       {
+               .oid = TZ_FW_NVCOUNTER_OID,
+               .sn = "TrustedNvCounter",
+               .ln = "Non-volatile trusted counter",
+               .type = V_ASN1_INTEGER
+       },
+       {
+               .oid = NTZ_FW_NVCOUNTER_OID,
+               .sn = "NonTrustedNvCounter",
+               .ln = "Non-volatile non-trusted counter",
+               .type = V_ASN1_INTEGER
+       },
+       {
+               .oid = BL2_HASH_OID,
+               .sn = "TrustedBootFirmwareHash",
+               .ln = "Trusted Boot Firmware (BL2) hash (SHA256)",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = TZ_WORLD_PK_OID,
+               .sn = "TrustedWorldPublicKey",
+               .ln = "Trusted World Public Key",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = NTZ_WORLD_PK_OID,
+               .sn = "NonTrustedWorldPublicKey",
+               .ln = "Non-Trusted World Public Key",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = BL31_CONTENT_CERT_PK_OID,
+               .sn = "SoCFirmwareContentCertPK",
+               .ln = "SoC Firmware content certificate public key",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = BL31_HASH_OID,
+               .sn = "APROMPatchHash",
+               .ln = "AP ROM patch hash",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = BL30_CONTENT_CERT_PK_OID,
+               .sn = "SCPFirmwareContentCertPK",
+               .ln = "SCP Firmware content certificate public key",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = BL30_HASH_OID,
+               .sn = "SCPFirmwareHash",
+               .ln = "SCP Firmware (BL30) hash (SHA256)",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = BL32_CONTENT_CERT_PK_OID,
+               .sn = "TrustedOSFirmwareContentCertPK",
+               .ln = "Trusted OS Firmware content certificate public key",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = BL32_HASH_OID,
+               .sn = "TrustedOSHash",
+               .ln = "Trusted OS (BL32) hash (SHA256)",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = BL33_CONTENT_CERT_PK_OID,
+               .sn = "NonTrustedFirmwareContentCertPK",
+               .ln = "Non-Trusted Firmware content certificate public key",
+               .type = V_ASN1_OCTET_STRING
+       },
+       {
+               .oid = BL33_HASH_OID,
+               .sn = "NonTrustedWorldBootloaderHash",
+               .ln = "Non-Trusted World (BL33) hash (SHA256)",
+               .type = V_ASN1_OCTET_STRING
+       },
+       { 0, 0, 0, 0 }
+};
diff --git a/tools/cert_create/src/tbb_key.c b/tools/cert_create/src/tbb_key.c
new file mode 100644 (file)
index 0000000..140aeda
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tbb_key.h"
+
+/*
+ * Keys used to establish the chain of trust
+ *
+ * The order of the keys must follow the enumeration specified in tbb_key.h
+ */
+key_t keys[NUM_KEYS] = {
+       {
+               .id = ROT_KEY,
+               .desc = "Root Of Trust key"
+       },
+       {
+               .id = TRUSTED_WORLD_KEY,
+               .desc = "Trusted World key"
+       },
+       {
+               .id = NON_TRUSTED_WORLD_KEY,
+               .desc = "Non Trusted World key"
+       },
+       {
+               .id = BL30_KEY,
+               .desc = "BL30 key"
+       },
+       {
+               .id = BL31_KEY,
+               .desc = "BL31 key"
+       },
+       {
+               .id = BL32_KEY,
+               .desc = "BL32 key"
+       },
+       {
+               .id = BL33_KEY,
+               .desc = "BL33 key"
+       }
+};
diff --git a/tools/fip_create/Makefile b/tools/fip_create/Makefile
new file mode 100644 (file)
index 0000000..c72bae5
--- /dev/null
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2014, 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.
+#
+
+PROJECT = fip_create
+OBJECTS = fip_create.o
+
+CFLAGS = -Wall -Werror -pedantic -std=c99
+ifeq (${DEBUG},1)
+  CFLAGS += -g -O0 -DDEBUG
+else
+  CFLAGS += -O2
+endif
+
+# Make soft links and include from local directory otherwise wrong headers
+# could get pulled in from firmware tree.
+INCLUDE_PATHS = -I.
+
+CC := gcc
+RM := rm -rf
+
+.PHONY: all clean
+
+all: ${PROJECT}
+
+${PROJECT}: ${OBJECTS} Makefile
+       @echo "  LD      $@"
+       ${Q}${CC} ${OBJECTS} -o $@
+       @echo
+       @echo "Built $@ successfully"
+       @echo
+
+%.o: %.c %.h Makefile
+       @echo "  CC      $<"
+       ${Q}${CC} -c ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
+
+clean:
+       ${Q}${RM} ${PROJECT}
+       ${Q}${RM} ${OBJECTS}
diff --git a/tools/fip_create/fip_create.c b/tools/fip_create/fip_create.c
new file mode 100644 (file)
index 0000000..c6869f9
--- /dev/null
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <getopt.h> /* getopt_long() is a GNU extention */
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "fip_create.h"
+#include "firmware_image_package.h"
+
+/* Values returned by getopt() as part of the command line parsing */
+#define OPT_TOC_ENTRY 0
+#define OPT_DUMP 1
+#define OPT_HELP 2
+
+file_info_t files[MAX_FILES];
+unsigned file_info_count = 0;
+uuid_t uuid_null = {0};
+
+/*
+ * TODO: Add ability to specify and flag different file types.
+ * Add flags to the toc_entry?
+ * const char* format_type_str[] = { "RAW", "ELF", "PIC" };
+ */
+
+/* The images used depends on the platform. */
+static entry_lookup_list_t toc_entry_lookup_list[] = {
+       { "Trusted Boot Firmware BL2", UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+         "bl2", NULL, FLAG_FILENAME },
+       { "SCP Firmware BL3-0", UUID_SCP_FIRMWARE_BL30,
+         "bl30", NULL, FLAG_FILENAME},
+       { "EL3 Runtime Firmware BL3-1", UUID_EL3_RUNTIME_FIRMWARE_BL31,
+         "bl31", NULL, FLAG_FILENAME},
+       { "Secure Payload BL3-2 (Trusted OS)", UUID_SECURE_PAYLOAD_BL32,
+         "bl32", NULL, FLAG_FILENAME},
+       { "Non-Trusted Firmware BL3-3", UUID_NON_TRUSTED_FIRMWARE_BL33,
+         "bl33", NULL, FLAG_FILENAME},
+       /* Key Certificates */
+       { "Root Of Trust key certificate", UUID_ROT_KEY_CERT,
+         "rot-cert", NULL, FLAG_FILENAME },
+       { "Trusted key certificate", UUID_TRUSTED_KEY_CERT,
+         "trusted-key-cert", NULL, FLAG_FILENAME},
+       { "SCP Firmware BL3-0 key certificate", UUID_SCP_FIRMWARE_BL30_KEY_CERT,
+         "bl30-key-cert", NULL, FLAG_FILENAME},
+       { "EL3 Runtime Firmware BL3-1 key certificate", UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT,
+         "bl31-key-cert", NULL, FLAG_FILENAME},
+       { "Secure Payload BL3-2 (Trusted OS) key certificate", UUID_SECURE_PAYLOAD_BL32_KEY_CERT,
+         "bl32-key-cert", NULL, FLAG_FILENAME},
+       { "Non-Trusted Firmware BL3-3 key certificate", UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT,
+         "bl33-key-cert", NULL, FLAG_FILENAME},
+       /* Content certificates */
+       { "Trusted Boot Firmware BL2 certificate", UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT,
+         "bl2-cert", NULL, FLAG_FILENAME },
+       { "SCP Firmware BL3-0 certificate", UUID_SCP_FIRMWARE_BL30_CERT,
+         "bl30-cert", NULL, FLAG_FILENAME},
+       { "EL3 Runtime Firmware BL3-1 certificate", UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT,
+         "bl31-cert", NULL, FLAG_FILENAME},
+       { "Secure Payload BL3-2 (Trusted OS) certificate", UUID_SECURE_PAYLOAD_BL32_CERT,
+         "bl32-cert", NULL, FLAG_FILENAME},
+       { "Non-Trusted Firmware BL3-3 certificate", UUID_NON_TRUSTED_FIRMWARE_BL33_CERT,
+         "bl33-cert", NULL, FLAG_FILENAME},
+       { NULL, {0}, 0 }
+};
+
+
+/* Return 0 for equal uuids */
+static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2)
+{
+       return memcmp(uuid1, uuid2, sizeof(uuid_t));
+}
+
+
+static inline void copy_uuid(uuid_t *to_uuid, const uuid_t *from_uuid)
+{
+       memcpy(to_uuid, from_uuid, sizeof(uuid_t));
+}
+
+
+static void print_usage(void)
+{
+       entry_lookup_list_t *entry = toc_entry_lookup_list;
+
+       printf("Usage: fip_create [options] FIP_FILENAME\n\n");
+       printf("\tThis tool is used to create a Firmware Image Package.\n\n");
+       printf("Options:\n");
+       printf("\t--help: Print this help message and exit\n");
+       printf("\t--dump: Print contents of FIP\n\n");
+       printf("\tComponents that can be added/updated:\n");
+       for (; entry->command_line_name != NULL; entry++) {
+               printf("\t--%s%s\t\t%s",
+                      entry->command_line_name,
+                      (entry->flags & FLAG_FILENAME) ? " FILENAME" : "",
+                      entry->name);
+               printf("\n");
+       }
+}
+
+
+static entry_lookup_list_t *get_entry_lookup_from_uuid(const uuid_t *uuid)
+{
+       unsigned int lookup_index = 0;
+
+       while (toc_entry_lookup_list[lookup_index].command_line_name != NULL) {
+               if (compare_uuids(&toc_entry_lookup_list[lookup_index].name_uuid,
+                   uuid) == 0) {
+                       return &toc_entry_lookup_list[lookup_index];
+               }
+               lookup_index++;
+       }
+       return NULL;
+}
+
+
+static file_info_t *find_file_info_from_uuid(const uuid_t *uuid)
+{
+       int index;
+
+       for (index = 0; index < file_info_count; index++) {
+               if (compare_uuids(&files[index].name_uuid, uuid) == 0) {
+                       return &files[index];
+               }
+       }
+       return NULL;
+}
+
+
+static int add_file_info_entry(entry_lookup_list_t *lookup_entry, char *filename)
+{
+       file_info_t *file_info_entry;
+       int error;
+       struct stat file_status;
+       bool is_new_entry = false;
+
+       /* Check if the file already exists in the array */
+       file_info_entry = find_file_info_from_uuid(&lookup_entry->name_uuid);
+       if (file_info_entry == NULL) {
+               /* The file does not exist in the current list; take the next
+                * one available in the file_info list. 'file_info_count' is
+                * incremented in case of successful update at the end of the
+                * function.
+                */
+               file_info_entry = &files[file_info_count];
+               is_new_entry = true;
+
+               /* Copy the uuid for the new entry */
+               copy_uuid(&file_info_entry->name_uuid,
+                         &lookup_entry->name_uuid);
+       }
+
+       /* Get the file information for entry */
+       error = stat(filename, &file_status);
+       if (error != 0) {
+               printf("Error: Cannot get information for file \"%s\": %s\n",
+                       filename, strerror(errno));
+               return errno;
+       }
+       file_info_entry->filename = filename;
+       file_info_entry->size = (unsigned int)file_status.st_size;
+       file_info_entry->entry = lookup_entry;
+
+       /* Increment the file_info counter on success if it is new file entry */
+       if (is_new_entry) {
+               file_info_count++;
+
+               /* Ensure we do not overflow */
+               if (file_info_count > MAX_FILES) {
+                       printf("ERROR: Too many files in Package\n");
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+
+static int write_memory_to_file(const uint8_t *start, const char *filename,
+               unsigned int size)
+{
+       FILE *stream;
+       unsigned int bytes_written;
+
+       /* Write the packed file out to the filesystem */
+       stream = fopen(filename, "r+");
+       if (stream == NULL) {
+               stream = fopen(filename, "w");
+               if (stream == NULL) {
+                       printf("Error: Cannot create output file \"%s\": %s\n",
+                              filename, strerror(errno));
+                       return errno;
+               } else {
+                       printf("Creating \"%s\"\n", filename);
+               }
+       } else {
+               printf("Updating \"%s\"\n", filename);
+       }
+
+       bytes_written = fwrite(start, sizeof(uint8_t), size, stream);
+       fclose(stream);
+
+       if (bytes_written != size) {
+               printf("Error: Incorrect write for file \"%s\": Size=%u,"
+                       "Written=%u bytes.\n", filename, size, bytes_written);
+               return EIO;
+       }
+
+       return 0;
+}
+
+
+static int read_file_to_memory(void *memory, const file_info_t *info)
+{
+       FILE *stream;
+       unsigned int bytes_read;
+
+       /* If the file_info is defined by its filename we need to load it */
+       if (info->filename) {
+               /* Read image from filesystem */
+               stream = fopen(info->filename, "r");
+               if (stream == NULL) {
+                       printf("Error: Cannot open file \"%s\": %s\n",
+                               info->filename, strerror(errno));
+                       return errno;
+               }
+
+               bytes_read = (unsigned int)fread(memory, sizeof(uint8_t),
+                                                info->size, stream);
+               fclose(stream);
+               if (bytes_read != info->size) {
+                       printf("Error: Incomplete read for file \"%s\":"
+                               "Size=%u, Read=%u bytes.\n", info->filename,
+                               info->size, bytes_read);
+                       return EIO;
+               }
+       } else {
+               if (info->image_buffer == NULL) {
+                       printf("ERROR: info->image_buffer = NULL\n");
+                       return EIO;
+               }
+               /* Copy the file_info buffer (extracted from the existing
+                * image package) into the new buffer.
+                */
+               memcpy(memory, info->image_buffer, info->size);
+       }
+
+       return 0;
+}
+
+
+/* Create the image package file */
+static int pack_images(const char *fip_filename)
+{
+       int status;
+       uint8_t *fip_base_address;
+       void *entry_address;
+       fip_toc_header_t *toc_header;
+       fip_toc_entry_t *toc_entry;
+       unsigned int entry_index;
+       unsigned int toc_size;
+       unsigned int fip_size;
+       unsigned int entry_offset_address;
+       unsigned int payload_size = 0;
+
+       /* Validate filename */
+       if ((fip_filename == NULL) || (strcmp(fip_filename, "") == 0)) {
+               return EINVAL;
+       }
+
+       /* Payload size calculation */
+       for (entry_index = 0; entry_index < file_info_count; entry_index++) {
+               payload_size += files[entry_index].size;
+       }
+
+       /* Allocate memory for entire package, including the final null entry */
+       toc_size = (sizeof(fip_toc_header_t) +
+                   (sizeof(fip_toc_entry_t) * (file_info_count + 1)));
+       fip_size = toc_size + payload_size;
+       fip_base_address = malloc(fip_size);
+       if (fip_base_address == NULL) {
+               printf("Error: Can't allocate enough memory to create package."
+                      "Process aborted.\n");
+               return ENOMEM;
+       }
+       memset(fip_base_address, 0, fip_size);
+
+       /* Create ToC Header */
+       toc_header = (fip_toc_header_t *)fip_base_address;
+       toc_header->name = TOC_HEADER_NAME;
+       toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER;
+       toc_header->flags = 0;
+
+       toc_entry = (fip_toc_entry_t *)(fip_base_address +
+                                     sizeof(fip_toc_header_t));
+
+       /* Calculate the starting address of the first image, right after the
+        * toc header.
+        */
+       entry_offset_address = toc_size;
+       entry_index = 0;
+
+       /* Create the package in memory. */
+       for (entry_index = 0; entry_index < file_info_count; entry_index++) {
+               entry_address = (fip_base_address + entry_offset_address);
+               status = read_file_to_memory(entry_address,
+                                            &files[entry_index]);
+               if (status != 0) {
+                       printf("Error: While reading \"%s\" from filesystem.\n",
+                               files[entry_index].filename);
+                       return status;
+               }
+
+               copy_uuid(&toc_entry->uuid, &files[entry_index].name_uuid);
+               toc_entry->offset_address = entry_offset_address;
+               toc_entry->size = files[entry_index].size;
+               toc_entry->flags = 0;
+               entry_offset_address += toc_entry->size;
+               toc_entry++;
+       }
+
+       /* Add a null uuid entry to mark the end of toc entries */
+       copy_uuid(&toc_entry->uuid, &uuid_null);
+       toc_entry->offset_address = entry_offset_address;
+       toc_entry->size = 0;
+       toc_entry->flags = 0;
+
+       /* Save the package to file */
+       status = write_memory_to_file(fip_base_address, fip_filename, fip_size);
+       if (status != 0) {
+               printf("Error: Failed while writing package to file \"%s\" "
+                       "with status=%d.\n", fip_filename, status);
+               return status;
+       }
+       return 0;
+}
+
+
+static void dump_toc(void)
+{
+       unsigned int index = 0;
+       unsigned int image_offset;
+       unsigned int image_size = 0;
+
+       image_offset = sizeof(fip_toc_header_t) +
+               (sizeof(fip_toc_entry_t) * (file_info_count + 1));
+
+       printf("Firmware Image Package ToC:\n");
+       printf("---------------------------\n");
+       for (index = 0; index < file_info_count; index++) {
+               if (files[index].entry) {
+                       printf("- %s: ", files[index].entry->name);
+               } else {
+                       printf("- Unknown entry: ");
+               }
+               image_size = files[index].size;
+
+               printf("offset=0x%X, size=0x%X\n", image_offset, image_size);
+               image_offset += image_size;
+
+               if (files[index].filename) {
+                       printf("  file: '%s'\n", files[index].filename);
+               }
+       }
+       printf("---------------------------\n");
+}
+
+
+/* Read and load existing package into memory. */
+static int parse_fip(const char *fip_filename)
+{
+       FILE *fip;
+       char *fip_buffer;
+       char *fip_buffer_end;
+       int fip_size, read_fip_size;
+       fip_toc_header_t *toc_header;
+       fip_toc_entry_t *toc_entry;
+       bool found_last_toc_entry = false;
+       file_info_t *file_info_entry;
+       int status = -1;
+       struct stat st;
+
+       fip = fopen(fip_filename, "r");
+       if (fip == NULL) {
+               /* If the fip does not exist just return, it should not be
+                * considered as an error. The package will be created later
+                */
+               status = 0;
+               goto parse_fip_return;
+       }
+
+       if (stat(fip_filename, &st) != 0) {
+               status = errno;
+               goto parse_fip_fclose;
+       } else {
+               fip_size = (int)st.st_size;
+       }
+
+       /* Allocate a buffer to read the package */
+       fip_buffer = (char *)malloc(fip_size);
+       if (fip_buffer == NULL) {
+               printf("ERROR: Cannot allocate %d bytes.\n", fip_size);
+               status = errno;
+               goto parse_fip_fclose;
+       }
+       fip_buffer_end = fip_buffer + fip_size;
+
+       /* Read the file */
+       read_fip_size = fread(fip_buffer, sizeof(char), fip_size, fip);
+       if (read_fip_size != fip_size) {
+               printf("ERROR: Cannot read the FIP.\n");
+               status = EIO;
+               goto parse_fip_free;
+       }
+       fclose(fip);
+       fip = NULL;
+
+       /* The package must at least contain the ToC Header */
+       if (fip_size < sizeof(fip_toc_header_t)) {
+               printf("ERROR: Given FIP is smaller than the ToC header.\n");
+               status = EINVAL;
+               goto parse_fip_free;
+       }
+       /* Set the ToC Header at the base of the buffer */
+       toc_header = (fip_toc_header_t *)fip_buffer;
+       /* The first toc entry should be just after the ToC header */
+       toc_entry = (fip_toc_entry_t *)(toc_header + 1);
+
+       /* While the ToC entry is contained into the buffer */
+       int cnt = 0;
+       while (((char *)toc_entry + sizeof(fip_toc_entry_t)) < fip_buffer_end) {
+               cnt++;
+               /* Check if the ToC Entry is the last one */
+               if (compare_uuids(&toc_entry->uuid, &uuid_null) == 0) {
+                       found_last_toc_entry = true;
+                       status = 0;
+                       break;
+               }
+
+               /* Add the entry into file_info */
+
+               /* Get the new entry in the array and clear it */
+               file_info_entry = &files[file_info_count++];
+               memset(file_info_entry, 0, sizeof(file_info_t));
+
+               /* Copy the info from the ToC entry */
+               copy_uuid(&file_info_entry->name_uuid, &toc_entry->uuid);
+               file_info_entry->image_buffer = fip_buffer +
+                 toc_entry->offset_address;
+               file_info_entry->size = toc_entry->size;
+
+               /* Check if there is a corresponding entry in lookup table */
+               file_info_entry->entry =
+                 get_entry_lookup_from_uuid(&toc_entry->uuid);
+
+               /* Go to the next ToC entry */
+               toc_entry++;
+       }
+
+       if (!found_last_toc_entry) {
+               printf("ERROR: Given FIP does not have an end ToC entry.\n");
+               status = EINVAL;
+               goto parse_fip_free;
+       } else {
+               /* All is well, we should not free any of the loaded images */
+               goto parse_fip_fclose;
+       }
+
+ parse_fip_free:
+       if (fip_buffer != NULL) {
+               free(fip_buffer);
+               fip_buffer = NULL;
+       }
+
+ parse_fip_fclose:
+       if (fip != NULL) {
+               fclose(fip);
+       }
+
+ parse_fip_return:
+       return status;
+}
+
+
+/* Parse all command-line options and return the FIP name if present. */
+static char *get_filename(int argc, char **argv, struct option *options)
+{
+       int c;
+       char *filename = NULL;
+
+       /* Reset option pointer so we parse all args. starts at 1.
+        * The filename is the only argument that does not have an option flag.
+        */
+       optind = 1;
+       while (1) {
+               c = getopt_long(argc, argv, "", options, NULL);
+               if (c == -1)
+                       break;
+
+               if (c == '?') {
+                       /* Failed to parse an option. Fail. */
+                       return NULL;
+               }
+       }
+
+       /* Only one argument left then it is the filename.
+        * We dont expect any other options
+        */
+       if (optind + 1 == argc)
+               filename = argv[optind];
+
+       return filename;
+}
+
+
+/* Work through command-line options */
+static int parse_cmdline(int argc, char **argv, struct option *options,
+                        int *do_pack)
+{
+       int c;
+       int status = 0;
+       int option_index = 0;
+       entry_lookup_list_t *lookup_entry;
+       int do_dump = 0;
+
+       /* restart parse to process all options. starts at 1. */
+       optind = 1;
+       while (1) {
+               c = getopt_long(argc, argv, "", options, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case OPT_TOC_ENTRY:
+                       if (optarg) {
+                               /* Does the option expect a filename. */
+                               lookup_entry = &toc_entry_lookup_list[option_index];
+                               if (lookup_entry->flags & FLAG_FILENAME) {
+                                       status = add_file_info_entry(lookup_entry, optarg);
+                                       if (status != 0) {
+                                               printf("Failed to process %s\n",
+                                                      options[option_index].name);
+                                               return status;
+                                       } else {
+                                               /* Update package */
+                                               *do_pack = 1;
+                                       }
+                               }
+                       }
+                       break;
+
+               case OPT_DUMP:
+                       do_dump = 1;
+                       continue;
+
+               case OPT_HELP:
+                       print_usage();
+                       exit(0);
+
+               default:
+                       /* Unrecognised options are caught in get_filename() */
+                       break;
+               }
+       }
+
+
+       /* Do not dump toc if we have an error as it could hide the error */
+       if ((status == 0) && (do_dump)) {
+               dump_toc();
+       }
+
+       return status;
+
+}
+
+int main(int argc, char **argv)
+{
+       int i;
+       int status;
+       char *fip_filename;
+       int do_pack = 0;
+
+       /* Clear file list table. */
+       memset(files, 0, sizeof(files));
+
+       /* Initialise for getopt_long().
+        * Use image table as defined at top of file to get options.
+        * Add 'dump' option, 'help' option and end marker.
+        */
+       static struct option long_options[(sizeof(toc_entry_lookup_list)/
+                                          sizeof(entry_lookup_list_t)) + 2];
+
+       for (i = 0;
+            /* -1 because we dont want to process end marker in toc table */
+            i < sizeof(toc_entry_lookup_list)/sizeof(entry_lookup_list_t) - 1;
+            i++) {
+               long_options[i].name = toc_entry_lookup_list[i].command_line_name;
+               /* The only flag defined at the moment is for a FILENAME */
+               long_options[i].has_arg = toc_entry_lookup_list[i].flags ? 1 : 0;
+               long_options[i].flag = 0;
+               long_options[i].val = OPT_TOC_ENTRY;
+       }
+
+       /* Add '--dump' option */
+       long_options[i].name = "dump";
+       long_options[i].has_arg = 0;
+       long_options[i].flag = 0;
+       long_options[i].val = OPT_DUMP;
+
+       /* Add '--help' option */
+       long_options[++i].name = "help";
+       long_options[i].has_arg = 0;
+       long_options[i].flag = 0;
+       long_options[i].val = OPT_HELP;
+
+       /* Zero the last entry (required) */
+       long_options[++i].name = 0;
+       long_options[i].has_arg = 0;
+       long_options[i].flag = 0;
+       long_options[i].val = 0;
+
+#ifdef DEBUG
+       /* Print all supported options */
+       for (i = 0; i < sizeof(long_options)/sizeof(struct option); i++) {
+               printf("long opt (%d) : name = %s\n", i, long_options[i].name);
+       }
+#endif /* DEBUG */
+
+       /* As the package may already exist and is to be updated we need to get
+        * the filename from the arguments and load from it.
+        * NOTE: As this is the first function to look at the program arguments
+        * it causes a failure if bad options were provided.
+        */
+       fip_filename = get_filename(argc, argv, long_options);
+
+       /* Try to open the file and load it into memory */
+       if (fip_filename != NULL) {
+               status = parse_fip(fip_filename);
+               if (status != 0) {
+                       return status;
+               }
+       }
+
+       /* Work through provided program arguments and perform actions */
+       status = parse_cmdline(argc, argv, long_options, &do_pack);
+       if (status != 0) {
+               return status;
+       };
+
+       if (fip_filename == NULL) {
+               printf("ERROR: Missing FIP filename\n");
+               print_usage();
+               return 0;
+       }
+
+       /* Processed all command line options. Create/update the package if
+        * required.
+        */
+       if (do_pack) {
+               status = pack_images(fip_filename);
+               if (status != 0) {
+                       printf("Failed to create package (status = %d).\n",
+                              status);
+               }
+       }
+
+       return status;
+}
diff --git a/tools/fip_create/fip_create.h b/tools/fip_create/fip_create.h
new file mode 100644 (file)
index 0000000..3258335
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FIP_CREATE_H__
+#define __FIP_CREATE_H__
+
+#include <stdint.h>
+#include <uuid.h>
+
+#define MAX_FILES                      20
+
+/* TODO: Update this number as required */
+#define TOC_HEADER_SERIAL_NUMBER       0x12345678
+
+#define FLAG_FILENAME                  (1 << 0)
+
+typedef struct entry_lookup_list {
+       const char              *name;
+       uuid_t                   name_uuid;
+       const char              *command_line_name;
+       struct file_info        *info;
+       unsigned int             flags;
+} entry_lookup_list_t;
+
+typedef struct file_info {
+       uuid_t                   name_uuid;
+       const char              *filename;
+       unsigned int             size;
+       void                    *image_buffer;
+       entry_lookup_list_t     *entry;
+} file_info_t;
+
+#endif /* __FIP_CREATE_H__ */
diff --git a/tools/fip_create/firmware_image_package.h b/tools/fip_create/firmware_image_package.h
new file mode 120000 (symlink)
index 0000000..cc61903
--- /dev/null
@@ -0,0 +1 @@
+../../include/common/firmware_image_package.h
\ No newline at end of file
diff --git a/tools/fip_create/uuid.h b/tools/fip_create/uuid.h
new file mode 120000 (symlink)
index 0000000..c77762f
--- /dev/null
@@ -0,0 +1 @@
+../../include/stdlib/sys/uuid.h
\ No newline at end of file