From e5bc1ff112d6645065ee29f16891f91da7f8e42d Mon Sep 17 00:00:00 2001 From: Sarat Chand Savitala Date: Wed, 7 Jan 2015 17:53:46 +0530 Subject: [PATCH] sw_apps:zynqmp_fsbl: Publishing zynqmp FSBL to HEAD of embeddedsw Initial publishing of zynqmp_fsbl in the embeddedsw repo. Signed-off-by: Sarat Chand Savitala --- lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.mss | 44 + lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl | 126 ++ lib/sw_apps/zynqmp_fsbl/src/Makefile | 107 ++ lib/sw_apps/zynqmp_fsbl/src/lscript.ld | 311 +++++ lib/sw_apps/zynqmp_fsbl/src/lscript_a53.ld | 333 ++++++ .../zynqmp_fsbl/src/xfsbl_authentication.c | 425 +++++++ .../zynqmp_fsbl/src/xfsbl_authentication.h | 131 ++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_config.h | 147 +++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.c | 182 +++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.h | 275 +++++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_debug.h | 102 ++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_error.h | 164 +++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S | 141 +++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c | 867 ++++++++++++++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.c | 99 ++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.h | 84 ++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h | 540 +++++++++ .../zynqmp_fsbl/src/xfsbl_image_header.c | 733 ++++++++++++ .../zynqmp_fsbl/src/xfsbl_image_header.h | 249 ++++ .../zynqmp_fsbl/src/xfsbl_initialization.c | 721 +++++++++++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.c | 416 +++++++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h | 165 +++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.c | 489 ++++++++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.h | 87 ++ .../zynqmp_fsbl/src/xfsbl_misc_drivers.c | 222 ++++ .../zynqmp_fsbl/src/xfsbl_misc_drivers.h | 117 ++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_nand.c | 159 +++ .../zynqmp_fsbl/src/xfsbl_partition_load.c | 1056 +++++++++++++++++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c | 640 ++++++++++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h | 193 +++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_rsa_sha.c | 497 ++++++++ lib/sw_apps/zynqmp_fsbl/src/xfsbl_sd.c | 189 +++ 32 files changed, 10011 insertions(+) create mode 100755 lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.mss create mode 100755 lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl create mode 100644 lib/sw_apps/zynqmp_fsbl/src/Makefile create mode 100644 lib/sw_apps/zynqmp_fsbl/src/lscript.ld create mode 100644 lib/sw_apps/zynqmp_fsbl/src/lscript_a53.ld create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_authentication.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_authentication.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_config.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_debug.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_error.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_initialization.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_nand.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_partition_load.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_rsa_sha.c create mode 100644 lib/sw_apps/zynqmp_fsbl/src/xfsbl_sd.c diff --git a/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.mss b/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.mss new file mode 100755 index 00000000..96fde6c7 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.mss @@ -0,0 +1,44 @@ +#/****************************************************************************** +#* +#* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +#* +#* Permission is hereby granted, free of charge, to any person obtaining a copy +#* of this software and associated documentation files (the "Software"), to deal +#* in the Software without restriction, including without limitation the rights +#* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#* copies of the Software, and to permit persons to whom the Software is +#* furnished to do so, subject to the following conditions: +#* +#* The above copyright notice and this permission notice shall be included in +#* all copies or substantial portions of the Software. +#* +#* Use of the Software is limited solely to applications: +#* (a) running on a Xilinx device, or +#* (b) that interact with a Xilinx device through a bus or interconnect. +#* +#* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +#* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +#* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +#* SOFTWARE. +#* +#* Except as contained in this notice, the name of the Xilinx shall not be used +#* in advertising or otherwise to promote the sale, use or other dealings in +#* this Software without prior written authorization from Xilinx. +#* +#******************************************************************************/ + +PARAMETER VERSION = 2.2.0 + + +BEGIN OS + PARAMETER OS_NAME = standalone + PARAMETER STDIN = * + PARAMETER STDOUT = * +END + +BEGIN LIBRARY + PARAMETER LIBRARY_NAME = xilffs +END \ No newline at end of file diff --git a/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl b/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl new file mode 100755 index 00000000..43389b72 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl @@ -0,0 +1,126 @@ +#/****************************************************************************** +#* +#* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +#* +#* Permission is hereby granted, free of charge, to any person obtaining a copy +#* of this software and associated documentation files (the "Software"), to deal +#* in the Software without restriction, including without limitation the rights +#* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#* copies of the Software, and to permit persons to whom the Software is +#* furnished to do so, subject to the following conditions: +#* +#* The above copyright notice and this permission notice shall be included in +#* all copies or substantial portions of the Software. +#* +#* Use of the Software is limited solely to applications: +#* (a) running on a Xilinx device, or +#* (b) that interact with a Xilinx device through a bus or interconnect. +#* +#* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +#* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +#* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +#* SOFTWARE. +#* +#* Except as contained in this notice, the name of the Xilinx shall not be used +#* in advertising or otherwise to promote the sale, use or other dealings in +#* this Software without prior written authorization from Xilinx. +#* +#******************************************************************************/ + +proc swapp_get_name {} { + return "Zynq MP FSBL"; +} + +proc swapp_get_description {} { + return "First Stage Bootloader (FSBL) for Zynq MP. The FSBL configures the FPGA with HW bit stream (if it exists) \ + and loads the Operating System (OS) Image or Standalone (SA) Image or 2nd Stage Boot Loader image from the \ + non-volatile memory (NAND/SD/QSPI) to RAM (DDR) and takes A5x/R5 out of reset. It supports multiple partitions, \ + and each partition can be a code image or a bit stream."; +} + +proc check_standalone_os {} { + set oslist [get_os]; + + if { [llength $oslist] != 1 } { + return 0; + } + set os [lindex $oslist 0]; + + if { $os != "standalone" } { + error "This application is supported only on the Standalone Board Support Package."; + } +} + +proc swapp_is_supported_sw {} { + # make sure we are using standalone OS + #check_standalone_os; + + # make sure xilffs is available + set librarylist [get_libs -filter "NAME==xilffs"]; + + if { [llength $librarylist] == 0 } { + error "This application requires xilffs library in the Board Support Package."; + } elseif { [llength $librarylist] > 1} { + error "Multiple xilffs libraries present in the Board Support Package." + } +} + +proc swapp_is_supported_hw {} { + + # check processor type + set proc_instance [get_sw_processor]; + set hw_processor [get_property HW_INSTANCE $proc_instance] + + set proc_type [get_property IP_NAME [get_cells $hw_processor]]; + + if { $proc_type != "pss_cortexr5" && $proc_type != "pss_cortexa53" } { + error "This application is supported only for CortexA53/CortexR5 processors."; + } + + return 1; +} + + +proc get_stdout {} { + set os [get_os]; + set stdout [get_property CONFIG.STDOUT $os]; + return $stdout; +} + +proc check_stdout_hw {} { + set ps_uarts [get_cells -filter "IP_NAME=pss_uart"]; +} + +proc swapp_generate {} { + + #delete unnecessary files (only pss_init.c & pss_init.h are needed for FSBL) + set file "pss_init.html" + if { [file exists $file] } { + file delete -force $file + } + + set file "pss_init.tcl" + if { [file exists $file] } { + file delete -force $file + } + + set file "pss_init_gpl.c" + if { [file exists $file] } { + file delete -force $file + } + + set file "pss_init_gpl.h" + if { [file exists $file] } { + file delete -force $file + } + +} + +proc swapp_get_linker_constraints {} { + + # don't generate a linker script. fsbl has its own linker script + return "lscript no"; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/Makefile b/lib/sw_apps/zynqmp_fsbl/src/Makefile new file mode 100644 index 00000000..309a8d6d --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/Makefile @@ -0,0 +1,107 @@ +#/****************************************************************************** +#* +#* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +#* +#* Permission is hereby granted, free of charge, to any person obtaining a copy +#* of this software and associated documentation files (the "Software"), to deal +#* in the Software without restriction, including without limitation the rights +#* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#* copies of the Software, and to permit persons to whom the Software is +#* furnished to do so, subject to the following conditions: +#* +#* The above copyright notice and this permission notice shall be included in +#* all copies or substantial portions of the Software. +#* +#* Use of the Software is limited solely to applications: +#* (a) running on a Xilinx device, or +#* (b) that interact with a Xilinx device through a bus or interconnect. +#* +#* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +#* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +#* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +#* SOFTWARE. +#* +#* Except as contained in this notice, the name of the Xilinx shall not be used +#* in advertising or otherwise to promote the sale, use or other dealings in +#* this Software without prior written authorization from Xilinx. +#* +#******************************************************************************/ + +PROC ?= a53 +CROSS ?= +BSP_DIR := . + +ECFLAGS := +LSCRIPT := -Tlscript_a53.ld +BOARD := +EXEC := ron_a53_fsbl.elf + +c_SOURCES := $(wildcard *.c) +S_SOURCES := $(wildcard *.S) +s_SOURCES := $(wildcard *.s) +INCLUDES := $(wildcard *.h) +OBJS := $(patsubst %.c, %.o, $(c_SOURCES)) +OBJS += $(patsubst %.S, %.o, $(S_SOURCES)) +OBJS += $(patsubst %.s, %.o, $(s_SOURCES)) + +ifeq '$(PROC)' 'r5' +CROSS := +CC := $(CROSS)arm-none-eabi-gcc +AS := $(CROSS)arm-none-eabi-gcc +LINKER := $(CROSS)arm-none-eabi-gcc +DUMP := $(CROSS)arm-none-eabi-objdump -xSD +CFLAGS = -Wall -O0 -g3 -fmessage-length=0 \ + -mcpu=cortex-r5 -mfloat-abi=softfp +LSCRIPT := -Tlscript.ld +EXEC := ron_r5_fsbl.elf +INCLUDEPATH := -I$(BSP_DIR)/ps8_cortexr5_0/include -I. +LIBPATH := $(BSP_DIR)/ps8_cortexr5_0/lib +LDFLAGS := -Wl,--start-group,-lxil,-lxilffs,-lgcc,-lc,--end-group -L$(LIBPATH) -L./ -Wl,--build-id=none +endif + +ifeq '$(PROC)' 'a53' +CROSS := +CC := $(CROSS)aarch64-none-elf-gcc +AS := $(CROSS)aarch64-none-elf-gcc +LINKER := $(CROSS)aarch64-none-elf-gcc +DUMP := $(CROSS)aarch64-none-elf-objdump -xSD +CFLAGS = -Wall -O0 -g3 -fmessage-length=0 \ + -march=armv8-a -DXFSBL_A53 +LSCRIPT := -Tlscript_a53.ld +EXEC := ron_a53_fsbl.elf +INCLUDEPATH := -I$(BSP_DIR)/ps8_cortexa53_0/include -I. +LIBPATH := $(BSP_DIR)/ps8_cortexa53_0/lib +LDFLAGS := -Wl,--start-group,-lxil,-lxilffs,-lgcc,-lc,--end-group -L$(LIBPATH) -L./ -Wl,--build-id=none +endif + +ifeq "$(CC)" "armcc" +AS=armasm +LINKER=armlink +CFLAGS += -c --c99 --wchar32 +CC_FLAGS += --cpu=Cortex-A9 --fpu=VFPv3_FP16 +LDFLAGS = --entry=_vector_table "$(LIBPATH)/libxil.a(*.o)" --no_search_dynamic_libraries --userlibpath=$(LIBPATH),. --library=xil +LSCRIPT = --scatter="scatter.scat" +endif + +all: $(EXEC) + +$(EXEC): $(OBJS) $(INCLUDES) + $(LINKER) -o $@ $(OBJS) $(CC_FLAGS) $(LDFLAGS) $(LSCRIPT) + $(DUMP) $(EXEC) > dump + cp $(EXEC) fsbl.elf + rm -rf $(OBJS) + +%.o:%.c + $(CC) $(CC_FLAGS) $(CFLAGS) $(ECFLAGS) -c $< -o $@ $(INCLUDEPATH) + +%.o:%.S + $(AS) $(CC_FLAGS) $(CFLAGS) $(ECFLAGS) -c $< -o $@ $(INCLUDEPATH) + +%.o:%.s + $(AS) $(CC_FLAGS) $(CFLAGS) $(ECFLAGS) -c $< -o $@ $(INCLUDEPATH) + +clean: + rm -rf $(OBJS) *.elf dump diff --git a/lib/sw_apps/zynqmp_fsbl/src/lscript.ld b/lib/sw_apps/zynqmp_fsbl/src/lscript.ld new file mode 100644 index 00000000..b69bcbe8 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/lscript.ld @@ -0,0 +1,311 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*******************************************************************/ +/* */ +/* Description : FSBL R5 Linker Script */ +/* */ +/*******************************************************************/ + +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x4000; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 1024; + +_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024; +_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048; +_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024; +_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024; +_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024; + +/* Define Memories in the system */ + +MEMORY +{ + ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0xfffc0000, LENGTH = 0x0002FF00 + ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xffff0040, LENGTH = 0x0000FE00 +} + +/* Specify the default entry point to the program */ + +ENTRY(_vector_table) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +.text : { + *(.vectors) + *(.boot) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + *(.gnu_warning) + *(.gcc_execpt_table) + *(.glue_7) + *(.glue_7t) + *(.vfp11_veneer) + *(.ARM.extab) + *(.gnu.linkonce.armextab.*) +} > ps7_ram_0_S_AXI_BASEADDR + +.init : { + KEEP (*(.init)) +} > ps7_ram_0_S_AXI_BASEADDR + +.fini : { + KEEP (*(.fini)) +} > ps7_ram_0_S_AXI_BASEADDR + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.rodata1 : { + __rodata1_start = .; + *(.rodata1) + *(.rodata1.*) + __rodata1_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.sdata2 : { + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + __sdata2_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.data : { + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.jcr) + *(.got) + *(.got.plt) + __data_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.data1 : { + __data1_start = .; + *(.data1) + *(.data1.*) + __data1_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.got : { + *(.got) +} > ps7_ram_0_S_AXI_BASEADDR + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + ___DTORS_END___ = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.fixup : { + __fixup_start = .; + *(.fixup) + __fixup_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.eh_frame : { + *(.eh_frame) +} > ps7_ram_0_S_AXI_BASEADDR + +.eh_framehdr : { + __eh_framehdr_start = .; + *(.eh_framehdr) + __eh_framehdr_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.gcc_except_table : { + *(.gcc_except_table) +} > ps7_ram_0_S_AXI_BASEADDR + +.mmu_tbl (ALIGN(16384)) : { + __mmu_tbl_start = .; + *(.mmu_tbl) + __mmu_tbl_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + *(.gnu.linkonce.armexidix.*.*) + __exidx_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.preinit_array : { + __preinit_array_start = .; + KEEP (*(SORT(.preinit_array.*))) + KEEP (*(.preinit_array)) + __preinit_array_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.init_array : { + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.fini_array : { + __fini_array_start = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.ARM.attributes : { + __ARM.attributes_start = .; + *(.ARM.attributes) + __ARM.attributes_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.sdata : { + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.sbss (NOLOAD) : { + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + __sbss_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > ps7_ram_0_S_AXI_BASEADDR + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > ps7_ram_1_S_AXI_BASEADDR + +.bss (NOLOAD) : { + __bss_start = .; + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + __bss_end = .; + __bss_end__ = .; +} > ps7_ram_1_S_AXI_BASEADDR + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(16); + _heap = .; + HeapBase = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; + HeapLimit = .; +} > ps7_ram_1_S_AXI_BASEADDR + +.stack (NOLOAD) : { + . = ALIGN(16); + _stack_end = .; + . += _STACK_SIZE; + _stack = .; + __stack = _stack; + . = ALIGN(16); + _irq_stack_end = .; + . += _IRQ_STACK_SIZE; + __irq_stack = .; + _supervisor_stack_end = .; + . += _SUPERVISOR_STACK_SIZE; + . = ALIGN(16); + __supervisor_stack = .; + _abort_stack_end = .; + . += _ABORT_STACK_SIZE; + . = ALIGN(16); + __abort_stack = .; + _fiq_stack_end = .; + . += _FIQ_STACK_SIZE; + . = ALIGN(16); + __fiq_stack = .; + _undef_stack_end = .; + . += _UNDEF_STACK_SIZE; + . = ALIGN(16); + __undef_stack = .; +} > ps7_ram_1_S_AXI_BASEADDR + +_end = .; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/lscript_a53.ld b/lib/sw_apps/zynqmp_fsbl/src/lscript_a53.ld new file mode 100644 index 00000000..aa940f4c --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/lscript_a53.ld @@ -0,0 +1,333 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*******************************************************************/ +/* */ +/* Description : FSBL A53 Linker Script */ +/* */ +/*******************************************************************/ +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x4000; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 1024; + +_EL0_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024; +_EL1_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048; +_EL2_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024; +_EL3_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024; + +/* Define Memories in the system */ + +MEMORY +{ + ps8_ocm_ram_0_S_AXI_BASEADDR : ORIGIN = 0xFFFC0000, LENGTH = 0x0002FF00 + ps8_ocm_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0040, LENGTH = 0x0000FE00 +} + +/* Specify the default entry point to the program */ + +ENTRY(_vector_table) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +.text : { + *(.vectors) + *(.boot) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + *(.gnu_warning) + *(.gcc_execpt_table) + *(.glue_7) + *(.glue_7t) + *(.ARM.extab) + *(.gnu.linkonce.armextab.*) +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.init (ALIGN(64)): { + KEEP (*(.init)) +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.fini (ALIGN(64)): { + KEEP (*(.fini)) +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.interp : { + __interp_start = .; + KEEP (*(.interp)) + __interp_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.note-ABI-tag : { + __note-ABI-tag_start = .; + KEEP (*(.note-ABI-tag)) + __note-ABI-tag_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.rodata (ALIGN(64)): { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.rodata1 (ALIGN(64)): { + __rodata1_start = .; + *(.rodata1) + *(.rodata1.*) + __rodata1_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.sdata2 (ALIGN(64)): { + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + __sdata2_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.sbss2 (ALIGN(64)): { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.data (ALIGN(64)): { + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.jcr) + *(.got) + *(.got.plt) + __data_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.data1 (ALIGN(64)): { + __data1_start = .; + *(.data1) + *(.data1.*) + __data1_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.got : { + *(.got) +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.got1 : { + *(.got1) +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.got2 : { + *(.got2) +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.ctors (ALIGN(64)): { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.dtors (ALIGN(64)): { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + ___DTORS_END___ = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.fixup : { + __fixup_start = .; + *(.fixup) + __fixup_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.eh_frame : { + *(.eh_frame) +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.eh_framehdr : { + __eh_framehdr_start = .; + *(.eh_framehdr) + __eh_framehdr_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.gcc_except_table : { + *(.gcc_except_table) +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.mmu_tbl0 (ALIGN(4096)) : { + __mmu_tbl0_start = .; + *(.mmu_tbl0) + __mmu_tbl0_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.mmu_tbl1 (ALIGN(4096)) : { + __mmu_tbl1_start = .; + *(.mmu_tbl1) + __mmu_tbl1_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.mmu_tbl2 (ALIGN(4096)) : { + __mmu_tbl2_start = .; + *(.mmu_tbl2) + __mmu_tbl2_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + *(.gnu.linkonce.armexidix.*.*) + __exidx_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.preinit_array (ALIGN(64)): { + __preinit_array_start = .; + KEEP (*(SORT(.preinit_array.*))) + KEEP (*(.preinit_array)) + __preinit_array_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.init_array (ALIGN(64)): { + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.fini_array (ALIGN(64)): { + __fini_array_start = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.ARM.attributes : { + __ARM.attributes_start = .; + *(.ARM.attributes) + __ARM.attributes_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.sdata (ALIGN(64)): { + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.sbss (NOLOAD) : { + . = ALIGN(64); + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + . = ALIGN(64); + __sbss_end = .; +} > ps8_ocm_ram_1_S_AXI_BASEADDR + +.tdata (ALIGN(64)): { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > ps8_ocm_ram_0_S_AXI_BASEADDR + +.tbss (ALIGN(64)): { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > ps8_ocm_ram_1_S_AXI_BASEADDR + +.bss (NOLOAD) : { + . = ALIGN(64); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(64); + __bss_end__ = .; +} > ps8_ocm_ram_1_S_AXI_BASEADDR + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(64); + _heap = .; + HeapBase = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; + HeapLimit = .; +} > ps8_ocm_ram_1_S_AXI_BASEADDR + +.stack (NOLOAD) : { + . = ALIGN(64); + _el3_stack_end = .; + . += _STACK_SIZE; + __el3_stack = .; + _el2_stack_end = .; + . += _EL2_STACK_SIZE; + . = ALIGN(64); + __el2_stack = .; + _el1_stack_end = .; + . += _EL1_STACK_SIZE; + . = ALIGN(64); + __el1_stack = .; + _el0_stack_end = .; + . += _EL0_STACK_SIZE; + . = ALIGN(64); + __el0_stack = .; +} > ps8_ocm_ram_1_S_AXI_BASEADDR + +_end = .; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_authentication.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_authentication.c new file mode 100644 index 00000000..bd5b76e9 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_authentication.c @@ -0,0 +1,425 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +*******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xfsbl_authentication.c +* +* Contains the function definitions for RSA Signature verification. +* +* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" + +#ifdef XFSBL_RSA + +#include "xfsbl_authentication.h" + +/*****************************************************************************/ + +const u8 XFsbl_TPadSha3[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x02, 0x05, 0x00, 0x04, 0x30 }; + +const u8 XFsbl_TPadSha2[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x01, 0x05, 0x00, 0x04, 0x20 }; + +/*****************************************************************************/ +/** + * Configure the RSA and SHA for the SPK + * Signature verification. + * If SPK Signature verification fails + * then return unique error code saying + * XFSBL_STAGE3_SPK_SIGN_VERIF_ERROR. + * + * @param + * + * @return + * + ******************************************************************************/ +u32 XFsbl_SpkVer(u64 AcOffset, u32 HashLen) +{ + u8 SpkHash[XFSBL_HASH_TYPE_SHA3] __attribute__ ((aligned (4))); + u8 * PpkModular = (u8 *)NULL; + u8 * PpkModularEx = (u8 *)NULL; + u32 PpkExp = 0; + u8 * AcPtr = (u8*) (PTRSIZE) AcOffset; + u32 Status = XFSBL_SUCCESS; + void * ShaCtx = (void * )NULL; + + + (void)XFsbl_ShaStart( ShaCtx, HashLen); + + /** + * Hash the PPK + SPK choice + */ + XFsbl_ShaUpdate( ShaCtx, AcPtr, 8, HashLen); + + /** + * Set PPK pointer + */ + AcPtr += XFSBL_RSA_AC_ALIGN; + PpkModular = (u8 *)AcPtr; + AcPtr += XFSBL_SPK_SIG_SIZE; + PpkModularEx = (u8 *)AcPtr; + AcPtr += XFSBL_SPK_SIG_SIZE; + PpkExp = *((u32 *)AcPtr); + AcPtr += XFSBL_RSA_AC_ALIGN; + + XFsbl_Printf(DEBUG_DETAILED, + "XFsbl_SpkVer: Ppk Mod %0x, Ppk Mod Ex %0x, Ppk Exp %0x\r\n", + PpkModular, PpkModularEx, PpkExp); + /** + * Calculate SPK + Auth header(PPK and SPK Selectoin both) Hash + */ + XFsbl_ShaUpdate( ShaCtx, (u8 *)AcPtr, XFSBL_PPK_SIZE, HashLen); + XFsbl_ShaFinish( ShaCtx, (u8 *)SpkHash, HashLen); + + /** + * Set SPK Signature pointer + */ + AcPtr += XFSBL_SPK_SIZE; + + /** + * Decrypt SPK Signature. + */ + if(XFSBL_SUCCESS != + XFsbl_RsaDecrypt(AcPtr, PpkModular, + PpkModularEx, (u8 *)&PpkExp, XFsbl_RsaSha3Array, 0) ) + { + XFsbl_Printf(DEBUG_GENERAL, + "XFsbl_SpkVer: XFSBL_ERROR_SPK_RSA_DECRYPT\r\n"); + Status = XFSBL_ERROR_SPK_RSA_DECRYPT; + goto END; + } + + /** + * Authenticate SPK Signature. + */ + if(XFSBL_SUCCESS != XFsbl_CheckPadding(XFsbl_RsaSha3Array, + SpkHash, HashLen)) + { + XFsbl_PrintArray(DEBUG_INFO, SpkHash, + HashLen, "Calculated Partition Hash"); + XFsbl_PrintArray(DEBUG_INFO, XFsbl_RsaSha3Array, + 512, "RSA decrypted Hash"); + XFsbl_Printf(DEBUG_GENERAL, + "XFsbl_SpkVer: XFSBL_ERROR_SPK_SIGNATURE\r\n"); + Status = XFSBL_ERROR_SPK_SIGNATURE; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * Configure the RSA and SHA for the + * Boot Header Signature verification. + * If Boot Header Signature verification + * fails then return unique error code saying + * XFSBL_STAGE3_BOOT_HDR_SIGN_VERIF_ERROR. + * + * @param + * + * @return + * + ******************************************************************************/ +u32 XFsbl_PartitionSignVer(u64 PartitionOffset, u32 PartitionLen, + u64 AcOffset, u32 HashLen) +{ + + u8 PartitionHash[XFSBL_HASH_TYPE_SHA3] __attribute__ ((aligned (4))); + u8 * SpkModular = (u8 *)NULL; + u8 * SpkModularEx = (u8 *)NULL; + u32 SpkExp = 0; + u8 * AcPtr = (u8*)(PTRSIZE) AcOffset; + u32 Status = XFSBL_SUCCESS; + u32 HashDataLen=0U; + + XFsbl_Printf(DEBUG_INFO,"Doing Partition Sign verification\r\n"); + + /** + * hash to be calculated will be total length with AC minus + * signature size + */ + HashDataLen = PartitionLen - XFSBL_FSBL_SIG_SIZE; + + /** + * Set SPK pointer + */ + AcPtr += (XFSBL_RSA_AC_ALIGN + XFSBL_PPK_SIZE); + SpkModular = (u8 *)AcPtr; + AcPtr += XFSBL_BHDR_SIG_SIZE; + SpkModularEx = (u8 *)AcPtr; + AcPtr += XFSBL_BHDR_SIG_SIZE; + SpkExp = *((u32 *)AcPtr); + AcPtr += XFSBL_RSA_AC_ALIGN; + + /** + * Calculate Partition Hash + */ + XFsbl_ShaDigest((const u8 *)(PTRSIZE)PartitionOffset, HashDataLen, + PartitionHash, HashLen); + + /** + * Increment by SPK Signature pointer + */ + AcPtr += XFSBL_SPK_SIG_SIZE; + /** + * Increment by BHDR Signature pointer + */ + AcPtr += XFSBL_BHDR_SIG_SIZE; + + XFsbl_Printf(DEBUG_DETAILED, + "XFsbl_PartVer: Spk Mod %0x, Spk Mod Ex %0x, Spk Exp %0x\r\n", + SpkModular, SpkModularEx, SpkExp); + + /** + * Decrypt Partition Signature. + */ + if(XFSBL_SUCCESS != + XFsbl_RsaDecrypt(AcPtr, SpkModular, + SpkModularEx, (u8 *)&SpkExp, XFsbl_RsaSha3Array, 0) ) + { + XFsbl_Printf(DEBUG_GENERAL, + "XFsbl_SpkVer: XFSBL_ERROR_PART_RSA_DECRYPT\r\n"); + Status = XFSBL_ERROR_PART_RSA_DECRYPT; + goto END; + } + + /** + * Authenticate Partition Signature. + */ + if(XFSBL_SUCCESS != XFsbl_CheckPadding(XFsbl_RsaSha3Array, + PartitionHash, HashLen)) + { + XFsbl_PrintArray(DEBUG_INFO, PartitionHash, + HashLen, "Calculated Partition Hash"); + XFsbl_PrintArray(DEBUG_INFO, XFsbl_RsaSha3Array, + 512, "RSA decrypted Hash"); + XFsbl_Printf(DEBUG_GENERAL, + "XFsbl_SpkVer: XFSBL_ERROR_PART_SIGNATURE\r\n"); + Status = XFSBL_ERROR_PART_SIGNATURE; + goto END; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * DT 764500(Add feature for basic integrity check of + the FSBL Image by FSBL.) + * + * @param + * + * @return + * + ******************************************************************************/ +u32 XFsbl_IntegrityCheck(u64 PartitionOffset, u32 PartitionLen, + u64 CheckSumOffset, u32 HashLen) +{ + u32 Status = XFSBL_SUCCESS; + u8 PartitionHash[XFSBL_HASH_TYPE_SHA3] __attribute__ ((aligned (4))); + u32 ii=0; + u8 *HashPtr = (u8 *)NULL; + void * ShaCtx = (void * )NULL; + + XFsbl_Printf(DEBUG_INFO,"XFsbl_IntegrityCheck: Doing Partition" + " Integrity Check HashLen=%d\r\n",HashLen); + + HashPtr = (u8 *)(PTRSIZE)CheckSumOffset; + (void)XFsbl_ShaStart(ShaCtx, HashLen); + + /** + * Calculate FSBL Hash + */ + XFsbl_ShaUpdate( ShaCtx, (u8 *)(PTRSIZE)PartitionOffset, + PartitionLen, HashLen); + + XFsbl_ShaFinish( ShaCtx, (u8 *)PartitionHash, HashLen); + + /** + * Compare the calculated and builtin hash + */ + for (ii = 0; ii < HashLen; ii++) + { + if (HashPtr[ii] != PartitionHash[ii]) + { + Status = XFSBL_FAILURE; + XFsbl_Printf(DEBUG_INFO,"Check Failed!!!!!\r\n"); + goto END; + } + } + XFsbl_Printf(DEBUG_INFO,"Check Passed!!!!!\r\n"); + +END: + return Status; +} + +/*****************************************************************************/ +/** + * + * @param + * + * @return + * + ******************************************************************************/ +u32 XFsbl_CheckPadding(u8 *Signature, u8 *Hash, u32 HashLen) +{ + + u8 * Tpadding = (u8 *)NULL; + u32 Pad = XFSBL_FSBL_SIG_SIZE - 3 - 19 - HashLen; + u8 * PadPtr = Signature; + u32 ii; + u32 Status = 0; + + if(XFSBL_HASH_TYPE_SHA3 == HashLen) + { + Tpadding = (u8 *)XFsbl_TPadSha3; + } + else + { + Tpadding = (u8 *)XFsbl_TPadSha2; + } + + /** + * Re-Create PKCS#1v1.5 Padding + * MSB ----------------------------------------------------------------LSB + * 0x0 || 0x1 || 0xFF(for 202 bytes) || 0x0 || T_padding || SHA256/384 Hash + */ + + if (0x00 != *PadPtr) + { + Status = 1; + goto END; + } + PadPtr++; + + if (0x01 != *PadPtr) + { + Status = 2; + goto END; + } + PadPtr++; + + for (ii = 0; ii < Pad; ii++) + { + if (0xFF != *PadPtr) + { + Status = 3; + goto END; + } + PadPtr++; + } + + if (0x00 != *PadPtr) + { + Status = 4; + goto END; + } + PadPtr++; + + for (ii = 0; ii < 19; ii++) + { + if (*PadPtr != Tpadding[ii]) + { + Status = 5; + goto END; + } + PadPtr++; + } + + for (ii = 0; ii < HashLen; ii++) + { + if (*PadPtr != Hash[ii]) + { + Status = 6; + goto END; + } + PadPtr++; + } + +END: + XFsbl_Printf(DEBUG_INFO,"XFsbl_CheckPadding: Error:0x%x\r\n",Status); + return Status; +} + +/*****************************************************************************/ +/** + * + * @param None + * + * @return None + * + ******************************************************************************/ +u32 XFsbl_Authentication(u64 PartitionOffset, u32 PartitionLen, + u64 AcOffset, u32 HashLen) +{ + u32 Status = XFSBL_SUCCESS; + + + XFsbl_Printf(DEBUG_INFO, + "Auth: Partition Offset %0x, PartitionLen %0x," + " AcOffset %0x, HashLen %0x\r\n", + (PTRSIZE )PartitionOffset, PartitionLen, + (PTRSIZE )AcOffset, HashLen); + + /** + * Do SPK Signature verification using PPK + */ + Status = XFsbl_SpkVer(AcOffset, HashLen); + if(XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * Do Partition Signature verification using SPK + */ + Status = XFsbl_PartitionSignVer(PartitionOffset, PartitionLen, + AcOffset, HashLen); + if(XFSBL_SUCCESS != Status) + { + goto END; + } + +END: + return Status; +} + +#endif /* end of XFSBL_RSA */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_authentication.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_authentication.h new file mode 100644 index 00000000..43bb591e --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_authentication.h @@ -0,0 +1,131 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +* +*******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xcbr_authentication.h +* +* Contains the function prototypes, defines and macros for +* the RSA DSA functionality. +* +* +******************************************************************************/ + +#ifndef XFSBL_AUTHENTICATION_H +#define XFSBL_AUTHENTICATION_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" + +/***************************** Type defines *********************************/ +#define XFSBL_HASH_TYPE_SHA3 (48U) +#define XFSBL_HASH_TYPE_SHA2 (32U) + +#define XFSBL_PPK_SIZE (512U+512U+64U) +#define XFSBL_SPK_SIZE XFSBL_PPK_SIZE +#define XFSBL_SPK_SIG_SIZE (512U) +#define XFSBL_BHDR_SIG_SIZE (512U) +#define XFSBL_FSBL_SIG_SIZE (512U) +#define XFSBL_RSA_KEY_LEN (4096U) +#define XFSBL_RSA_BIG_ENDIAN (0x1U) +#define XFSBL_RSA_AC_ALIGN (64U) + +#define XFSBL_AUTH_HEADER_SIZE (8U) + +#define XFSBL_AUTH_CERT_USER_DATA (64U - XFSBL_AUTH_HEADER_SIZE) + +#define XFSBL_AUTH_CERT_MIN_SIZE (XFSBL_AUTH_HEADER_SIZE \ + + XFSBL_AUTH_CERT_USER_DATA \ + + XFSBL_PPK_SIZE \ + + XFSBL_PPK_SIZE \ + + XFSBL_SPK_SIG_SIZE \ + + XFSBL_BHDR_SIG_SIZE \ + + XFSBL_FSBL_SIG_SIZE) + +#define XFSBL_AUTH_CERT_MAX_SIZE (XFSBL_AUTH_CERT_MIN_SIZE + 60) + +#define XFSBL_PARTIAL_AC_SIZE (XFSBL_AUTH_CERT_MIN_SIZE - XFSBL_FSBL_SIG_SIZE) + +/** +* CSU RSA Register Map +*/ + +#define XFSBL_CSU_RSA_CONTROL_2048 (0xA0U) +#define XFSBL_CSU_RSA_CONTROL_4096 (0xC0U) +#define XFSBL_CSU_RSA_CONTROL_DCA (0x08U) +#define XFSBL_CSU_RSA_CONTROL_NOP (0x00U) +#define XFSBL_CSU_RSA_CONTROL_EXP (0x01U) +#define XFSBL_CSU_RSA_CONTROL_EXP_PRE (0x05U) +#define XFSBL_CSU_RSA_CONTROL_MASK (XFSBL_CSU_RSA_CONTROL_4096 + XFSBL_CSU_RSA_CONTROL_EXP_PRE) + +#define XFSBL_CSU_RSA_RAM_EXPO (0) +#define XFSBL_CSU_RSA_RAM_MOD (1) +#define XFSBL_CSU_RSA_RAM_DIGEST (2) +#define XFSBL_CSU_RSA_RAM_SPAD (3) +#define XFSBL_CSU_RSA_RAM_RES_Y (4) +#define XFSBL_CSU_RSA_RAM_RES_Q (5) + +#define XFSBL_CSU_RSA_RAM_WORDS (6) + +/** +* CSU SHA3 Memory Map +*/ + +#define XFSBL_SHA3_BLOCK_LEN (104) + +#define XFSBL_SHA3_LAST_PACKET (0x1) + +u32 XFsbl_Authentication(u64 PartitionOffset, u32 PartitionLen, + u64 AcOffset, u32 HashLen); +u32 XFsbl_PartitionSignVer(u64 PartitionOffset, u32 PartitionLen, + u64 AcOffset, u32 HashLen); +u32 XFsbl_SpkVer(u64 AcOffset, u32 HashLen); +//u32 XFsbl_IntegrityCheck(XCbrBootRom *InstancePtr); +u32 XFsbl_CheckPadding(u8 *Signature, u8 *Hash, u32 HashLen); + +u32 XFsbl_RsaDecrypt(u8* EncText, u8* Mod, u8* ModExt, u8* ModExpo, u8* Result, u8 Reuse); +void XFsbl_ShaDigest(const u8 *In, const u32 Size, u8 *Out, u32 HashLen); +void XFsbl_ShaStart( void * Ctx, u32 HashLen); +void XFsbl_ShaUpdate(void * Ctx, u8 * Data, u32 Size, u32 HashLen); +void XFsbl_ShaFinish(void * Ctx, u8 * Hash, u32 HashLen); + +extern u8 XFsbl_RsaSha3Array[512]; +#ifdef __cplusplus +extern "C" } +#endif + +#endif /** XFSBL_AUTHENTICATION_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_config.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_config.h new file mode 100644 index 00000000..643b9fb6 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_config.h @@ -0,0 +1,147 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_config.h +* +* This is the header file which contains FSBL configuration +* for users. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ +#ifndef XFSBL_CONFIG_H +#define XFSBL_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +/** + * @name FSBL Debug options + * + * FSBL by default doesn't have any prints enabled. If user + * want to enable the prints, they can define the following + * options to have FSBL prints + * FSBL supports three types of debug levels. + * - FSBL_DEBUG Defining this will print the FSBL header and + * same basic information and error prints if any + * - FSBL_DEBUG_INFO Defining this will have prints enabled with + * in addition to the basic information + * - FSBL_DEBUG_DETAILED Defining this will print information with + * all data exchanged. + */ +#define FSBL_DEBUG_VAL (0U) +#define FSBL_DEBUG_INFO_VAL (1U) +#define FSBL_DEBUG_DETAILED_VAL (0U) + +/** + * FSBL Debug options + */ +#if FSBL_DEBUG_VAL +#define FSBL_DEBUG +#endif + +#if FSBL_DEBUG_INFO_VAL +#define FSBL_DEBUG_INFO +#endif + +#if FSBL_DEBUG_DETAILED_VAL +#define FSBL_DEBUG_DETAILED +#endif + + +/** + * @name FSBL code include options + * + * FSBL by default all the code is included. + * Unwanted code can be excluded from the elf by defining here + * Below blocks can be excluded from the code. + * - FSBL_NAND_EXCLUDE NAND code will be excluded + * - FSBL_QSPI_EXCLUDE QSPI code will be excluded + * - FSBL_SD_EXCLUDE SD code will be excluded + * - FSBL_RSA_EXCLUDE RSA code will be excluded + */ +#define FSBL_NAND_EXCLUDE_VAL (0U) +#define FSBL_QSPI_EXCLUDE_VAL (0U) +#define FSBL_SD_EXCLUDE_VAL (0U) +#define FSBL_RSA_EXCLUDE_VAL (0U) +#define FSBL_SHA2_EXCLUDE_VAL (1U) + +#if FSBL_NAND_EXCLUDE_VAL +#define FSBL_NAND_EXCLUDE +#endif + +#if FSBL_QSPI_EXCLUDE_VAL +#define FSBL_QSPI_EXCLUDE +#endif + +#if FSBL_SD_EXCLUDE_VAL +#define FSBL_SD_EXCLUDE +#endif + +#if FSBL_RSA_EXCLUDE_VAL +#define FSBL_RSA_EXCLUDE +#endif + +#if FSBL_SHA2_EXCLUDE_VAL +#define FSBL_SHA2_EXCLUDE +#endif + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_CONFIG_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.c new file mode 100644 index 00000000..caa4b368 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.c @@ -0,0 +1,182 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +*******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xfsbl_csu_dma.c + * + * This contains code for the CSU DMA driver. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date        Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00   kc  07/22/14 Initial release
+ *
+ * 
+ * + * @note + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xfsbl_csu_dma.h" +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** + * + * This function will configure dst/src DMA address + * and size and also start the CSU DMA. + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_CsuDmaStart(XFSBL_CSU_DMA_CHANNEL Channel, u32 Addr, u32 Size) +{ + XASSERT_VOID((Addr & 3) == 0); + + if(XFSBL_CSU_DMA_SRC == Channel) + { + XASSERT_VOID((Size & 2) == 0); + } + else + { + XASSERT_VOID((Size & 3) == 0); + } + + XFsbl_Out32(CSUDMA_BASEADDR + Channel + XFSBL_CSU_DMA_ADDR_REG, Addr); + + /** + * Writes to SIZE to start the channel, this starts + * the DMA. + */ + /** ASM Code */ + mb(); + XFsbl_Out32(CSUDMA_BASEADDR + Channel + XFSBL_CSU_DMA_SIZE_REG, Size); +} + +/*****************************************************************************/ +/** + * + * This function will stop/pause the CSU DMA. + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_CsuDmaStop(u32 Flags) +{ + /** + * This function is TBD. + */ + +} + +/*****************************************************************************/ +/** + * + * This function will wait for CSU DMA done. + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_CsuDmaWaitForDone(XFSBL_CSU_DMA_CHANNEL Channel) +{ + volatile u32 Status = 0; + + /** ASM Code */ + mb(); + /* Busy wait for the DMA. */ + /** + * TBD: May need to have some timeout for this loop. + */ + do + { + Status = XFsbl_In32(CSUDMA_BASEADDR + Channel + + XFSBL_CSU_DMA_STATUS_REG); + + } while (Status & XFSBL_CSU_DMA_STATUS_BUSY); + +} + +/*****************************************************************************/ +/** + * + * This function will start the dma transfer + * and wait for DST DMA done. + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_CsuDmaXfer(u32 SrcAddr, u32 DestAddr, u32 ImgLen) +{ + XFsbl_Printf(DEBUG_INFO,"In XCbr_CsuDmaXfer: SrcAddr:0x%x " + "DestAddr:0x%x ImgLen:0x%x\r\n",SrcAddr,DestAddr,ImgLen); + + XFsbl_CsuDmaStart(XFSBL_CSU_DMA_DST, DestAddr, ((ImgLen/4) << 2) ); + + /** + * In case of PSTP, the Src DMA channel is not used. + * For this function SrcAddr == 0 means we are calling + * this function for PS_TEST boot mode + */ + if(0 != SrcAddr) + { + XFsbl_CsuDmaStart(XFSBL_CSU_DMA_SRC, SrcAddr, (ImgLen/4) << 2); + XFsbl_CsuDmaWaitForDone(XFSBL_CSU_DMA_SRC); + } + + /** + * TBD: Need to enhance this to return + * timeout error + */ + XFsbl_CsuDmaWaitForDone(XFSBL_CSU_DMA_DST); + +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.h new file mode 100644 index 00000000..d73d2cb9 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_csu_dma.h @@ -0,0 +1,275 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +*******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xcbr_csu_dma.h +* +* Contains enums/typedefs and macros for CSU DMA driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   07/22/14 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_CSU_DMA_H +#define XFSBL_CSU_DMA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" + +/**************************** Macros Definitions *****************************/ +#define XASSERT_VOID(expression) +#define mb() asm("dsb sy") + +u8 XFsbl_RsaSha3Array[512]; +/**************************** Type Definitions *******************************/ + +/** +* Definition for DMA channels. +*/ +typedef enum +{ + XFSBL_CSU_DMA_SRC = 0x000U, + XFSBL_CSU_DMA_DST = 0x800U +}XFSBL_CSU_DMA_CHANNEL; + +/** +* Definition for DMA registers. +*/ +typedef enum +{ + XFSBL_CSU_DMA_ADDR_REG = 0x00U, + XFSBL_CSU_DMA_SIZE_REG = 0x04U, + XFSBL_CSU_DMA_STATUS_REG = 0x08U, + XFSBL_CSU_DMA_CTRL_REG = 0x0CU, + XFSBL_CSU_DMA_CRC_REG = 0x10U, + XFSBL_CSU_DMA_INT_STATUS_REG = 0x14U, + XFSBL_CSU_DMA_INT_ENABLE_REG = 0x18U, + XFSBL_CSU_DMA_INT_DISABLE_REG = 0x1CU, + XFSBL_CSU_DMA_INT_MASK_REG = 0x20U, +}XFSBL_CSU_DMA_REG_OFFSET; + +/** +* Definition for DMA EOP. +*/ +enum +{ + XFSBL_CSU_DMA_SIZE_EOP = 0x1U +}; + +/** +* Definition for DMA Status reg bits. +*/ +typedef enum +{ + XFSBL_CSU_DMA_STATUS_BUSY = (0x1U << 0x0U), + XFSBL_CSU_DMA_STATUS_DONE_CNT_SHIFT = (13U), + XFSBL_CSU_DMA_STATUS_DONE_CNT_MASK = (0x7U << XFSBL_CSU_DMA_STATUS_DONE_CNT_SHIFT) +}XFSBL_CSU_DMA_STATUS; + +/** +* Definition for DMA Control reg bits. +*/ +typedef enum +{ + XFSBL_CSU_DMA_CTRL_PAUSE_MEM = (0x1U << 0x0U), + XFSBL_CSU_DMA_CTRL_PAUSE_STREAM = (0x1U << 0x1U), + XFSBL_CSU_DMA_CTRL_FIFO_THRESH_SHIFT = 0x2U, + XFSBL_CSU_DMA_CTRL_TIMEOUT_SHIFT = 10U, + XFSBL_CSU_DMA_CTRL_AXI_BURST_INCR = (0x0U << 22U), + XFSBL_CSU_DMA_CTRL_AXI_BURST_FIXED = (0x1U << 22U), + XFSBL_CSU_DMA_CTRL_ENDIANNESS = (0x1U << 23U), + XFSBL_CSU_DMA_CTRL_ERR_RESPONSE = (0x1U << 24U), + XFSBL_CSU_DMA_CTRL_IF_FIFO_THRESH_SHIFT = 25U +}XFSBL_CSU_DMA_CTRL; + +/** +* Definition for DMA Interrupt reg bits. +*/ +typedef enum +{ + XFSBL_CSU_DMA_INT_INVALID_APB_ACCESS = (0x1U << 0x5U), + XFSBL_CSU_DMA_INT_FIFO_THRESH_HIT = (0x1U << 0x4U), + XFSBL_CSU_DMA_INT_DMA_TIMEOUT = (0x1U << 0x3U), + XFSBL_CSU_DMA_INT_AXI_RD__ERR = (0x1U << 0x2U), + XFSBL_CSU_DMA_INT_DMA_DONE = (0x1U << 0x1U), + XFSBL_CSU_DMA_INT_DMA_MEM_DONE = (0x1U << 0x0U) +}XFSBL_CSU_DMA_INT; + +/* + * Definition for SSS reg Source bits. + */ +typedef enum +{ + XFSBL_CSU_SSS_SRC_PCAP = 0x3U, + XFSBL_CSU_SSS_SRC_SRC_DMA = 0x5U, + XFSBL_CSU_SSS_SRC_AES = 0xAU, + XFSBL_CSU_SSS_SRC_PSTP = 0xCU, + XFSBL_CSU_SSS_SRC_NONE = 0x0U, + XFSBL_CSU_SSS_SRC_MASK = 0xFU +}XFSBL_CSU_SSS_SRC; + +/** +* Definition for SSS reg Destination bits. +*/ +typedef enum +{ + XFSBL_CSU_SSS_PCAP_SHIFT = 0U, + XFSBL_CSU_SSS_DMA_SHIFT = 4U, + XFSBL_CSU_SSS_AES_SHIFT = 8U, + XFSBL_CSU_SSS_SHA_SHIFT = 12U, + XFSBL_CSU_SSS_PSTP_SHIFT = 16U +}XFSBL_CSU_SSS_DEST_SHIFT; + + +/**************************** Macros Definitions *****************************/ + +/** +* Definition for DMA inline functions +*/ +static inline void XFsbl_DmaControl(XFSBL_CSU_DMA_CHANNEL Channel, u32 Val) +{ + XFsbl_Out32((CSUDMA_BASEADDR + Channel + XFSBL_CSU_DMA_CTRL_REG), Val); +} + +static inline void XFsbl_DmaEndian(XFSBL_CSU_DMA_CHANNEL Channel, u32 Enable) +{ + u32 Value = XFsbl_In32(CSUDMA_BASEADDR + Channel + XFSBL_CSU_DMA_CTRL_REG); + if(Enable) + { + Value |= XFSBL_CSU_DMA_CTRL_ENDIANNESS; + } + else + { + Value &= ~XFSBL_CSU_DMA_CTRL_ENDIANNESS; + } + + XFsbl_Out32((CSUDMA_BASEADDR + Channel + XFSBL_CSU_DMA_CTRL_REG), Value); +} + +static inline int XFsbl_DmaIsBusy(XFSBL_CSU_DMA_CHANNEL Channel) +{ + return (XFsbl_In32(CSUDMA_BASEADDR + Channel + XFSBL_CSU_DMA_STATUS_REG) & + XFSBL_CSU_DMA_STATUS_BUSY); +} + +static inline unsigned int XFsbl_DmaDoneCount(XFSBL_CSU_DMA_CHANNEL Channel) +{ + u32 Count; + + Count = XFsbl_In32(CSUDMA_BASEADDR + Channel + XFSBL_CSU_DMA_STATUS_REG); + Count &= XFSBL_CSU_DMA_STATUS_DONE_CNT_MASK; + Count >>= XFSBL_CSU_DMA_STATUS_DONE_CNT_SHIFT; + return Count; +} + +static inline void XFsbl_DmaZeroDoneCount(XFSBL_CSU_DMA_CHANNEL Channel) +{ + XFsbl_Out32(CSUDMA_BASEADDR + Channel + XFSBL_CSU_DMA_STATUS_REG, + XFSBL_CSU_DMA_STATUS_DONE_CNT_MASK); + /** ASM Code */ + mb(); +} + +/* The CRC function is only available on SRC channels. */ +static inline u32 XFsbl_DmaSrcGetCrc(void) +{ + return (XFsbl_In32(CSUDMA_BASEADDR + XFSBL_CSU_DMA_SRC + + XFSBL_CSU_DMA_CRC_REG)); +} + +static inline void XFsbl_DmaSrcSetCrc(u32 Crc) +{ + XFsbl_Out32(CSUDMA_BASEADDR + XFSBL_CSU_DMA_SRC + + XFSBL_CSU_DMA_CRC_REG, Crc); + /** ASM Code */ + mb(); +} + +void XFsbl_CsuDmaWaitForDone(XFSBL_CSU_DMA_CHANNEL Channel); +void XFsbl_CsuDmaStart(XFSBL_CSU_DMA_CHANNEL Channel, u32 Addr, u32 Size); +void XFsbl_CsuDmaXfer(u32 SrcAddr, u32 DestAddr, u32 ImgLen); + + +/** +* Definition for SSS inline functions +*/ +static inline u32 XFsbl_SssInputPcap(XFSBL_CSU_SSS_SRC Src) +{ + Src &= XFSBL_CSU_SSS_SRC_MASK; + return (Src << XFSBL_CSU_SSS_PCAP_SHIFT); +} + +static inline u32 XFsbl_SssInputDstDma(XFSBL_CSU_SSS_SRC Src) +{ + Src &= XFSBL_CSU_SSS_SRC_MASK; + return (Src << XFSBL_CSU_SSS_DMA_SHIFT); +} + +static inline u32 XFsbl_SssInputAes(XFSBL_CSU_SSS_SRC Src) +{ + Src &= XFSBL_CSU_SSS_SRC_MASK; + return (Src << XFSBL_CSU_SSS_AES_SHIFT); +} + +static inline u32 XFsbl_SssInputSha3(XFSBL_CSU_SSS_SRC Src) +{ + Src &= XFSBL_CSU_SSS_SRC_MASK; + return (Src << XFSBL_CSU_SSS_SHA_SHIFT); +} + +static inline u32 XFsbl_SssInputPstp(XFSBL_CSU_SSS_SRC Src) +{ + Src &= XFSBL_CSU_SSS_SRC_MASK; + return (Src << XFSBL_CSU_SSS_PSTP_SHIFT); +} + +static inline void XFsbl_SssSetup(u32 Cfg) +{ + XFsbl_Out32(CSU_CSU_SSS_CFG, Cfg); +} + +#endif /* XFSBL_CSU_DMA_H*/ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_debug.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_debug.h new file mode 100644 index 00000000..7deef97f --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_debug.h @@ -0,0 +1,102 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +*****************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_debug.h +* +* This file contains the debug verbose information for FSBL print functionality +* +*
+* MODIFICATION HISTORY:
+*
+* Ver	Who	Date		Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a kc	11/05/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_DEBUG_H +#define XFSBL_DEBUG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_printf.h" +#include "xfsbl_config.h" +#include "xil_types.h" +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/** + * Debug levels for FSBL + */ +#define DEBUG_GENERAL (0x00000001U) /* general debug messages */ +#define DEBUG_INFO (0x00000002U) /* More debug information */ +#define DEBUG_DETAILED (0x00000004U) /* More debug information */ + +#if defined (FSBL_DEBUG_DETAILED) +#define XFsblDbgCurrentTypes ((DEBUG_DETAILED) | (DEBUG_INFO) | (DEBUG_GENERAL)) +#elif defined (FSBL_DEBUG_INFO) +#define XFsblDbgCurrentTypes ((DEBUG_INFO) | (DEBUG_GENERAL)) +#elif defined (FSBL_DEBUG) +#define XFsblDbgCurrentTypes (DEBUG_GENERAL) +#else +#define XFsblDbgCurrentTypes (0U) +#endif + +#if 0 +__inline void XFsbl_Printf(u32 DebugType,char *Format, ...); +#else +#define XFsbl_Printf(DebugType,...) \ + if (((DebugType) & XFsblDbgCurrentTypes) != 0U) {xil_printf (__VA_ARGS__); } +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_DEBUG_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_error.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_error.h new file mode 100644 index 00000000..09c99952 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_error.h @@ -0,0 +1,164 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_error.h +* +* This is the header file which contains error codes for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_ERROR_H +#define XFSBL_ERROR_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +/************************** Constant Definitions *****************************/ +/** + * @name FSBL error codes description + * + * XXYY - Error code format + * + * YY - error code irrespective of stage + * + * XX -> x1 x2 x3 x4 x5 x6 x7 x8 + * + * x1 -> FSBL / CSUROM error + * x2x3 -> Stage at which error happened + * 00 -> Error at stage 1 + * 01 -> Error at stage 2 + * 10 -> Error at stage 3 + * 11 -> Error at stage 4 + * x4x5x6 -> Error source for next 10 bits + * 000 -> FSBL error code + * 001 -> ps8 init failure + * 010 -> ps8 postconfig failure + * 011 -> Driver error code + * x7x8 -> + */ + +#define XFSBL_ERROR_STAGE_1 (0x0000U) +#define XFSBL_ERROR_STAGE_2 (0x2000U) +#define XFSBL_ERROR_STAGE_3 (0x4000U) +#define XFSBL_ERROR_STAGE_4 (0x6000U) + +#define XFSBL_PS8_INIT_FAILED (0x0800U) +#define XFSBL_PS8_POSTCONFIG_FAILED (0x1000U) + +#define XFSBL_SUCCESS (0x0U) +#define XFSBL_STATUS_JTAG (0x1U) +#define XFSBL_SUCCESS_NOT_PARTITION_OWNER (0x2U) + +#define XFSBL_ERROR_UNSUPPORTED_BOOT_MODE (0x6U) +#define XFSBL_WDT_INIT_FAILED (0x7U) +#define XFSBL_INVALID_DEST_CPU (0x8U) +#define XFSBL_ERROR_SYSTEM_WDT_RESET (0x9U) + +#define XFSBL_ERROR_QSPI_READ_ID (0xAU) +#define XFSBL_ERROR_UNSUPPORTED_QSPI (0xBU) +#define XFSBL_ERROR_QSPI_INIT (0xCU) + +#define XFSBL_ERROR_NO_OF_PARTITIONS (0xDU) +#define XFSBL_ERROR_PPD (0xEU) +#define XFSBL_ERROR_XIP_AUTH_ENC_PRESENT (0xFU) +#define XFSBL_ERROR_XIP_EXEC_ADDRESS (0x10U) +#define XFSBL_ERROR_PARTITION_LENGTH (0x11U) +#define XFSBL_ERROR_INVALID_CHECKSUM_TYPE (0x12U) +#define XFSBL_ERROR_INVALID_CPU_TYPE (0x13U) +#define XFSBL_ERROR_LS_CPU_TYPE (0x14U) +#define XFSBL_ERROR_INVALID_DEST_DEVICE (0x15U) +#define XFSBL_ERROR_INVALID_LOAD_ADDRESS (0x16U) +#define XFSBL_ERROR_PH_CHECKSUM_FAILED (0x17U) +#define XFSBL_ERROR_PWR_UP_CPU (0x18U) +#define XFSBL_ERROR_QSPI_LENGTH (0x19U) +#define XFSBL_ERROR_INVALID_QSPI_CONNECTION (0x1AU) +#define XFSBL_ERROR_UNDEFINED_EXCEPTION (0x1BU) +#define XFSBL_ERROR_SVC_EXCEPTION (0x1CU) +#define XFSBL_ERROR_PREFETCH_ABORT_EXCEPTION (0x1DU) +#define XFSBL_ERROR_DATA_ABORT_EXCEPTION (0x1EU) +#define XFSBL_ERROR_IRQ_EXCEPTION (0x1FU) +#define XFSBL_ERROR_FIQ_EXCEPTION (0x20U) +#define XFSBL_ERROR_IHT_CHECKSUM (0x21U) +#define XFSBL_ERROR_QSPI_READ (0x22U) +#define XFSBL_ERROR_HANDOFF_CPUID (0x23U) +#define XFSBL_ERROR_LOAD_ADDRESS (0x24U) +#define XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD (0x25U) +#define XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD (0x26U) +#define XFSBL_ERROR_HOOK_BEFORE_HANDOFF (0x27U) +#define XFSBL_ERROR_SD_INIT (0x28U) +#define XFSBL_ERROR_SD_F_OPEN (0x29U) +#define XFSBL_ERROR_SD_F_LSEEK (0x2AU) +#define XFSBL_ERROR_SD_F_READ (0x2BU) +#define XFSBL_ERROR_NAND_INIT (0x2CU) +#define XFSBL_ERROR_NAND_READ (0x2DU) +#define XFSBL_ERROR_ADDRESS (0x2EU) +#define XFSBL_ERROR_RSA_NOT_ENABLED (0x2DU) +#define XFSBL_ERROR_SPK_RSA_DECRYPT (0x2FU) +#define XFSBL_ERROR_SPK_SIGNATURE (0x30U) +#define XFSBL_ERROR_PART_RSA_DECRYPT (0x31U) +#define XFSBL_ERROR_PART_SIGNATURE (0x32U) +#define XFSBL_ERROR_DDR_INIT_FAIL (0x33U) + +#define XFSBL_FAILURE (0x3FFU) + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_ERROR_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S new file mode 100644 index 00000000..ba27dbee --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S @@ -0,0 +1,141 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +*******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_exit.s +* +* This is the main file which contains exit code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   11/13/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +.globl XFsbl_Exit + +/************************** Variable Definitions *****************************/ + +XFsbl_Exit: + +#ifndef XFSBL_A53 + mov lr, r0 /* move the destination address into link register */ + + mcr 15,0,r0,cr7,cr5,0 /* Invalidate Instruction cache */ + mcr 15,0,r0,cr7,cr5,6 /* Invalidate branch predictor array */ + + dsb + isb /* make sure it completes */ + + mrc p15,0,r4,c1,c0,0 /* Read SCTLR */ + bic r4, r4, #0x04 /* disable L1 I Cache */ + bic r4, r4, #0x1000 /* Disable L1 D Cache */ + mcr 15,0,r4,cr1,cr0,0 /* disable the DCache, ICache */ + isb /* make sure it completes */ + + /* set exception vector to HIVEC */ + /* this is done because, in LOVEC we can not disable the MPU as */ + /* OCM region is not present in default MPU regions when in LOVEC*/ + mrc p15, 0, r0, c1, c0, 0 /* Read SCTLR */ + orr r0, r0, #0x2000 + mcr 15, 0, r0, cr1, cr0, 0 + isb + + /* disable the MPU */ + mrc p15,0,r4,c1,c0,0 /* Read SCTLR */ + bic r4, r4, #0x01 + mcr 15,0,r4,cr1,cr0,0 + isb + + cmp r1,#0 + bne XFsbl_StartApp +#else + mov x30, x0 /* move the destination address into x30 register */ + + tlbi ALLE3 /* invalidate All E3 translation tables */ + ic IALLU /* invalidate I Cache All to PoU, Inner Shareable */ + + dsb sy + isb /* make sure it completes */ + + mrs x5, SCTLR_EL3 /* Read control register */ + mov x6, #0x1005 /* D, I , M bits disable */ + bic x5, x5, x6 /* Disable MMU, L1 and L2 I/D cache */ + msr SCTLR_EL3, x5 /* */ + + isb + + cmp x1, #0 /* exit to wfe */ + beq XFsbl_Loop + + cmp x1, #1 /* x1 is 1 - exit in aarch64 */ + beq XFsbl_StartApp + + /* x1 is 2 - exit in aarch32 */ + + mov x2, #3 /* request for warm reset and aarch32 */ + msr RMR_EL3,x2 /* write to reset management register */ + isb +#endif + +XFsbl_Loop: + wfe /* wait for event */ + b XFsbl_Loop + +.Ldone: + b .Ldone /* Paranoia: we should never get here */ + +XFsbl_StartApp: +#ifdef XFSBL_A53 + br x30 /* branch to */ +#else + bx lr; +#endif +.end diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c new file mode 100644 index 00000000..d75acdfb --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c @@ -0,0 +1,867 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xfsbl_handoff.c + * + * This is the main file which contains handoff code for the FSBL. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date        Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00  kc   10/21/13 Initial release
+ *
+ * 
+ * + * @note + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xil_cache.h" +#include "pss_init.h" +#include "xfsbl_main.h" +#include "xfsbl_image_header.h" + +/************************** Constant Definitions *****************************/ +#define XFSBL_CPU_POWER_UP (0x1U) +#define XFSBL_CPU_SWRST (0x2U) + +/** + * Aarch32 or Aarch64 CPU definitions + */ +#define APU_CONFIG_0_AA64N32_MASK_CPU0 (0x1U) +#define APU_CONFIG_0_AA64N32_MASK_CPU1 (0x2U) +#define APU_CONFIG_0_AA64N32_MASK_CPU2 (0x4U) +#define APU_CONFIG_0_AA64N32_MASK_CPU3 (0x8U) + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +#define XFSBL_IVT_ADDRESS (0xFFFF0000U) +#define XFSBL_HANDOFF_ADDR_PTR (0xFFFFFF00U) +#define XFSBL_HANDOFF_FLAG_ADDR (0xFFFFFF80U) +/************************** Function Prototypes ******************************/ + +static u32 XFsbl_SetCpuPwrSettings (u32 CpuSettings, u32 Flags); +static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings); +static void XFsbl_CopyIVT(u32 CpuSettings); +static int XFsbl_Is32BitCpu(u32 CpuSettings); + +/** + * Functions defined in xfsbl_handoff.S + */ +extern void XFsbl_Exit(PTRSIZE HandoffAddress, u32 Flags); + +/************************** Variable Definitions *****************************/ +/** + * Variabled defined in xfsbl_partition_load.c + */ +extern u8 TcmVectorArray[32]; +extern u32 TcmSkipLength; +extern PTRSIZE TcmSkipAddress; + +int XFsbl_Is32BitCpu(u32 CpuSettings) +{ + int Status; + u32 CpuId=0U; + u32 ExecState=0U; + + CpuId = CpuSettings & XIH_PH_ATTRB_DEST_CPU_MASK; + ExecState = CpuSettings & XIH_PH_ATTRB_A53_EXEC_ST_MASK; + + if ((CpuId == XIH_PH_ATTRB_DEST_CPU_R5_0) || + (CpuId == XIH_PH_ATTRB_DEST_CPU_R5_1) || + (CpuId == XIH_PH_ATTRB_DEST_CPU_R5_L) || + (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)) + { + Status = TRUE; + } else { + Status = FALSE; + } + + return Status; +} + + +/****************************************************************************/ +/** + * This function will set up the settings for the CPU's + * This can power up the CPU or do a soft reset to the CPU's + * + * @param CpuId specifies for which CPU settings should be done + * + * @param Flags is used to specify the settings for the CPU + * XFSBL_CPU_POWER_UP - This is used to power up the CPU + * XFSBL_CPU_SWRST - This is used to trigger the reset to CPU + * + * @return + * - XFSBL_SUCCESS on successful settings + * - XFSBL_FAILURE + * + * @note + * + *****************************************************************************/ + +static u32 XFsbl_SetCpuPwrSettings (u32 CpuSettings, u32 Flags) +{ + u32 RegValue=0U; + u32 Status=XFSBL_SUCCESS; + u32 CpuId=0U; + u32 ExecState=0U; + + CpuId = CpuSettings & XIH_PH_ATTRB_DEST_CPU_MASK; + ExecState = CpuSettings & XIH_PH_ATTRB_A53_EXEC_ST_MASK; + /** + * Reset the CPU + */ + if ((Flags & XFSBL_CPU_SWRST) != 0U) + { + + switch(CpuId) + { + + case XIH_PH_ATTRB_DEST_CPU_A53_0: + + /** + * Set to Aarch32 if enabled + */ + if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32) + { + RegValue = XFsbl_In32(APU_CONFIG_0); + RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU0); + XFsbl_Out32(APU_CONFIG_0, RegValue); + } + + /** + * Release reset + */ + RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU); + RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU0_RESET_MASK); + RegValue &= ~(CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK); + XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL); + RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK | + CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK); + XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue); + break; + + case XIH_PH_ATTRB_DEST_CPU_A53_1: + /** + * Set to Aarch32 if enabled + */ + if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32) + { + RegValue = XFsbl_In32(APU_CONFIG_0); + RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU1); + XFsbl_Out32(APU_CONFIG_0, RegValue); + } + + /** + * Release reset + */ + RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU); + RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU1_RESET_MASK); + RegValue &= ~(CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK); + XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL); + RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK | + CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK); + XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue); + break; + + case XIH_PH_ATTRB_DEST_CPU_A53_2: + /** + * Set to Aarch32 if enabled + */ + if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32) + { + RegValue = XFsbl_In32(APU_CONFIG_0); + RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU2); + XFsbl_Out32(APU_CONFIG_0, RegValue); + } + + /** + * Release reset + */ + RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU); + RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU2_RESET_MASK); + RegValue &= ~(CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK); + XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL); + RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK | + CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK); + XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue); + break; + + case XIH_PH_ATTRB_DEST_CPU_A53_3: + /** + * Set to Aarch32 if enabled + */ + if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32) + { + RegValue = XFsbl_In32(APU_CONFIG_0); + RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU3); + XFsbl_Out32(APU_CONFIG_0, RegValue); + } + + /** + * Release reset + */ + RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU); + RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU3_RESET_MASK); + RegValue &= ~(CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK); + XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL); + RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK | + CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK); + XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue); + break; + + case XIH_PH_ATTRB_DEST_CPU_R5_0: + /** + * Place R5, TCM's in split mode + */ + RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); + RegValue |= (RPU_RPU_GLBL_CNTL_SLSPLIT_MASK); + RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK); + RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK); + XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue); + + /** + * Place R5-0 in HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_0_CFG); + RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK); + XFsbl_Out32(RPU_RPU_0_CFG, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL); + RegValue |= (CRL_APB_CPU_R5_CTRL_CLKACT_MASK); + XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue); + + /** + * Provide some delay, + * so that clock propogates properly. + */ + //Status = usleep(0x50U); + (void)usleep(0x50U); + + + /** + * Release reset to R5-0 + */ + RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK); + XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue); + + + /** + * Take R5-0 out of HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_0_CFG); + RegValue |= RPU_RPU_0_CFG_NCPUHALT_MASK; + XFsbl_Out32(RPU_RPU_0_CFG, RegValue); + break; + + case XIH_PH_ATTRB_DEST_CPU_R5_1: + /** + * Place R5, TCM's in split mode + */ + RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); + RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK; + RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK); + RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK); + XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue); + + /** + * Place R5-1 in HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_1_CFG); + RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK); + XFsbl_Out32(RPU_RPU_1_CFG, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL); + RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK; + XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue); + + /** + * Provide some delay, + * so that clock propogates properly. + */ + //Status = usleep(0x50U); + (void)usleep(0x50U); + + /** + * Release reset to R5-1 + */ + RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK); + XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue); + + + /** + * Take R5-1 out of HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_1_CFG); + RegValue |= RPU_RPU_1_CFG_NCPUHALT_MASK; + XFsbl_Out32(RPU_RPU_1_CFG, RegValue); + break; + case XIH_PH_ATTRB_DEST_CPU_R5_L: + /** + * Place R5, TCM's in safe mode + */ + RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); + RegValue &= ~(RPU_RPU_GLBL_CNTL_SLSPLIT_MASK); + RegValue |= RPU_RPU_GLBL_CNTL_TCM_COMB_MASK; + RegValue |= RPU_RPU_GLBL_CNTL_SLCLAMP_MASK; + XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue); + + /** + * Place R5-0 in HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_0_CFG); + RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK); + XFsbl_Out32(RPU_RPU_0_CFG, RegValue); + + /** + * Place R5-1 in HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_1_CFG); + RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK); + XFsbl_Out32(RPU_RPU_1_CFG, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL); + RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK; + XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue); + + /** + * Provide some delay, + * so that clock propogates properly. + */ + //Status = usleep(0x50U); + (void )usleep(0x50U); + + /** + * Release reset to R5-0, R5-1 + */ + RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK); + XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue); + + + /** + * Take R5-0 out of HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_0_CFG); + RegValue |= RPU_RPU_0_CFG_NCPUHALT_MASK; + XFsbl_Out32(RPU_RPU_0_CFG, RegValue); + + /** + * Take R5-1 out of HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_1_CFG); + RegValue |= RPU_RPU_1_CFG_NCPUHALT_MASK; + XFsbl_Out32(RPU_RPU_1_CFG, RegValue); + break; + + default: + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_HANDOFF_CPUID\n\r"); + Status = XFSBL_ERROR_HANDOFF_CPUID; + break; + } + + } + + return Status; +} + +/****************************************************************************/ +/** + * FSBL exit function before the assembly code + * + * @param HandoffAddress is handoff address for the FSBL running cpu + * + * @param Flags is to determine whether to handoff to applicatio or + * to be in wfe state + * + * @return None + * + * + *****************************************************************************/ +void XFsbl_HandoffExit(u64 HandoffAddress, u32 Flags) +{ + + /** + * Flush the L1 data cache and L2 cache + */ + Xil_DCacheFlush(); + + /** + * Disable Data Cache + */ + Xil_DCacheDisable(); + + XFsbl_Printf(DEBUG_GENERAL,"Exit from FSBL \n\r"); + + /** + * Exit to handoff address + * PTRSIZE is used since handoff is in same running cpu + * and address is of PTRSIZE + */ + XFsbl_Exit((PTRSIZE) HandoffAddress, Flags); + + /** + * should not reach here + */ + return ; + +} + + +/****************************************************************************/ +/** +* +* @param +* +* @return +* +* @note +* +* +*****************************************************************************/ +static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings) +{ + u32 HandOffAddressLow=0U; + u32 HandOffAddressHigh=0U; + u32 LowAddressReg=0U; + u32 HighAddressReg=0U; + u32 CpuId; + + CpuId = CpuSettings & XIH_PH_ATTRB_DEST_CPU_MASK; + + /** + * copy the IVT to 0xffff0000 + */ + XFsbl_CopyIVT(CpuSettings); + + /** + * Writing u64/u32 will be decided on the handoff Cpu + */ + if (XFsbl_Is32BitCpu(CpuSettings) == TRUE) + { + /** + * for R5 cpu, write 32bit handoff address + */ + XFsbl_Out32(XFSBL_HANDOFF_ADDR_PTR, + (u32 )HandOffAddress); + } else { + /** + * for A53 cpu, write 64bit handoff address + * to the RVBARADDR in APU + */ + + HandOffAddressLow = (u32 )(HandOffAddress & 0xFFFFFFFFU); + HandOffAddressHigh = (u32 )((HandOffAddress>>32) + & 0xFFFFFFFFU); + switch (CpuId) + { + case XIH_PH_ATTRB_DEST_CPU_A53_0: + LowAddressReg = APU_RVBARADDR0L; + HighAddressReg = APU_RVBARADDR0H; + break; + case XIH_PH_ATTRB_DEST_CPU_A53_1: + LowAddressReg = APU_RVBARADDR1L; + HighAddressReg = APU_RVBARADDR1H; + break; + case XIH_PH_ATTRB_DEST_CPU_A53_2: + LowAddressReg = APU_RVBARADDR2L; + HighAddressReg = APU_RVBARADDR2H; + break; + case XIH_PH_ATTRB_DEST_CPU_A53_3: + LowAddressReg = APU_RVBARADDR3L; + HighAddressReg = APU_RVBARADDR3H; + break; + default: + /** + * error can be triggered here + */ + break; + } + XFsbl_Out32(LowAddressReg, HandOffAddressLow); + XFsbl_Out32(HighAddressReg, HandOffAddressHigh); + } + + return; +} + +/****************************************************************************/ +/** + * This function will copy the Arm predefined code to the Reset IVT address + * + * @param CpuId is used to determine which arm predefined code to be loaded + Supports R5, A53/A53 processors + * + * @return + * + * @note + * + *****************************************************************************/ +static void XFsbl_CopyIVT(u32 CpuSettings) +{ + u32 Index=0U; + const u32 XFsbl_ArmR5PredefinedCode[] = + { + /** + * 1. Move 0xffffff00 to r0 + * 2. load value stored in r0 to lr + * 3. dsb + * 4. isb + * 5. Move 0xAA to r1 + * 6. Move 0xffffff80 to r0 + * 7. str r1 to [r0] + * 8. dsb + * 9. isb + * 10. branch to lr + */ + + /* mvn r0, #255 */ + 0xE3E000FFU, + /* ldr lr, [r0] */ + 0xE590E000U, + /* dsb */ + 0xF57FF04FU, + /* isb */ + 0xF57FF06FU, + /* mov r1, #170 */ + 0xE3A010AAU, + /* mvn r0, #127 */ + 0xE3E0007FU, + /* str r1, [r0] */ + 0xE5801000U, + /* dsb */ + 0xF57FF04FU, + /* isb */ + 0xF57FF06FU, + /* bx lr */ + 0xE12FFF1EU + }; + + /** + * Load the predefined ARM code to the reset vector address + * For R5 load the R5 code otherwise A53 code + */ + if (XFsbl_Is32BitCpu(CpuSettings) == TRUE) + { + /** + * Load R5 code + */ + for (Index=0U;Index<10U;Index++) + { + XFsbl_Out32(XFSBL_IVT_ADDRESS + (Index*4U), + XFsbl_ArmR5PredefinedCode[Index]); + } + } + return; +} + +/*****************************************************************************/ +/** + * This function handoff the images to the respective cpu's + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return returns the error codes described in xfsbl_error.h on any error + * + * @note This function should not return incase of success + * + *****************************************************************************/ + +u32 XFsbl_Handoff (XFsblPs * FsblInstancePtr) +{ + u32 Status=XFSBL_SUCCESS; + u32 CpuIndex=0U; + u32 CpuId=0U; + u32 ExecState=0U; + u32 CpuSettings=0U; + u64 HandoffAddress=0U; + u64 RunningCpuHandoffAddress=0U; + u32 RunningCpuExecState=0U; + s32 RunningCpuHandoffAddressPresent=FALSE; + + /** + * post config from ps8_init.c + */ + + /** + * if JTAG bootmode, be in while loop as of now + * Check if Process can be parked in HALT state + */ + if (FsblInstancePtr->PrimaryBootDevice == + XFSBL_JTAG_BOOT_MODE) + { + /** + * Mark Error status with Fsbl completed + */ + XFsbl_Out32(XFSBL_ERROR_STATUS_REGISTER_OFFSET, + XFSBL_COMPLETED); + + if (XFSBL_PLATFORM == XFSBL_PLATFORM_VELOCE) + { + /** + * Flush the L1 data cache and L2 cache + */ + Xil_DCacheFlush(); + + /** + * Disable Data Cache + */ + Xil_DCacheDisable(); + XFsbl_Printf(DEBUG_GENERAL,"VeloceExit from FSBL \n\r"); +#ifdef XFSBL_A53 + XFsbl_Out32(0xFFFC0000U, 0x14000000U); +#else + XFsbl_Out32(0xFFFC0000U, 0xEAFFFFFEU); +#endif + XFsbl_Exit(0xFFFC0000U, XFSBL_HANDOFFEXIT); + } else { + /** + * Exit from FSBL + */ + XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT); + } + } + + /** + * if XIP image present + * Put QSPI in linear mode + */ + + /** + * FSBL hook before Handoff + */ + Status = XFsbl_HookBeforeHandoff(); + if (Status != XFSBL_SUCCESS) + { + Status = XFSBL_ERROR_HOOK_BEFORE_HANDOFF; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_HOOK_BEFORE_HANDOFF\r\n"); + goto END; + } + + /** + * Flush the L1 data cache and L2 cache + */ + Xil_DCacheFlush(); + + /** + * Disable Data Cache to have smooth data + * transfer between the processors. + * Data transfer is required to update flag for CPU out of reset + */ + Xil_DCacheDisable(); + + /** + * get cpu out of reset + * + */ + CpuIndex=0U; + while (CpuIndex < FsblInstancePtr->HandoffCpuNo) + { + CpuSettings = + FsblInstancePtr->HandoffValues[CpuIndex].CpuSettings; + + CpuId = CpuSettings & XIH_PH_ATTRB_DEST_CPU_MASK; + ExecState = CpuSettings & XIH_PH_ATTRB_A53_EXEC_ST_MASK; + + /** + * Check if handoff address is present + */ + if (CpuId != FsblInstancePtr->ProcessorID) + { + /** + * Check for power status of the cpu + * Update the IVT + * Take cpu out of reset + */ + Status = XFsbl_SetCpuPwrSettings( + CpuSettings, XFSBL_CPU_POWER_UP); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"Power Up " + "Cpu 0x%0lx failed \n\r", CpuId); + + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_PWR_UP_CPU\n\r"); + Status = XFSBL_ERROR_PWR_UP_CPU; + goto END; + } + + /** + * Read the handoff address from structure + */ + HandoffAddress = (u64 ) + FsblInstancePtr->HandoffValues[CpuIndex].HandoffAddress; + + /** + * Update the handoff address at reset vector address + */ + XFsbl_UpdateResetVector(HandoffAddress, CpuSettings); + + XFsbl_Printf(DEBUG_INFO,"CPU 0x%0lx reset release, " + "Exec State 0x%0lx, HandoffAddress: %0lx\n\r", + CpuId, ExecState, (PTRSIZE )HandoffAddress); + + /** + * Reset the flag at 0xffffff80 + * Write Zero at 0xffffff80 + */ + XFsbl_Out32(XFSBL_HANDOFF_FLAG_ADDR, 0U); + /** + * Take CPU out of reset + */ + Status = XFsbl_SetCpuPwrSettings( + CpuSettings, XFSBL_CPU_SWRST); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * Wait till the CPU executed the + * predefined code for R5 + */ + if ((CpuId == XIH_PH_ATTRB_DEST_CPU_R5_0) || + (CpuId == XIH_PH_ATTRB_DEST_CPU_R5_1) || + (CpuId == XIH_PH_ATTRB_DEST_CPU_R5_L) ) + { + while (XFsbl_In32(XFSBL_HANDOFF_FLAG_ADDR) + != 0xAAU) + { + /** + * wait for flag + * block for MISRA C compliance + */ + }; + } + + } else { + /** + * Update the running cpu handoff address + */ + RunningCpuHandoffAddressPresent = TRUE; + RunningCpuHandoffAddress = (u64 ) + FsblInstancePtr->HandoffValues[CpuIndex].HandoffAddress; + RunningCpuExecState = ExecState; + } + + /** + * Go to the next cpu + */ + CpuIndex++; + } + + + /** + * Remove the R5 vectors from TCM and load APP data + * if present + */ + if (TcmSkipLength != 0U) + { + XFsbl_MemCpy((u8 *)TcmSkipAddress, TcmVectorArray, + TcmSkipLength); + } + + + /** + * Mark Error status with Fsbl completed + */ + XFsbl_Out32(XFSBL_ERROR_STATUS_REGISTER_OFFSET, XFSBL_COMPLETED); + + /** + * call to the handoff routine + * which will never return + */ + if (RunningCpuHandoffAddressPresent == TRUE) + { + XFsbl_Printf(DEBUG_INFO, + "Running Cpu Handoff address: 0x%0lx, Exec State: %0lx\n\r", + (PTRSIZE )RunningCpuHandoffAddress, RunningCpuExecState); + if (RunningCpuExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32) + { + XFsbl_HandoffExit(RunningCpuHandoffAddress, + XFSBL_HANDOFFEXIT_32); + } else { + XFsbl_HandoffExit(RunningCpuHandoffAddress, + XFSBL_HANDOFFEXIT); + } + } else { + XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT); + } + +END: + return Status; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.c new file mode 100644 index 00000000..7e1f0665 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.c @@ -0,0 +1,99 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_hooks.c +* +* This is the file which contains FSBL hook functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   04/21/14 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xfsbl_hooks.h" +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +u32 XFsbl_HookBeforeBSDownload(void ) +{ + u32 Status = XFSBL_SUCCESS; + + /** + * Add the code here + */ + + + return Status; +} + + +u32 XFsbl_HookAfterBSDownload(void ) +{ + u32 Status = XFSBL_SUCCESS; + + /** + * Add the code here + */ + + return Status; +} + + +u32 XFsbl_HookBeforeHandoff(void ) +{ + u32 Status = XFSBL_SUCCESS; + + /** + * Add the code here + */ + + return Status; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.h new file mode 100644 index 00000000..0e675b05 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hooks.h @@ -0,0 +1,84 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_hooks.h +* +* This is the header file which contains definitions for the FSBL hooks +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ +#ifndef XFSBL_HOOKS_H +#define XFSBL_HOOKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xfsbl_hw.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +u32 XFsbl_HookBeforeBSDownload(void ); + +u32 XFsbl_HookAfterBSDownload(void ); + +u32 XFsbl_HookBeforeHandoff(void ); + + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_HOOKS_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h new file mode 100644 index 00000000..7ac4440f --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h @@ -0,0 +1,540 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_hw.h +* +* This is the header file which contains definitions for the hardware +* registers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_HW_H +#define XFSBL_HW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "xparameters.h" +#include "xil_types.h" +#include "sleep.h" + +#include "xfsbl_config.h" +#include "xfsbl_debug.h" +#include "xfsbl_error.h" +#include "xfsbl_hooks.h" +#include "xfsbl_misc.h" + +/************************** Constant Definitions *****************************/ + +/* csu */ + +/** + * CSU Base Address + */ +#define CSU_BASEADDR 0XFFCA0000U + +/** + * Register: CSU_CSU_SSS_CFG + */ +#define CSU_CSU_SSS_CFG ( ( CSU_BASEADDR ) + 0X00000008U ) +#define CSU_CSU_SSS_CFG_PCAP_SSS_MASK 0X0000000FU + +/** + * Register: CSU_PCAP_STATUS + */ +#define CSU_PCAP_STATUS ( ( CSU_BASEADDR ) + 0X00003010U ) + +/** + * Register: CSU_PCAP_RDWR + */ +#define CSU_PCAP_RDWR ( ( CSU_BASEADDR ) + 0X00003004U ) + +/** + * Register: CSU_VERSION + */ +#define CSU_VERSION ( ( CSU_BASEADDR ) + 0X00000044U ) +#define CSU_VERSION_RTL_VERSION_MASK 0X00000FF0U + +#define CSU_VERSION_PLATFORM_MASK 0X0000F000U + +/** + * Register: CSU_CSU_MULTI_BOOT + */ +#define CSU_CSU_MULTI_BOOT ( ( CSU_BASEADDR ) + 0X00000010U ) + +/** + * Register: CSU_SHA_RESET + */ +#define CSU_SHA_RESET ( ( CSU_BASEADDR ) + 0X00002004U ) +#define CSU_SHA_RESET_RESET_MASK 0X00000001U + +/** + * Register: CSU_SHA_START + */ +#define CSU_SHA_START ( ( CSU_BASEADDR ) + 0X00002000U ) +#define CSU_SHA_START_START_MSG_MASK 0X00000001U + +/** + * Register: CSU_SHA_DONE + */ +#define CSU_SHA_DONE ( ( CSU_BASEADDR ) + 0X00002008U ) +#define CSU_SHA_DONE_SHA_DONE_MASK 0X00000001U + +/** + * Register: CSU_SHA_DIGEST_0 + */ +#define CSU_SHA_DIGEST_0 ( ( CSU_BASEADDR ) + 0X00002010U ) + + +/* efuse */ + +/** + * EFUSE Base Address + */ +#define EFUSE_BASEADDR 0XFFCC0000U + +/** + * Register: EFUSE_SEC_CTRL + */ +#define EFUSE_SEC_CTRL ( ( EFUSE_BASEADDR ) + 0X00001000U ) + +/** + * Register: EFUSE_RSA_CTRL + */ +#define EFUSE_RSA_CTRL ( ( EFUSE_BASEADDR ) + 0X00001060U ) +#define EFUSE_RSA_CTRL_RSA_EN_MASK 0X00000001U + + +/* csudma */ + +/** + * CSUDMA Base Address + */ +#define CSUDMA_BASEADDR 0XFFC80000U + +/* crf_apb */ + +/** + * CRF_APB Base Address + */ +#define CRF_APB_BASEADDR 0XFD1A0000U + +/** + * Register: CRF_APB_RST_FPD_APU + */ +#define CRF_APB_RST_FPD_APU ( ( CRF_APB_BASEADDR ) + 0X00000104U ) +#define CRF_APB_RST_FPD_APU_ACPU0_RESET_MASK 0X00000001U +#define CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK 0X00000100U + +/** + * Register: CRF_APB_ACPU_CTRL + */ +#define CRF_APB_ACPU_CTRL ( ( CRF_APB_BASEADDR ) + 0X00000060U ) +#define CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK 0X01000000U +#define CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK 0X02000000U +#define CRF_APB_RST_FPD_APU_ACPU1_RESET_MASK 0X00000002U +#define CRF_APB_RST_FPD_APU_ACPU2_RESET_MASK 0X00000004U +#define CRF_APB_RST_FPD_APU_ACPU3_RESET_MASK 0X00000008U + +/* crl_apb */ + +/** + * CRL_APB Base Address + */ +#define CRL_APB_BASEADDR 0XFF5E0000U + +/** + * Register: CRL_APB_CPU_R5_CTRL + */ +#define CRL_APB_CPU_R5_CTRL ( ( CRL_APB_BASEADDR ) + 0X00000090U ) +#define CRL_APB_CPU_R5_CTRL_CLKACT_MASK 0X01000000U + +/** + * Register: CRL_APB_RST_LPD_TOP + */ +#define CRL_APB_RST_LPD_TOP ( ( CRL_APB_BASEADDR ) + 0X0000023CU ) +#define CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK 0X00000001U +#define CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK 0X00000004U +#define CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK 0X00000002U + +/** + * Register: CRL_APB_BOOT_MODE_USER + */ +#define CRL_APB_BOOT_MODE_USER ( ( CRL_APB_BASEADDR ) + 0X00000200U ) +#define CRL_APB_BOOT_MODE_USER_BOOT_MODE_MASK 0X0000000FU + +/* apu */ + +/** + * APU Base Address + */ +#define APU_BASEADDR 0XFD5C0000U + +/** + * Register: APU_CONFIG_0 + */ +#define APU_CONFIG_0 ( ( APU_BASEADDR ) + 0X00000020U ) + +/** + * Register: APU_RVBARADDR0L + */ +#define APU_RVBARADDR0L ( ( APU_BASEADDR ) + 0X00000040U ) + +/** + * Register: APU_RVBARADDR0H + */ +#define APU_RVBARADDR0H ( ( APU_BASEADDR ) + 0X00000044U ) + +/** + * Register: APU_RVBARADDR1L + */ +#define APU_RVBARADDR1L ( ( APU_BASEADDR ) + 0X00000048U ) + +/** + * Register: APU_RVBARADDR1H + */ +#define APU_RVBARADDR1H ( ( APU_BASEADDR ) + 0X0000004CU ) + +/** + * Register: APU_RVBARADDR2L + */ +#define APU_RVBARADDR2L ( ( APU_BASEADDR ) + 0X00000050U ) + +/** + * Register: APU_RVBARADDR2H + */ +#define APU_RVBARADDR2H ( ( APU_BASEADDR ) + 0X00000054U ) + +/** + * Register: APU_RVBARADDR3L + */ +#define APU_RVBARADDR3L ( ( APU_BASEADDR ) + 0X00000058U ) + +/** + * Register: APU_RVBARADDR3H + */ +#define APU_RVBARADDR3H ( ( APU_BASEADDR ) + 0X0000005CU ) + +/* pmu_global */ + +/** + * Register: PMU_GLOBAL_PERS_GLOB_GEN_STORAGE1 + */ +#define PMU_GLOBAL_PERS_GLOB_GEN_STORAGE1 ( ( PMU_GLOBAL_BASEADDR ) + 0X00000054U ) + +/** + * PMU_GLOBAL Base Address + */ +#define PMU_GLOBAL_BASEADDR 0XFFD80000U + +/* rpu */ + +/** + * RPU Base Address + */ +#define RPU_BASEADDR 0XFF9A0000U + +/** + * Register: RPU_RPU_GLBL_CNTL + */ +#define RPU_RPU_GLBL_CNTL ( ( RPU_BASEADDR ) + 0X00000000U ) +#define RPU_RPU_GLBL_CNTL_SLSPLIT_MASK 0X00000008U +#define RPU_RPU_GLBL_CNTL_TCM_COMB_MASK 0X00000040U +#define RPU_RPU_GLBL_CNTL_SLCLAMP_MASK 0X00000010U + +/** + * Register: RPU_RPU_0_CFG + */ +#define RPU_RPU_0_CFG ( ( RPU_BASEADDR ) + 0X00000100U ) +#define RPU_RPU_0_CFG_NCPUHALT_MASK 0X00000001U + +/** + * Register: RPU_RPU_1_CFG + */ +#define RPU_RPU_1_CFG ( ( RPU_BASEADDR ) + 0X00000200U ) +#define RPU_RPU_1_CFG_NCPUHALT_MASK 0X00000001U + + +/* rsa */ + +/** + * RSA Base Address + */ +#define RSA_BASEADDR 0XFFCE002CU + +/** + * Register: RSA_WR_DATA_0 + */ +#define RSA_WR_DATA_0 ( ( RSA_BASEADDR ) + 0X00000000U ) + +/** + * Register: RSA_WR_ADDR + */ +#define RSA_WR_ADDR ( ( RSA_BASEADDR ) + 0X00000018U ) + +/** + * Register: RSA_RD_ADDR + */ +#define RSA_RD_ADDR ( ( RSA_BASEADDR ) + 0X00000034U ) + +/** + * Register: RSA_RD_DATA_0 + */ +#define RSA_RD_DATA_0 ( ( RSA_BASEADDR ) + 0X0000001CU ) + +/* rsa_core */ + +/** + * RSA_CORE Base Address + */ +#define RSA_CORE_BASEADDR 0XFFCE0000U + +/** + * Register: RSA_CORE_MINV0 + */ +#define RSA_CORE_MINV0 ( ( RSA_CORE_BASEADDR ) + 0X00000018U ) + +/** + * Register: RSA_CORE_MINV1 + */ +#define RSA_CORE_MINV1 ( ( RSA_CORE_BASEADDR ) + 0X0000001CU ) + +/** + * Register: RSA_CORE_MINV2 + */ +#define RSA_CORE_MINV2 ( ( RSA_CORE_BASEADDR ) + 0X00000020U ) + +/** + * Register: RSA_CORE_MINV3 + */ +#define RSA_CORE_MINV3 ( ( RSA_CORE_BASEADDR ) + 0X00000024U ) + +/** + * Register: RSA_CORE_STATUS + */ +#define RSA_CORE_STATUS ( ( RSA_CORE_BASEADDR ) + 0X00000014U ) +#define RSA_CORE_STATUS_ERROR_MASK 0X00000004U +#define RSA_CORE_STATUS_DONE_MASK 0X00000001U + +/** + * Register: RSA_CORE_CTRL + */ +#define RSA_CORE_CTRL ( ( RSA_CORE_BASEADDR ) + 0X00000010U ) + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + + +/** + * For error reporting PMU_GLOBAL_PERS_GLOB_GEN_STORAGE1 is used + */ +#define XFSBL_ERROR_STATUS_REGISTER_OFFSET (PMU_GLOBAL_PERS_GLOB_GEN_STORAGE1) +#define XFSBL_PMU_RAM_ADDRESS (0xFFDC0000U) + +/** + * ARM Processor defines + */ +#define XFSBL_CLUSTER_ID_MASK (0x00000F00U) +#define XFSBL_A53_PROCESSOR (0x00000000U) +#define XFSBL_R5_PROCESSOR (0x00000100U) + + +/** + * Other FSBL defines + * this can defined in xfsbl_main.h + */ +#define XFSBL_DDR_TEMP_ADDRESS (0x100000U) +#define XFSBL_R5_0 (0x1U) +#define XFSBL_R5_L (0x2U) + +/** + * TCM address for R5 + */ +#define XFSBL_R5_TCM_START_ADDRESS (0x0U) +#define XFSBL_R5_TCM_END_ADDRESS (0x20000U) +#define XFSBL_R5L_TCM_END_ADDRESS (0x40000U) + +#define XFSBL_R50_HIGH_TCM_START_ADDRESS (0xFFE00000U) +#define XFSBL_R51_HIGH_TCM_START_ADDRESS (0xFFE90000U) + +#define XFSBL_R5_TCM_LENGTH (0x10000U) + +/** + * defines for the FSBL peripherals present + */ + +/** + * Definition for WDT to be included + */ +#ifdef XPAR_XWDTPS_0_DEVICE_ID +/*#define XFSBL_WDT_PRESENT*/ +#endif + +/** + * Definition for SD to be included + */ +#if !defined(FSBL_SD_EXCLUDE) & defined( XPAR_XSDPS_0_DEVICE_ID) +#define XFSBL_SD +#endif + +/** + * Definition for QSPI to be included + */ +#if !defined(FSBL_QSPI_EXCLUDE) & defined(XPAR_XQSPIPS_0_DEVICE_ID) +#define XFSBL_QSPI +#define XFSBL_QSPI_BASEADDRESS XPAR_XQSPIPS_0_BASEADDR +#endif + +/** + * Definition for NAND to be included + */ +#if !defined(FSBL_NAND_EXCLUDE) & defined(XPAR_XNANDPS8_0_DEVICE_ID) +#define XFSBL_NAND +#endif + +/** + * Definition for RSA to be included + */ +#if !defined(FSBL_RSA_EXCLUDE) +#define XFSBL_RSA +#endif + + +#define XFSBL_QSPI_LINEAR_BASE_ADDRESS_START (0xC0000000U) +#define XFSBL_QSPI_LINEAR_BASE_ADDRESS_END (0xDFFFFFFFU) + +#define XFSBL_PS_DDR +#define XFSBL_PS_DDR_START_ADDRESS (0x0U) +#define XFSBL_PS_DDR_END_ADDRESS (0x80000000U) //2GB of DDR + +#define XFSBL_OCM +#define XFSBL_OCM_START_ADDRESS (0xFFFE2000U) +#define XFSBL_OCM_END_ADDRESS (0xFFFF0000U) + +#ifdef XFSBL_A53 +#define PTRSIZE u64 +#else +#define PTRSIZE u32 +#endif + + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XFsbl_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XFsbl_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +#define XFsbl_In32(Addr) Xil_In32(Addr) + +#define XFsbl_In64(Addr) Xil_In64(Addr) + +/****************************************************************************/ +/** +* +* Write to the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XFsbl_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XFsbl_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +#define XFsbl_Out32(Addr, Data) Xil_Out32(Addr, Data) + +#define XFsbl_Out64(Addr, Data) Xil_Out64(Addr, Data) + +/** + * Platform + */ +#if 1 +#define XFSBL_PLATFORM \ + (Xil_In32(CSU_VERSION) & CSU_VERSION_PLATFORM_MASK ) +#else +#define XFSBL_PLATFORM XFSBL_PLATFORM_VELOCE +#endif + +#define XFSBL_RTL_VERSION \ + (Xil_In32(CSU_VERSION) & CSU_VERSION_RTL_VERSION_MASK ) + +#define XFSBL_PLATFORM_SILICON (0X00000000U) +#define XFSBL_PLATFORM_REMUS (0X00001000U) +#define XFSBL_PLATFORM_VELOCE (0X00002000U) +#define XFSBL_PLATFORM_QEMU (0X00003000U) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_HW_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.c new file mode 100644 index 00000000..507f12e7 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.c @@ -0,0 +1,733 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_image_header.c +* +* This is the image header C file which does validation for the image header. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xfsbl_image_header.h" +#include "xfsbl_misc_drivers.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +__inline u32 XFsbl_GetPartitionOwner( + XFsblPs_PartitionHeader * PartitionHeader) +{ + return PartitionHeader->PartitionAttributes & + XIH_PH_ATTRB_PART_OWNER_MASK; + +} + +__inline u32 XFsbl_IsRsaSignaturePresent( + XFsblPs_PartitionHeader * PartitionHeader) +{ + return PartitionHeader->PartitionAttributes & + XIH_PH_ATTRB_RSA_SIGNATURE_MASK; +} + +__inline u32 XFsbl_GetChecksumType( + XFsblPs_PartitionHeader * PartitionHeader) +{ + return PartitionHeader->PartitionAttributes & + XIH_PH_ATTRB_CHECKSUM_MASK; +} + +__inline u32 XFsbl_GetDestinationCpu( + XFsblPs_PartitionHeader * PartitionHeader) +{ + return PartitionHeader->PartitionAttributes & + XIH_PH_ATTRB_DEST_CPU_MASK; +} + + +__inline u32 XFsbl_IsEncrypted( + XFsblPs_PartitionHeader * PartitionHeader) +{ + return PartitionHeader->PartitionAttributes & + XIH_PH_ATTRB_ENCRYPTION_MASK; +} + +__inline u32 XFsbl_GetDestinationDevice( + XFsblPs_PartitionHeader * PartitionHeader) +{ + return PartitionHeader->PartitionAttributes & + XIH_PH_ATTRB_DEST_DEVICE_MASK; +} + +__inline u32 XFsbl_GetA53ExecState( + XFsblPs_PartitionHeader * PartitionHeader) +{ + return PartitionHeader->PartitionAttributes & + XIH_PH_ATTRB_A53_EXEC_ST_MASK; +} + +/************************** Function Prototypes ******************************/ +static u32 XFsbl_ValidateImageHeaderTable( + XFsblPs_ImageHeaderTable * ImageHeaderTable); +static u32 XFsbl_CheckValidMemoryAddress(u64 Address, u32 CpuId); + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* This function is used to validate the word checksum for the image header +* table and partition headers. +* Checksum is based on the below formulae +* Checksum = ~(X1 + X2 + X3 + .... + Xn) +* +* @param Buffer pointer for the data words. +* +* @param Length of the buffer for which checksum should be calculated. +* last word is taken as checksum for the data to be compared against +* +* @return +* - XFSBL_SUCCESS for successful checksum validation +* - XFSBL_FAILURE if checksum validation fails +* +* @note +* +*****************************************************************************/ +u32 XFsbl_ValidateChecksum(u32 Buffer[], u32 Length) +{ + u32 Status=XFSBL_SUCCESS; + u32 Checksum=0U; + u32 Count=0U; + + /** + * Length has to be atleast equal to 2, + */ + if (Length < 2U) + { + Status = XFSBL_FAILURE; + goto END; + } + + /** + * Checksum = ~(X1 + X2 + X3 + .... + Xn) + * Calculate the checksum + */ + for (Count = 0U; Count < (Length-1U); Count++) { + /** + * Read the word from the header + */ + Checksum += Buffer[Count]; + } + + /** + * Invert checksum + */ + Checksum ^= 0xFFFFFFFFU; + + /** + * Validate the checksum + */ + if (Buffer[Length-1U] != Checksum) { + XFsbl_Printf(DEBUG_GENERAL, + "Error: Checksum 0x%0lx != %0lx\r\n", + Checksum, Buffer[Length-1U]); + Status = XFSBL_FAILURE; + } + +END: + return Status; +} + +/****************************************************************************/ +/** +* This function checks the fields of the image header table and validates +* them. Image header table contains the fields that common across the +* partitions and for image +* +* @param ImageHeaderTable pointer to the image header table. +* +* @return +* - XFSBL_SUCCESS on successful image header table validation +* - errors as mentioned in xfsbl_error.h +* +* @note +* +*****************************************************************************/ + +static u32 XFsbl_ValidateImageHeaderTable( + XFsblPs_ImageHeaderTable * ImageHeaderTable) +{ + u32 Status = XFSBL_SUCCESS; + u32 PartitionPresentDevice=0U; + + /** + * Check the check sum of the image header table + */ + Status = XFsbl_ValidateChecksum((u32 *)ImageHeaderTable, + XIH_IHT_LEN/XIH_PARTITION_WORD_LENGTH); + if (XFSBL_SUCCESS != Status) + { + Status = XFSBL_ERROR_IHT_CHECKSUM; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_IHT_CHECKSUM\n\r"); + goto END; + } + + /** + * check for no of partitions + */ + if ((ImageHeaderTable->NoOfPartitions <= XIH_MIN_PARTITIONS ) || + (ImageHeaderTable->NoOfPartitions > XIH_MAX_PARTITIONS) ) + { + Status = XFSBL_ERROR_NO_OF_PARTITIONS; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_NO_OF_PARTITIONS\n\r"); + goto END; + } + + /** + * check for the partition present device + */ + PartitionPresentDevice = ImageHeaderTable->PartitionPresentDevice; + if ((PartitionPresentDevice != XIH_IHT_PPD_SAME) && + (PartitionPresentDevice != XIH_IHT_PPD_PCIE) && + (PartitionPresentDevice != XIH_IHT_PPD_ETHERNET) && + (PartitionPresentDevice != XIH_IHT_PPD_SATA) ) + { + Status = XFSBL_ERROR_PPD; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_PPD\n\r"); + goto END; + } + + + /** + * Print the Image header table details + * Print the Bootgen version + */ + XFsbl_Printf(DEBUG_INFO,"*****Image Header Table Details******** \n\r"); + XFsbl_Printf(DEBUG_INFO,"Boot Gen Ver: 0x%0lx \n\r", + ImageHeaderTable->Version); + XFsbl_Printf(DEBUG_INFO,"No of Partitions: 0x%0lx \n\r", + ImageHeaderTable->NoOfPartitions); + XFsbl_Printf(DEBUG_INFO,"Partition Header Address: 0x%0lx \n\r", + ImageHeaderTable->PartitionHeaderAddress); + XFsbl_Printf(DEBUG_INFO,"Partition Present Device: 0x%0lx \n\r", + ImageHeaderTable->PartitionPresentDevice); + +END: + return Status; +} + +/****************************************************************************/ +/** + * This function reads the image header from flash device. Image header + * reads the image header table and partition headers + * + * @param ImageHeader pointer to the image header at which image header to + * be stored + * + * @param DeviceOps pointer deviceops structure which contains the + * function pointer to flash read function + * + * @param FlashImageOffsetAddress base offset to the image in the flash + * + * @return + * - XFSBL_SUCCESS on successful reading image header + * - errors as mentioned in xfsbl_error.h + * + * @note + *****************************************************************************/ +u32 XFsbl_ReadImageHeader(XFsblPs_ImageHeader * ImageHeader, + XFsblPs_DeviceOps * DeviceOps, + u32 FlashImageOffsetAddress) +{ + u32 Status = XFSBL_SUCCESS; + u32 ImageHeaderTableAddressOffset=0U; + u32 PartitionHeaderAddress=0U; + u32 PartitionIndex=0U; + + /** + * Read the Image Header Table offset from + * Boot Header + */ + Status = DeviceOps->DeviceCopy(FlashImageOffsetAddress + + XIH_BH_IH_TABLE_OFFSET, + (PTRSIZE ) &ImageHeaderTableAddressOffset, XIH_FIELD_LEN); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"Device Copy Failed \n\r"); + goto END; + } + XFsbl_Printf(DEBUG_INFO,"Image Header Table Offset 0x%0lx \n\r", + ImageHeaderTableAddressOffset); + + /** + * Read the Image header table of 64 bytes + * and update the image header table structure + */ + Status = DeviceOps->DeviceCopy(FlashImageOffsetAddress + + ImageHeaderTableAddressOffset, + (PTRSIZE ) &(ImageHeader->ImageHeaderTable), + XIH_IHT_LEN); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"Device Copy Failed \n\r"); + goto END; + } + + + /** + * Check the validity of Image Header Table + */ + Status = XFsbl_ValidateImageHeaderTable( + &(ImageHeader->ImageHeaderTable)); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"Image Header Table " + "Validation failed \n\r"); + goto END; + } + + /** + * Update the first partition address + */ + PartitionHeaderAddress = + (ImageHeader->ImageHeaderTable.PartitionHeaderAddress) + * XIH_PARTITION_WORD_LENGTH; + + + /** + * Read the partitions based on the partition offset + * and update the partition header structure + */ + for (PartitionIndex=0U; + PartitionIndexImageHeaderTable.NoOfPartitions; + PartitionIndex++) + { + + /** + * Read the Image header table of 64 bytes + * and update the image header table structure + */ + Status = DeviceOps->DeviceCopy( + FlashImageOffsetAddress + PartitionHeaderAddress, + (PTRSIZE ) &(ImageHeader->PartitionHeader[PartitionIndex]), + XIH_PH_LEN); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"Device Copy Failed \n\r"); + goto END; + } + +#if 0 + /** + * Check the validity of Image Header Table + */ + Status = XFsbl_ValidatePartitionHeader( + &ImageHeader->PartitionHeader[PartitionIndex]); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"Partition %x Header " + "Validation failed \n\r", PartitionIndex); + goto END; + } +#endif + + /** + * Update the next partition present address + */ + PartitionHeaderAddress = + (ImageHeader->PartitionHeader[PartitionIndex].NextPartitionOffset) + * XIH_PARTITION_WORD_LENGTH; + } + +END: + return Status; +} + + +static u32 XFsbl_CheckValidMemoryAddress(u64 Address, u32 CpuId) +{ + u32 Status = XFSBL_SUCCESS; + + /** + * Check if Address is in the range of TCM for R5 + */ + if ((CpuId == XIH_PH_ATTRB_DEST_CPU_R5_0) || + (CpuId == XIH_PH_ATTRB_DEST_CPU_R5_1) || + (CpuId == XIH_PH_ATTRB_DEST_CPU_R5_L) ) + { + if ((Address >= XFSBL_R5_TCM_START_ADDRESS) && + (Address < XFSBL_R5_TCM_END_ADDRESS) ) + { + goto END; + } + } + +#ifdef XFSBL_PS_DDR + /** + * Check if Address is in the range of PS DDR + */ + if ((Address >= XFSBL_PS_DDR_START_ADDRESS) && + (Address < XFSBL_PS_DDR_END_ADDRESS) ) + { + goto END; + } +#endif + +#ifdef XFSBL_PL_DDR + /** + * Check if Address is in the range of PS DDR + */ + if ((Address >= XFSBL_PL_DDR_START_ADDRESS) && + (Address < XFSBL_PL_DDR_END_ADDRESS) ) + { + goto END; + } +#endif + +#ifdef XFSBL_OCM + /** + * Check if Address is in the range of last bank of OCM + */ + if ((Address >= XFSBL_OCM_START_ADDRESS) && + (Address < XFSBL_OCM_END_ADDRESS) ) + { + goto END; + } +#endif + + + /** + * Not a valid address + */ + Status = XFSBL_ERROR_ADDRESS; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_ADDRESS\n\r"); +END: + return Status; +} + + +/****************************************************************************/ +/** +* This function validates the partition header. +* +* @param PartitionHeader is pointer to the XFsblPs_PartitionHeader structure +* +* @return +* - XFSBL_SUCCESS on successful partition header validation +* - errors as mentioned in xfsbl_error.h +* +* @note +* +*****************************************************************************/ +u32 XFsbl_ValidatePartitionHeader( + XFsblPs_PartitionHeader * PartitionHeader, u32 RunningCpu) +{ + u32 Status = XFSBL_SUCCESS; + u32 DestinationCpu=0U; + /* u32 RpuGlobalCntl=0; */ + s32 IsEncrypted=FALSE, IsAuthenticated=FALSE; + + + /** + * Update the variables + */ + if (XFsbl_IsEncrypted(PartitionHeader) == + XIH_PH_ATTRB_ENCRYPTION ) + { + IsEncrypted = TRUE; + } + + if (XFsbl_IsRsaSignaturePresent(PartitionHeader) == + XIH_PH_ATTRB_RSA_SIGNATURE ) + { + IsAuthenticated = TRUE; + } + + + DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader); + + /** + * Partition fields Validation + */ + + + /** + * check for XIP image - partition lengths should be zero + * execution address should be in QSPI + */ + if (PartitionHeader->UnEncryptedDataWordLength == 0U) + { + if ((IsAuthenticated == TRUE ) || + (IsEncrypted == TRUE )) + { + Status = XFSBL_ERROR_XIP_AUTH_ENC_PRESENT; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_XIP_AUTH_ENC_PRESENT\n\r"); + goto END; + } + + if ((PartitionHeader->DestinationExecutionAddress + < XFSBL_QSPI_LINEAR_BASE_ADDRESS_START) || + (PartitionHeader->DestinationExecutionAddress + > XFSBL_QSPI_LINEAR_BASE_ADDRESS_END)) + { + Status = XFSBL_ERROR_XIP_EXEC_ADDRESS; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_XIP_EXEC_ADDRESS\n\r"); + goto END; + } + } + + + /** + * check for authentication and encryption length + */ + if ((IsAuthenticated == FALSE ) && + (IsEncrypted == FALSE )) + { + /** + * all lengths should be equal + */ + if ((PartitionHeader->UnEncryptedDataWordLength != + PartitionHeader->EncryptedDataWordLength) || + (PartitionHeader->EncryptedDataWordLength != + PartitionHeader->TotalDataWordLength)) + { + Status = XFSBL_ERROR_PARTITION_LENGTH; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_PARTITION_LENGTH\n\r"); + goto END; + } + } else if ((IsAuthenticated == TRUE ) && + (IsEncrypted == FALSE )) + { + /** + * TotalDataWordLength should be more + */ + if ((PartitionHeader->UnEncryptedDataWordLength != + PartitionHeader->EncryptedDataWordLength) || + (PartitionHeader->EncryptedDataWordLength >= + PartitionHeader->TotalDataWordLength)) + { + Status = XFSBL_ERROR_PARTITION_LENGTH; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_PARTITION_LENGTH\n\r"); + goto END; + } + } else if ((IsAuthenticated == FALSE ) && + (IsEncrypted == TRUE )) + { + /** + * EncryptedDataWordLength should be more + */ + if ((PartitionHeader->UnEncryptedDataWordLength >= + PartitionHeader->EncryptedDataWordLength) || + (PartitionHeader->EncryptedDataWordLength != + PartitionHeader->TotalDataWordLength)) + { + Status = XFSBL_ERROR_PARTITION_LENGTH; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_PARTITION_LENGTH\n\r"); + goto END; + } + } else /* Authenticated and Encrypted */ + { + /** + * TotalDataWordLength should be more + */ + if ((PartitionHeader->UnEncryptedDataWordLength >= + PartitionHeader->EncryptedDataWordLength) || + (PartitionHeader->EncryptedDataWordLength >= + PartitionHeader->TotalDataWordLength)) + { + Status = XFSBL_ERROR_PARTITION_LENGTH; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_PARTITION_LENGTH\n\r"); + goto END; + } + } + + + /** + * handled on partition copy block + * Check for Destination Load Address, + * executable address + * Address not in TCM, OCM, DDR, PL + * No DDR and address in DDR + */ + Status = XFsbl_CheckValidMemoryAddress( + PartitionHeader->DestinationLoadAddress, + DestinationCpu); + if (Status != XFSBL_SUCCESS) + { + goto END; + } + + /** + * R5 can't access the DDR 0 address as TCM is present there + */ + if ( ((RunningCpu == XIH_PH_ATTRB_DEST_CPU_R5_0) || + (RunningCpu == XIH_PH_ATTRB_DEST_CPU_R5_L)) + && + ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_A53_0) || + (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_A53_1) || + (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_A53_2) || + (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_A53_3) )) + { + /** + * DDR address for A53-x should be greater than TCM + */ + if (PartitionHeader->DestinationLoadAddress < 0x80000U) + { + Status = XFSBL_ERROR_ADDRESS; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_ADDRESS\n\r"); + goto END; + } + } + + + /** + * Checks for invalid checksum type + */ + if ((XFsbl_GetChecksumType(PartitionHeader) != + XIH_PH_ATTRB_NOCHECKSUM) + && (XFsbl_GetChecksumType(PartitionHeader) != + XIH_PH_ATTRB_CHECKSUM_MD5)) + { + Status = XFSBL_ERROR_INVALID_CHECKSUM_TYPE; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_INVALID_CHECKSUM_TYPE\n\r"); + goto END; + } + + /** + * check for invalid cpu + */ + if (DestinationCpu > XIH_PH_ATTRB_DEST_CPU_R5_L) + { + Status = XFSBL_ERROR_INVALID_CPU_TYPE; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_INVALID_CPU_TYPE\n\r"); + goto END; + } + + + /** + * check if + * 1. if FSBL on R5-0 and Destination CPU is R5-L + * 2. if FSBL on R5-L and Destination CPU is R5-0/R5-1 + */ + if ( + (((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_0) || + (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_1)) && + (RunningCpu == XIH_PH_ATTRB_DEST_CPU_R5_L) ) || + + ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_L) && + (RunningCpu == XIH_PH_ATTRB_DEST_CPU_R5_0)) + ) + { + Status = XFSBL_ERROR_LS_CPU_TYPE; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_LS_CPU_TYPE\n\r"); + goto END; + + } + + /** + * check for invalid destination device + */ + if (XFsbl_GetDestinationDevice(PartitionHeader) > + XIH_PH_ATTRB_DEST_DEVICE_PMU) + { + Status = XFSBL_ERROR_INVALID_DEST_DEVICE; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_INVALID_DEST_DEVICE\n\r"); + goto END; + } + + /** + * Check for PMU address not in PMU RAM + */ + if (XFsbl_GetDestinationDevice(PartitionHeader) == + XIH_PH_ATTRB_DEST_DEVICE_PMU) + { + if (PartitionHeader->DestinationLoadAddress != + XFSBL_PMU_RAM_ADDRESS) + { + Status = XFSBL_ERROR_INVALID_LOAD_ADDRESS; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_INVALID_LOAD_ADDRESS\n\r"); + goto END; + } + } + + + /** + * Print Partition Header Details + */ + XFsbl_Printf(DEBUG_INFO,"UnEncrypted data Length: 0x%0lx \n\r", + PartitionHeader->UnEncryptedDataWordLength); + XFsbl_Printf(DEBUG_INFO,"Data word offset: 0x%0lx \n\r", + PartitionHeader->EncryptedDataWordLength); + XFsbl_Printf(DEBUG_INFO,"Total Data word length: 0x%0lx \n\r", + PartitionHeader->TotalDataWordLength); + XFsbl_Printf(DEBUG_INFO,"Destination Load Address: 0x%0lx \n\r", + (PTRSIZE)PartitionHeader->DestinationLoadAddress); + XFsbl_Printf(DEBUG_INFO,"Execution Address: 0x%0lx \n\r", + (PTRSIZE)PartitionHeader->DestinationExecutionAddress); + XFsbl_Printf(DEBUG_INFO,"Data word offset: 0x%0lx \n\r", + PartitionHeader->DataWordOffset); + XFsbl_Printf(DEBUG_INFO,"Partition Attributes: 0x%0lx \n\r", + PartitionHeader->PartitionAttributes); + +END: + return Status; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h new file mode 100644 index 00000000..d263eff0 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h @@ -0,0 +1,249 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_image_header.h +* +* This is the image header file which contains definitions for the image header. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_IH_H +#define XFSBL_IH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xfsbl_misc_drivers.h" + +/************************** Constant Definitions *****************************/ +#define XIH_MIN_PARTITIONS (1U) +#define XIH_MAX_PARTITIONS (32U) +#define XIH_RESERVED_OLD_IH (0x380U) +#define XIH_PARTITION_WORD_LENGTH (0x4U) + +/** + * Boot header field offset + */ +#define XIH_BH_IH_OFFSET (0x3CU) +#define XIH_BH_IMAGE_ATTRB_OFFSET (0x44U) +#define XIH_BH_IH_TABLE_OFFSET (0x98U) +#define XIH_BH_PH_TABLE_OFFSET (0x9CU) + +#define XIH_BH_IMAGE_ATTRB_RSA_MASK (0xC000U) +#define XIH_BH_IMAGE_ATTRB_SHA2_MASK (0x3000U) + +/** + * Defines for length of the headers + */ +#define XIH_FIELD_LEN (4U) +#define XIH_IHT_LEN (64U) +#define XIH_PH_LEN (64U) + +/** + * Image header table field offsets + */ +#define XIH_IHT_VERSION_OFFSET (0x0U) +#define XIH_IHT_NO_OF_PARTITONS_OFFSET (0x4U) +#define XIH_IHT_PH_ADDR_OFFSET (0x8U) +#define XIH_IHT_PPD_OFFSET (0x14U) +#define XIH_IHT_CHECKSUM_OFFSET (0x3CU) + +/** + * Partition Header Fields + */ +#define XIH_PH_ENC_DATAWORD_LENGTH (0x0U) +#define XIH_PH_UNENC_DATAWORD_LENGTH (0x4U) +#define XIH_PH_TOTAL_DATAWORD_LENGTH (0x8U) +#define XIH_PH_NEXT_PARTITION_OFFSET (0xCU) +#define XIH_PH_DEST_EXECUTION_ADDRESS (0x10U) +#define XIH_PH_DEST_LOAD_ADDRESS (0x18U) +#define XIH_PH_DATA_WORD_OFFSET (0x20U) +#define XIH_PH_ATTRB_OFFSET (0x24U) +#define XIH_PH_SECTION_COUNT (0x28U) +#define XIH_PH_CHECKSUM_WORD_OFFSET (0x2CU) +#define XIH_PH_IMAGEHEADER_OFFSET (0x30U) +#define XIH_PH_AUTHCERTIFICATE_OFFSET (0x34U) +#define XIH_PH_CHECKSUM (0x3CU) + +/** + * Partition Present Devices(PPD) in IHT + */ +#define XIH_IHT_PPD_SAME (0x0U) +#define XIH_IHT_PPD_QSPI (0x1U) +#define XIH_IHT_PPD_NAND (0x2U) +#define XIH_IHT_PPD_SD (0x3U) +#define XIH_IHT_PPD_MMC (0x4U) +#define XIH_IHT_PPD_USB (0x5U) +#define XIH_IHT_PPD_ETHERNET (0x6U) +#define XIH_IHT_PPD_PCIE (0x7U) +#define XIH_IHT_PPD_SATA (0x8U) + +/** + * Partition Attribute fields + */ +#define XIH_PH_ATTRB_PART_OWNER_MASK (0x30000U) +#define XIH_PH_ATTRB_RSA_SIGNATURE_MASK (0x8000U) +#define XIH_PH_ATTRB_CHECKSUM_MASK (0x7000U) +#define XIH_PH_ATTRB_DEST_CPU_MASK (0x0F00U) +#define XIH_PH_ATTRB_ENCRYPTION_MASK (0x0080U) +#define XIH_PH_ATTRB_DEST_DEVICE_MASK (0x0070U) +#define XIH_PH_ATTRB_A53_EXEC_ST_MASK (0x0008U) + + +/** + * Partition Attribute Values + */ +#define XIH_PH_ATTRB_PART_OWNER_FSBL (0x00000U) +#define XIH_PH_ATTRB_RSA_SIGNATURE (0x8000U) +#define XIH_PH_ATTRB_NOCHECKSUM (0x0000U) +#define XIH_PH_ATTRB_CHECKSUM_MD5 (0x1000U) + +#define XIH_PH_ATTRB_DEST_CPU_NONE (0x0000U) +#define XIH_PH_ATTRB_DEST_CPU_A53_0 (0x0100U) +#define XIH_PH_ATTRB_DEST_CPU_A53_1 (0x0200U) +#define XIH_PH_ATTRB_DEST_CPU_A53_2 (0x0300U) +#define XIH_PH_ATTRB_DEST_CPU_A53_3 (0x0400U) +#define XIH_PH_ATTRB_DEST_CPU_R5_0 (0x0500U) +#define XIH_PH_ATTRB_DEST_CPU_R5_1 (0x0600U) +#define XIH_PH_ATTRB_DEST_CPU_R5_L (0x0700U) + +#define XIH_PH_ATTRB_ENCRYPTION (0x0080U) + + +#define XIH_PH_ATTRB_DEST_DEVICE_NONE (0x0000U) +#define XIH_PH_ATTRB_DEST_DEVICE_PS (0x0010U) +#define XIH_PH_ATTRB_DEST_DEVICE_PL (0x0020U) +#define XIH_PH_ATTRB_DEST_DEVICE_PMU (0x0030U) + +#define XIH_PH_ATTRB_A53_EXEC_ST_AA32 (0x0008U) +#define XIH_PH_ATTRB_A53_EXEC_ST_AA64 (0x0000U) + +/**************************** Type Definitions *******************************/ + +/** + * Structure to store the image header table details. + * It contains all the information of image header table in order. + */ +typedef struct { + u32 Version; /**< bootgen version used */ + u32 NoOfPartitions; /**< No of partition present */ + u32 PartitionHeaderAddress; /**< Address to start of partition header*/ + u32 Reserved_0xC; /**< Reserved */ + u32 Reserved_0x10; /**< Reserved */ + u32 PartitionPresentDevice; + /**< Partition present device for secondary boot modes*/ + u32 Reserved[9]; /**< Reserved */ + u32 Checksum; /**< Checksum of the image header table */ +} XFsblPs_ImageHeaderTable; + +/** + * Structure to store the partition header details. + * It contains all the information of partition header in order. + */ +typedef struct { + u32 EncryptedDataWordLength; /**< Encrypted word length of partition*/ + u32 UnEncryptedDataWordLength; /**< unencrypted word length */ + u32 TotalDataWordLength; + /**< Total word length including the authentication + certificate if any*/ + u32 NextPartitionOffset; /**< Address of the next partition header*/ + u64 DestinationExecutionAddress; /**< Execution address */ + u64 DestinationLoadAddress; /**< Load address in DDR/TCM */ + u32 DataWordOffset; /**< */ + u32 PartitionAttributes; /**< partition attributes */ + u32 SectionCount; /**< section count */ + u32 ChecksumWordOffset; /**< address to checksum when enabled */ + u32 ImageHeaderOffset; /**< address to image header */ + u32 AuthCertificateOffset; + /**< address to the authentication certificate when enabled */ + u32 Reserved[1]; /**< Reserved */ + u32 Checksum; /**< checksum of the partition header */ +} XFsblPs_PartitionHeader; + +/** + * Structure of the image header which contains + * information of image header table and + * partition headers. + */ +typedef struct { + XFsblPs_ImageHeaderTable ImageHeaderTable; + /**< Image header table structure */ + XFsblPs_PartitionHeader PartitionHeader[XIH_MAX_PARTITIONS]; + /**< Partition header */ +} XFsblPs_ImageHeader; + +/***************** Macros (Inline Functions) Definitions *********************/ +__inline u32 XFsbl_GetPartitionOwner( + XFsblPs_PartitionHeader * PartitionHeader); +__inline u32 XFsbl_IsRsaSignaturePresent( + XFsblPs_PartitionHeader * PartitionHeader); +__inline u32 XFsbl_GetChecksumType( + XFsblPs_PartitionHeader * PartitionHeader); +__inline u32 XFsbl_GetDestinationCpu( + XFsblPs_PartitionHeader * PartitionHeader); +__inline u32 XFsbl_IsEncrypted( + XFsblPs_PartitionHeader * PartitionHeader); +__inline u32 XFsbl_GetDestinationDevice( + XFsblPs_PartitionHeader * PartitionHeader); +__inline u32 XFsbl_GetA53ExecState( + XFsblPs_PartitionHeader * PartitionHeader); + +/************************** Function Prototypes ******************************/ +u32 XFsbl_ValidateChecksum(u32 Buffer[], u32 Length); +u32 XFsbl_ReadImageHeader(XFsblPs_ImageHeader * ImageHeader, + XFsblPs_DeviceOps * DeviceOps, u32 FlashImageOffsetAddress); +u32 XFsbl_ValidateImageHeader(XFsblPs_ImageHeaderTable * ImageHeaderTable); +u32 XFsbl_ValidatePartitionHeader(XFsblPs_PartitionHeader * PartitionHeader, + u32 RunningCpu); + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_IH_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_initialization.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_initialization.c new file mode 100644 index 00000000..87417d0d --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_initialization.c @@ -0,0 +1,721 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* + ******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_initilization.c +* +* This is the file which contains initialization code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xfsbl_main.h" +#include "xfsbl_misc_drivers.h" +#include "pss_init.h" + +#include "xfsbl_qspi.h" + +/************************** Constant Definitions *****************************/ +#define XFSBL_R5_VECTOR_VALUE 0xEAFEFFFEU + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +static u32 XFsbl_ProcessorInit(XFsblPs * FsblInstancePtr); +static u32 XFsbl_ResetValidation(XFsblPs * FsblInstancePtr); +static u32 XFsbl_SystemInit(XFsblPs * FsblInstancePtr); +static u32 XFsbl_PrimaryBootDeviceInit(XFsblPs * FsblInstancePtr); +static u32 XFsbl_ValidateHeader(XFsblPs * FsblInstancePtr); +static u32 XFsbl_SecondaryBootDeviceInit(XFsblPs * FsblInstancePtr); + +/** + * Functions from xfsbl_misc.c + */ +void XFsbl_RegisterHandlers(void); + +/** + *Functions from xfsbl_qspi.c + */ + + + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** + * This function is used to initialize the FsblInstance with the + * default values + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return None + * + * @note + * + *****************************************************************************/ +void XFsbl_CfgInitialize (XFsblPs * FsblInstancePtr) +{ + FsblInstancePtr->Version = 0x3U; + FsblInstancePtr->ErrorCode = XFSBL_SUCCESS; + FsblInstancePtr->HandoffCpuNo = 0U; +} + +/*****************************************************************************/ +/** + * This function is initializes the processor and system. + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return + * - returns the error codes described in xfsbl_error.h on any error + * - returns XFSBL_SUCCESS on success + * + *****************************************************************************/ +u32 XFsbl_Initialize(XFsblPs * FsblInstancePtr) +{ + u32 Status = XFSBL_SUCCESS; + + /** + * Configure the system as in PS8 + */ + Status = XFsbl_SystemInit(FsblInstancePtr); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + +#ifdef STDOUT_BASEADDRESS + Init_Uart(); +#endif + + + /** + * Print the FSBL banner + */ + XFsbl_PrintFsblBanner(); + + /** + * Initialize the processor + */ + Status = XFsbl_ProcessorInit(FsblInstancePtr); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * Validate the reset reason + */ + Status = XFsbl_ResetValidation(FsblInstancePtr); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + XFsbl_Printf(DEBUG_INFO,"Processor Initialization Done \n\r"); +END: + return Status; +} + + +/*****************************************************************************/ +/** + * This function initializes the primary and secondary boot devices + * and validates the image header + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + ******************************************************************************/ +u32 XFsbl_BootDeviceInitAndValidate(XFsblPs * FsblInstancePtr) +{ + u32 Status = XFSBL_SUCCESS; + + /** + * Configure the primary boot device + */ + Status = XFsbl_PrimaryBootDeviceInit(FsblInstancePtr); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * Read and Validate the header + */ + Status = XFsbl_ValidateHeader(FsblInstancePtr); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * Update the secondary boot device + */ + FsblInstancePtr->SecondaryBootDevice = + FsblInstancePtr->ImageHeader.ImageHeaderTable.PartitionPresentDevice; + + /** + * Configure the secondary boot device if required + */ + if (FsblInstancePtr->SecondaryBootDevice != + FsblInstancePtr->PrimaryBootDevice) + { + Status = XFsbl_SecondaryBootDeviceInit(FsblInstancePtr); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function initializes the processor and updates the cluster id + * which indicates CPU on which fsbl is running + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + * + ******************************************************************************/ +static u32 XFsbl_ProcessorInit(XFsblPs * FsblInstancePtr) +{ + u32 Status = XFSBL_SUCCESS; + //u64 ClusterId=0U; + PTRSIZE ClusterId=0U; + u32 RegValue; + u32 Index=0U; + + /** + * Read the cluster ID and Update the Processor ID + * Initialize the processor settings that are not done in + * BSP startup code + */ +#ifdef XFSBL_A53 + ClusterId = mfcp(MPIDR_EL1); +#else + ClusterId = mfcp(XREG_CP15_MULTI_PROC_AFFINITY); +#endif + + XFsbl_Printf(DEBUG_INFO,"Cluster ID 0x%0lx\n\r", ClusterId); + + if (XFSBL_PLATFORM == XFSBL_PLATFORM_QEMU) + { + /** + * Remmaping for R5 in QEMU + */ + if (ClusterId == 0x80000004U) + { + ClusterId = 0xC0000100U; + } + } + + /** + * store the processor ID based on the cluster ID + * Need a check for unsupported Cluster ID + */ + if ((ClusterId & XFSBL_CLUSTER_ID_MASK) == XFSBL_A53_PROCESSOR) + { + XFsbl_Printf(DEBUG_GENERAL,"Running on A53-0 Processor \n\r"); + FsblInstancePtr->ProcessorID = + XIH_PH_ATTRB_DEST_CPU_A53_0; + } else { + RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); + if ((RegValue & RPU_RPU_GLBL_CNTL_SLSPLIT_MASK) == 0U) + { + XFsbl_Printf(DEBUG_GENERAL, + "Running on R5 Processor in Lockstep \n\r"); + FsblInstancePtr->ProcessorID = + XIH_PH_ATTRB_DEST_CPU_R5_L; + } else { + XFsbl_Printf(DEBUG_GENERAL, + "Running on R5-0 Processor \n\r"); + FsblInstancePtr->ProcessorID = + XIH_PH_ATTRB_DEST_CPU_R5_0; + } + + /** + * Update the Vector locations in R5 TCM + */ + while (Index<32U) + { + XFsbl_Out32(Index, 0U); + XFsbl_Out32(Index, XFSBL_R5_VECTOR_VALUE); + Index += 4; + } + + } + + /** + * Enable the exceptions + * Register the exception handlers + */ +#ifndef XFSBL_A53 + XFsbl_RegisterHandlers(); +#endif + return Status; +} + +/*****************************************************************************/ +/** + * This function validates the reset reason + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + * + ******************************************************************************/ + +static u32 XFsbl_ResetValidation(XFsblPs * FsblInstancePtr) +{ + u32 Status = XFSBL_SUCCESS; +#if 0 + u32 FsblErrorStatus=0U; + u32 ResetReasonValue=0U; + + /** + * Read the Error Status register + * If WDT reset, do fallback + */ + FsblErrorStatus = XFsbl_In32(XFSBL_ERROR_STATUS_REGISTER_OFFSET); + + ResetReasonValue = XFsbl_In32(CRL_APB_RESET_REASON); + + /** + * Add LPD_SWDT for r5 + * check if the reset is due to system WDT during + * previous FSBL execution + */ + /* WDT reset is missing in reset reason */ + if (((ResetReasonValue & CRL_APB_RESET_REASON_FPD_SWDT_MASK) + == CRL_APB_RESET_REASON_FPD_SWDT_MASK) && + (FsblErrorStatus == XFSBL_RUNNING)) + { + /** + * reset is due to System WDT. + * Do a fallback + */ + Status = XFSBL_ERROR_SYSTEM_WDT_RESET; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SYSTEM_WDT_RESET\n\r"); + goto END; + } + + /** + * Mark FSBL running in error status register to + * detect the WDT reset while FSBL execution + */ + if (FsblErrorStatus != XFSBL_RUNNING) + { + XFsbl_Out32(XFSBL_ERROR_STATUS_REGISTER_OFFSET, + XFSBL_RUNNING); + } + + /** + * Read system error status register + * provide FsblHook function for any action + */ + +END: +#endif + return Status; +} + +/*****************************************************************************/ +/** + * This function initializes the system using the ps8_init() + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + * + ******************************************************************************/ +static u32 XFsbl_SystemInit(XFsblPs * FsblInstancePtr) +{ + u32 Status = XFSBL_SUCCESS; + + /** + * ps8 initialization + */ + Status = (u32 )pss_init(); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_PS8_INIT_FAILED\n\r"); + /** + * Need to check a way to communicate both FSBL code + * and PS8 init error code + */ + Status = XFSBL_PS8_INIT_FAILED + Status; + goto END; + } + + /** + * DDR Check if present + */ + + + /** + * Poweroff the unused blocks as per PS8 + */ + +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function initializes the primary boot device + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + * + ******************************************************************************/ +static u32 XFsbl_PrimaryBootDeviceInit(XFsblPs * FsblInstancePtr) +{ + u32 Status = XFSBL_SUCCESS; + u32 BootMode=0U; + + /** + * Read Boot Mode register and update the value + */ + BootMode = XFsbl_In32(CRL_APB_BOOT_MODE_USER) & + CRL_APB_BOOT_MODE_USER_BOOT_MODE_MASK; + + FsblInstancePtr->PrimaryBootDevice = BootMode; + + /** + * Enable drivers only if they are device boot modes + * Not required for JTAG modes + */ + if ( (BootMode == XFSBL_QSPI24_BOOT_MODE) || + (BootMode == XFSBL_QSPI32_BOOT_MODE) || + (BootMode == XFSBL_NAND_BOOT_MODE) || + (BootMode == XFSBL_SD_BOOT_MODE) || + (BootMode == XFSBL_EMMC_BOOT_MODE) ) + { + /** + * Initialize the WDT and CSU drivers + */ +#ifdef XFSBL_WDT_PRESENT + Status = XFsbl_InitWdt(); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"WDT initialization failed \n\r"); + goto END; + } +#endif + } + + switch(BootMode) + { + /** + * For JTAG boot mode, it will be in while loop + */ + case XFSBL_JTAG_BOOT_MODE: + { + XFsbl_Printf(DEBUG_GENERAL,"In JTAG Boot Mode \n\r"); + Status = XFSBL_STATUS_JTAG; + } + break; + + case XFSBL_QSPI24_BOOT_MODE: + { +#ifdef XFSBL_QSPI + XFsbl_Printf(DEBUG_GENERAL,"QSPI 24bit Boot Mode \n\r"); + /** + * Update the deviceops structure with necessary values + */ + FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_Qspi24Init; + FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_Qspi24Copy; + FsblInstancePtr->DeviceOps.DeviceRelease = XFsbl_Qspi24Release; +#else + /** + * This bootmode is not supported in this release + */ + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r"); + Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE; +#endif + } + break; + + case XFSBL_QSPI32_BOOT_MODE: + { + XFsbl_Printf(DEBUG_GENERAL,"QSPI 32 bit Boot Mode \n\r"); + /** + * Update the deviceops structure with necessary values + * + */ + + /** + * This bootmode is not supported in this release + */ + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r"); + Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE; + }break; + + case XFSBL_NAND_BOOT_MODE: + { + XFsbl_Printf(DEBUG_GENERAL,"NAND Boot Mode \n\r"); +#ifdef XFSBL_NAND + /** + * Update the deviceops structure with necessary values + * + */ + FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_NandInit; + FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_NandCopy; + FsblInstancePtr->DeviceOps.DeviceRelease = + XFsbl_NandRelease; +#else + /** + * This bootmode is not supported in this release + */ + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r"); + Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE; +#endif + } break; + + case XFSBL_SD_BOOT_MODE: + { + XFsbl_Printf(DEBUG_GENERAL,"SD Boot Mode \n\r"); +#ifdef XFSBL_SD + /** + * Update the deviceops structure with necessary values + */ + FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_SdInit; + FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_SdCopy; + FsblInstancePtr->DeviceOps.DeviceRelease = XFsbl_SdRelease; +#else + /** + * This bootmode is not supported in this release + */ + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r"); + Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE; +#endif + } break; + + case XFSBL_EMMC_BOOT_MODE: + { + XFsbl_Printf(DEBUG_GENERAL,"eMMC Boot Mode \n\r"); + /** + * Update the deviceops structure with necessary values + * + */ + + /** + * This bootmode is not supported in this release + */ + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r"); + Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE; + } break; + + case XFSBL_USB_BOOT_MODE: + { + XFsbl_Printf(DEBUG_GENERAL,"USB Boot Mode \n\r"); + /** + * Update the deviceops structure with necessary values + * + */ + + /** + * This bootmode is not supported in this release + */ + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r"); + Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE; + } break; + + default: + { + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r"); + Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE; + } break; + + } + + /** + * In case of error or Jtag boot, goto end + */ + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * Initialize the Device Driver + */ + Status = FsblInstancePtr->DeviceOps.DeviceInit(); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function validates the image header + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + * + ******************************************************************************/ +static u32 XFsbl_ValidateHeader(XFsblPs * FsblInstancePtr) +{ + u32 Status = XFSBL_SUCCESS; + u32 MultiBootOffset=0U; + u32 BootHdrAttrb=0U; + u32 FlashImageOffsetAddress=0U; + u32 EfuseCtrl=0U; + + /** + * Read the Multiboot Register + */ + MultiBootOffset = XFsbl_In32(CSU_CSU_MULTI_BOOT); + XFsbl_Printf(DEBUG_INFO,"Multiboot Reg : 0x%0lx \n\r", MultiBootOffset); + + /** + * Calculate the Flash Offset Address + */ + FsblInstancePtr->ImageOffsetAddress = + MultiBootOffset * XFSBL_IMAGE_SEARCH_OFFSET; + FlashImageOffsetAddress = FsblInstancePtr->ImageOffsetAddress; + + /** + * Read Boot Image attributes + */ + Status = FsblInstancePtr->DeviceOps.DeviceCopy(FlashImageOffsetAddress + + XIH_BH_IMAGE_ATTRB_OFFSET, + (PTRSIZE ) &BootHdrAttrb, XIH_FIELD_LEN); + if (XFSBL_SUCCESS != Status) + { + XFsbl_Printf(DEBUG_GENERAL,"Device Copy Failed \n\r"); + goto END; + } + FsblInstancePtr->BootHdrAttributes = BootHdrAttrb; + + /** + * Read Image Header and validate Image Header Table + */ + Status = XFsbl_ReadImageHeader(&FsblInstancePtr->ImageHeader, + &FsblInstancePtr->DeviceOps, + FlashImageOffsetAddress); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + + /** + * Read Efuse bit and check Boot Header for Authentication + */ + EfuseCtrl = XFsbl_In32(EFUSE_RSA_CTRL); + if (((EfuseCtrl & EFUSE_RSA_CTRL_RSA_EN_MASK) != 0) || + ((BootHdrAttrb & XIH_BH_IMAGE_ATTRB_RSA_MASK) + == XIH_BH_IMAGE_ATTRB_RSA_MASK)) + { + + XFsbl_Printf(DEBUG_INFO,"Authentication Enabled\r\n"); +#ifdef XFSBL_RSA + /** + * Authenticate the image header + */ + +#else + XFsbl_Printf(DEBUG_GENERAL,"Rsa code not Enabled\r\n"); + Status = XFSBL_ERROR_RSA_NOT_ENABLED; + goto END; +#endif + } +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function initializes secondary boot device + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + * + ******************************************************************************/ +static u32 XFsbl_SecondaryBootDeviceInit(XFsblPs * FsblInstancePtr) +{ + u32 Status = XFSBL_SUCCESS; + + /** + * Update the deviceops structure + */ + + + /** + * Initialize the Secondary Boot Device Driver + */ + + return Status; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.c new file mode 100644 index 00000000..96b68004 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.c @@ -0,0 +1,416 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_main.c +* +* This is the main file which contains code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xfsbl_main.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +XFsblPs FsblInstancePtr; + +/*****************************************************************************/ +/** This is the FSBL main function and is implemented stage wise. + * + * @param None + * + * @return None + * + *****************************************************************************/ +int main(void ) +{ + /** + * Local variables + */ + u32 FsblStatus = XFSBL_SUCCESS; + u32 FsblStage = XFSBL_STAGE1; + u32 PartitionNum=0U; + + /** + * Initialize globals. + */ + FsblInstancePtr.ErrorCode = FsblStatus; + + while (1) { + + switch (FsblStage) + { + + case XFSBL_STAGE1: + { + /** + * Initialize the system + */ + XFsbl_CfgInitialize(&FsblInstancePtr); + + FsblStatus = XFsbl_Initialize(&FsblInstancePtr); + if (XFSBL_SUCCESS != FsblStatus) + { + FsblStatus += XFSBL_ERROR_STAGE_1; + FsblStage = XFSBL_STAGE_ERR; + } else { + + /** + * + * Include the code for FSBL time measurements + * Initialize the global timer and get the value + */ + + FsblStage = XFSBL_STAGE2; + } + }break; + + case XFSBL_STAGE2: + { + + XFsbl_Printf(DEBUG_INFO, + "================= In Stage 2 ============ \n\r"); + + /** + * Primary Device + * Secondary boot device + * DeviceOps + * image header + * partition header + */ + FsblStatus = XFsbl_BootDeviceInitAndValidate(&FsblInstancePtr); + if ( (XFSBL_SUCCESS != FsblStatus) && + (XFSBL_STATUS_JTAG != FsblStatus) ) + { + XFsbl_Printf(DEBUG_GENERAL,"Boot Device " + "Initialization failed 0x%0lx\n\r", FsblStatus); + FsblStatus += XFSBL_ERROR_STAGE_2; + FsblStage = XFSBL_STAGE_ERR; + } else if (XFSBL_STATUS_JTAG == FsblStatus) { + /** + * This is JTAG boot mode, go to the handoff stage + */ + FsblStage = XFSBL_STAGE4; + } else { + XFsbl_Printf(DEBUG_INFO,"Initialization Success \n\r"); + + /** + * Start the partition loading from 1 + * 0th partition will be FSBL + */ + PartitionNum = 0x1U; + + FsblStage = XFSBL_STAGE3; + } + } break; + + case XFSBL_STAGE3: + { + + XFsbl_Printf(DEBUG_INFO, + "======= In Stage 3, Partition No:%d ======= \n\r", + PartitionNum); + + /** + * Load the partitions + * image header + * partition header + * partition parameters + */ + FsblStatus = XFsbl_PartitionLoad(&FsblInstancePtr, + PartitionNum); + if (XFSBL_SUCCESS != FsblStatus) + { + /** + * Error + */ + XFsbl_Printf(DEBUG_GENERAL,"Partition %d Load Failed, 0x%0lx\n\r", + PartitionNum, FsblStatus); + FsblStatus += XFSBL_ERROR_STAGE_3; + FsblStage = XFSBL_STAGE_ERR; + } else { + XFsbl_Printf(DEBUG_INFO,"Partition %d Load Success \n\r", + PartitionNum); + /** + * Check loading all partitions is completed + */ + if (PartitionNum < + (FsblInstancePtr.ImageHeader.ImageHeaderTable.NoOfPartitions-1U)) + { + /** + * No need to change the Fsbl Stage + * Load the next partition + */ + PartitionNum++; + } else { + /** + * No more partitions present, go to handoff stage + */ + XFsbl_Printf(DEBUG_INFO,"All Partitions Loaded \n\r"); + FsblStage = XFSBL_STAGE4; + + } + } /* End of else loop for Load Success */ + } break; + + case XFSBL_STAGE4: + { + + XFsbl_Printf(DEBUG_INFO, + "================= In Stage 4 ============ \n\r"); + + /** + * Handoff to the applications + * Handoff address + * xip + * ps7 post config + */ + FsblStatus = XFsbl_Handoff(&FsblInstancePtr); + if (XFSBL_SUCCESS != FsblStatus) + { + /** + * Error + */ + XFsbl_Printf(DEBUG_GENERAL,"Handoff Failed 0x%0lx\n\r", FsblStatus); + FsblStatus += XFSBL_ERROR_STAGE_4; + FsblStage = XFSBL_STAGE_ERR; + } else { + /** + * we should never be here + */ + FsblStage = XFSBL_STAGE_DEFAULT; + } + } break; + + case XFSBL_STAGE_ERR: + { + XFsbl_Printf(DEBUG_INFO, + "================= In Stage Err ============ \n\r"); + + XFsbl_ErrorLockDown(FsblStatus); + /** + * we should never be here + */ + FsblStage = XFSBL_STAGE_DEFAULT; + }break; + + case XFSBL_STAGE_DEFAULT: + default: + { + /** + * we should never be here + */ + XFsbl_Printf(DEBUG_GENERAL,"In default stage: " + "We should never be here \n\r"); + + /** + * Exit FSBL + */ + XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT); + + }break; + + } /* End of switch(FsblStage) */ + + } /* End of while(1) */ + + /** + * We should never be here + */ + XFsbl_Printf(DEBUG_GENERAL,"In default stage: " + "We should never be here \n\r"); + /** + * Exit FSBL + */ + XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT); + + return 0; +} + +void XFsbl_PrintFsblBanner(void ) +{ + /** + * Print the FSBL Banner + */ + XFsbl_Printf(DEBUG_GENERAL,"Xilinx First Stage Boot Loader \n\r"); + XFsbl_Printf(DEBUG_GENERAL,"Release SW Beta1 %s-%s\r\n", + __DATE__,__TIME__); + /** + * Print the platform + */ + if (XFSBL_PLATFORM == XFSBL_PLATFORM_QEMU) + { + XFsbl_Printf(DEBUG_GENERAL, "Platform: QEMU, "); + } else if (XFSBL_PLATFORM == XFSBL_PLATFORM_REMUS) + { + XFsbl_Printf(DEBUG_GENERAL, "Platform: REMUS, "); + } else if (XFSBL_PLATFORM == XFSBL_PLATFORM_VELOCE) + { + XFsbl_Printf(DEBUG_GENERAL, "Platform: VELOCE, "); + } else { + XFsbl_Printf(DEBUG_GENERAL, "Platform Not identified \r\n"); + } + + /** + * Print the RTL Version + */ + XFsbl_Printf(DEBUG_GENERAL, "RTL Version: %0lx\r\n", XFSBL_RTL_VERSION); + + return ; +} + + + +/*****************************************************************************/ +/** + * This function is called in FSBL error cases. Error status + * register is updated and fallback is applied + * + * @param ErrorStatus is the error code which is written to the + * error status register + * + * @return none + * + * @note Fallback is applied only for fallback supported bootmodes + *****************************************************************************/ +void XFsbl_ErrorLockDown(u32 ErrorStatus) +{ + u32 BootMode=0U; + + /** + * Print the FSBL error + */ + XFsbl_Printf(DEBUG_GENERAL,"Fsbl Error Status: 0x%08lx\r\n", + ErrorStatus); + + /** + * Update the error status register + * and Fsbl instance structure + */ + XFsbl_Out32(XFSBL_ERROR_STATUS_REGISTER_OFFSET, ErrorStatus); + FsblInstancePtr.ErrorCode = ErrorStatus; + + /** + * Read Boot Mode register + */ + BootMode = XFsbl_In32(CRL_APB_BOOT_MODE_USER) & + CRL_APB_BOOT_MODE_USER_BOOT_MODE_MASK; + + /** + * Fallback if bootmode supports + */ + if ( (BootMode == XFSBL_QSPI24_BOOT_MODE) || + (BootMode == XFSBL_QSPI32_BOOT_MODE) || + (BootMode == XFSBL_NAND_BOOT_MODE) || + (BootMode == XFSBL_SD_BOOT_MODE) || + (BootMode == XFSBL_EMMC_BOOT_MODE) ) + { + XFsbl_FallBack(); + } else { + /** + * Be in while loop if fallback is not supported + */ + XFsbl_Printf(DEBUG_GENERAL,"Fallback not supported \n\r"); + + /** + * Exit FSBL + */ + XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT); + } + + /** + * Should never be here + */ + return ; +} + +/*****************************************************************************/ +/** + * In Fallback, soft reset is applied to the system after incrementing + * the multiboot register. A hook is provided to before the fallback so + * that users can write their own code before soft reset + * + * @param none + * + * @return none + * + * @note We will not return from this function as it does soft reset + *****************************************************************************/ +void XFsbl_FallBack(void ) +{ + + /** + * Increment the Multiboot register + */ + + /** + * Hook before FSBL Fallback + */ + + /** + * dsb and isb to make sure every thing completes + */ + + /** + * Soft reset the system + */ + + /** + * Fall back is not supported now, placing CPU in wfe state + * Exit FSBL + */ + XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT); + + return ; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h new file mode 100644 index 00000000..0d3cf39b --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h @@ -0,0 +1,165 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_main.h +* +* This is the main header file which contains definitions for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_MAIN_H +#define XFSBL_MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xfsbl_image_header.h" +#include "xfsbl_misc_drivers.h" +#include "xfsbl_hw.h" +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This stores the handoff Address of the different cpu's + */ +typedef struct { + u32 CpuSettings; + u64 HandoffAddress; +} XFsblPs_HandoffValues; + +/** + * This is FSBL instance pointer. This stores all the information + * required for FSBL + */ +typedef struct { + u32 Version; /**< FSBL Version */ + u32 PresentStage; /**< Stage */ + u32 ProcessorID; /**< One of R5-0, R5-LS, A53-0 */ + u32 BootHdrAttributes; /**< Boot Header attributes */ + u32 ImageOffsetAddress; /**< Flash offset address */ + XFsblPs_ImageHeader ImageHeader; /** Image header */ + u32 ErrorCode; /**< Error code during FSBL failure */ + u32 PrimaryBootDevice; /**< Primary boot device used for booting */ + u32 SecondaryBootDevice; /**< Secondary boot device in image header*/ + XFsblPs_DeviceOps DeviceOps; /**< Device operations for bootmodes */ + u32 HandoffCpuNo; /**< Number of CPU's FSBL will handoff to */ + XFsblPs_HandoffValues HandoffValues[10]; + /**< Handoff address for different CPU's */ +} XFsblPs; + + +/***************** Macros (Inline Functions) Definitions *********************/ +#define XFSBL_RELEASE_YEAR 2014 +#define XFSBL_RELEASE_VERSION 3 + +#define XFSBL_RUNNING (0xFFFFU) +#define XFSBL_COMPLETED (0x0U) +#define XFSBL_IMAGE_SEARCH_OFFSET (0x8000U) /**< 32KB offset */ + +/** + * Fsbl exit definitions + */ +#define XFSBL_NO_HANDOFFEXIT (0x0U) +#define XFSBL_HANDOFFEXIT (0x1U) +#define XFSBL_HANDOFFEXIT_32 (0x2U) + +/** + * Boot Modes definition + */ +#define XFSBL_JTAG_BOOT_MODE (0x0U) +#define XFSBL_QSPI24_BOOT_MODE (0x1U) +#define XFSBL_QSPI32_BOOT_MODE (0x2U) +#define XFSBL_NAND_BOOT_MODE (0x4U) +#define XFSBL_SD_BOOT_MODE (0x5U) +#define XFSBL_EMMC_BOOT_MODE (0x6U) +#define XFSBL_USB_BOOT_MODE (0x7U) + +/** + * FSBL stages definition + */ +#define XFSBL_STAGE1 (0x1U) +#define XFSBL_STAGE2 (0x2U) +#define XFSBL_STAGE3 (0x3U) +#define XFSBL_STAGE4 (0x4U) +#define XFSBL_STAGE_ERR (0x5U) +#define XFSBL_STAGE_DEFAULT (0x6U) + +/************************** Function Prototypes ******************************/ +/** + * Functions defined in xfsbl_main.c + */ +void XFsbl_PrintFsblBanner(void ); +void XFsbl_ErrorLockDown(u32 ErrorStatus); +void XFsbl_FallBack(void ); + +/** + * Functions defined in xfsbl_initialization.c + */ +void XFsbl_CfgInitialize (XFsblPs * FsblInstancePtr); +u32 XFsbl_Initialize(XFsblPs * FsblInstancePtr); +u32 XFsbl_BootDeviceInitAndValidate(XFsblPs * FsblInstancePtr); + +/** + * Functions defined in xfsbl_partition_load.c + */ +u32 XFsbl_PartitionLoad(XFsblPs * FsblInstancePtr, u32 PartitionNum); + +/** + * Functions defined in xfsbl_handoff.c + */ +u32 XFsbl_Handoff (XFsblPs * FsblInstancePtr); +void XFsbl_HandoffExit(u64 HandoffAddress, u32 Flags); +/************************** Variable Definitions *****************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_MAIN_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.c new file mode 100644 index 00000000..c8f428c2 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.c @@ -0,0 +1,489 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_common.c +* +* This is the file which contains common code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +#if 0 +__inline void XFsbl_Printf(u32 DebugType,char *Format, ...) +{ +#ifdef STDOUT_BASEADDRESS + va_list Args; + if (((DebugType) & XFsblDbgCurrentTypes) != 0) + { + va_start(Args, Format); + xil_printf(Format, Args); + va_end(Args); + } +#endif +} +#endif +/************************** Function Prototypes ******************************/ +static char * XFsbl_Itoa(u32 Val, u32 Base); +static void XFsbl_UndefHandler (void); +#ifndef XFSBL_A53 +static void XFsbl_SvcHandler (void); +static void XFsbl_PreFetchAbortHandler (void); +#endif +static void XFsbl_DataAbortHandler (void); +static void XFsbl_IrqHandler (void); +static void XFsbl_FiqHandler (void); + +/** + * functions from xfsbl_main.c + */ +extern void XFsbl_ErrorLockDown(u32 ErrorStatus); + +/************************** Variable Definitions *****************************/ +static char ItoaBuf[20]; +static const char *ItoaStringPtr = "0123456789abcdef"; + +/****************************************************************************/ +/** +* This function is used to print the entire array in bytes as specified by the +* debug type +* +* @param DebugType printing of the array will happen as defined by the +* debug type +* +* @param Buf pointer to the buffer to be printed +* +* @param Len length of the bytes to be printed +* +* @param Str pointer to the data that is printed along the +* data +* +* @return None +* +* @note +* +*****************************************************************************/ +void XFsbl_PrintArray (u32 DebugType, const u8 Buf[], u32 Len, const char *Str) +{ + u32 Index=0U; + + if ((DebugType & XFsblDbgCurrentTypes) != 0U) + { + XFsbl_Printf(DebugType, "%s START\r\n", Str); + for (Index=0U;Index> 24; + Value2 |= (Value1 & 0x00FF0000) >> 8; + Value2 |= (Value1 & 0x0000FF00) << 8; + Value2 |= (Value1 & 0x000000FF) << 24; + + return Value2; +} + + + +/*****************************************************************************/ +/** + * + * + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName, u32 MultibootReg) +{ + + XFsbl_MemSet((void *)XFsbl_SdEmmcFileName, '\0', 32); + (void)XFsbl_Strcpy((char *)XFsbl_SdEmmcFileName, "BOOT"); + + (void)XFsbl_Strcat((char *)XFsbl_SdEmmcFileName, + (char*)XFsbl_Itoa(MultibootReg, 10)); + + (void)XFsbl_Strcat((char *)XFsbl_SdEmmcFileName, ".BIN"); + XFsbl_Printf(DEBUG_INFO, + "File name is %s\r\n",XFsbl_SdEmmcFileName); +} + +/****************************************************************************/ +/** +* +* @param +* +* @return +* +* @note +* +* +*****************************************************************************/ +static void XFsbl_UndefHandler (void) +{ + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_UNDEFINED_EXCEPTION\n\r"); + XFsbl_ErrorLockDown(XFSBL_ERROR_UNDEFINED_EXCEPTION); +} + +#ifndef XFSBL_A53 +/****************************************************************************/ +/** +* +* @param +* +* @return +* +* @note +* +* +*****************************************************************************/ +static void XFsbl_SvcHandler (void) +{ + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SVC_EXCEPTION\n\r"); + XFsbl_ErrorLockDown(XFSBL_ERROR_SVC_EXCEPTION); +} + +/****************************************************************************/ +/** +* +* @param +* +* @return +* +* @note +* +*****************************************************************************/ +static void XFsbl_PreFetchAbortHandler (void) +{ + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_PREFETCH_ABORT_EXCEPTION\n\r"); + XFsbl_ErrorLockDown(XFSBL_ERROR_PREFETCH_ABORT_EXCEPTION); +} +#endif + +/****************************************************************************/ +/** +* +* @param +* +* @return +* +* @note +* +* +*****************************************************************************/ +static void XFsbl_DataAbortHandler (void) +{ + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_DATA_ABORT_EXCEPTION\n\r"); + XFsbl_ErrorLockDown(XFSBL_ERROR_DATA_ABORT_EXCEPTION); +} + +/****************************************************************************/ +/** +* +* @param +* +* @return +* +* @note +* +* +*****************************************************************************/ +static void XFsbl_IrqHandler (void) +{ + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_IRQ_EXCEPTION\n\r"); + XFsbl_ErrorLockDown(XFSBL_ERROR_IRQ_EXCEPTION); +} + +/****************************************************************************/ +/** +* +* @param +* +* @return +* +* @note +* +* +*****************************************************************************/ +static void XFsbl_FiqHandler (void) +{ + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_FIQ_EXCEPTION\n\r"); + XFsbl_ErrorLockDown(XFSBL_ERROR_FIQ_EXCEPTION); +} + +/*****************************************************************************/ +/** +* +* This function Registers the Exception Handlers +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XFsbl_RegisterHandlers(void) +{ + Xil_ExceptionInit(); + + /* + * Initialize the vector table. Register the stub Handler for each + * exception. + */ +#ifdef XFSBL_A53 + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_SYNC_INT, + (Xil_ExceptionHandler)XFsbl_UndefHandler,(void *) 0); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XFsbl_IrqHandler,(void *) 0); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_FIQ_INT, + (Xil_ExceptionHandler)XFsbl_FiqHandler,(void *) 0); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_SERROR_ABORT_INT, + (Xil_ExceptionHandler)XFsbl_DataAbortHandler,(void *) 0); +#else + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_UNDEFINED_INT, + (Xil_ExceptionHandler)XFsbl_UndefHandler,(void *) 0); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_SWI_INT, + (Xil_ExceptionHandler)XFsbl_SvcHandler,(void *) 0); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_PREFETCH_ABORT_INT, + (Xil_ExceptionHandler)XFsbl_PreFetchAbortHandler,(void *) 0); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_DATA_ABORT_INT, + (Xil_ExceptionHandler)XFsbl_DataAbortHandler,(void *) 0); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XFsbl_IrqHandler,(void *) 0); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_FIQ_INT, + (Xil_ExceptionHandler)XFsbl_FiqHandler,(void *) 0); +#endif + + Xil_ExceptionEnable(); +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.h new file mode 100644 index 00000000..e4f4ab50 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc.h @@ -0,0 +1,87 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_common.c +* +* This is the file which contains common code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_MISC_H +#define XFSBL_MISC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +void XFsbl_PrintArray (u32 DebugType, const u8 Buf[], u32 Len, const char *Str); +void XFsbl_MemSet(void *SrcPtr, u8 Char, u32 Len); +void *XFsbl_MemCpy(void * DestPtr, const void * SrcPtr, u32 Len); +int XFsbl_MemCmp(const void *Str1Ptr, const void *Str2Ptr, u32 Count); +char *XFsbl_Strcpy(char *DestPtr, const char *SrcPtr); +char * XFsbl_Strcat(char* Str1Ptr, const char* Str2Ptr); +void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName, u32 MultibootReg); +u32 XFsbl_Htonl(u32 Value1); +#ifndef XFSBL_A53 +void XFsbl_RegisterHandlers(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_MISC_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.c new file mode 100644 index 00000000..dad3724b --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.c @@ -0,0 +1,222 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_misc_drivers.c +* +* This is the header file which contains definitions for wrapper functions for +* WDT, CSUDMA drivers +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xfsbl_misc_drivers.h" + +/** + * Include WDT only if WDT is present + */ +#ifdef XFSBL_WDT_PRESENT +#include "xwdtps.h" +#endif +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +#ifdef XFSBL_WDT_PRESENT +static XWdtPs Watchdog; /* Instance of WatchDog Timer */ +#endif +/*****************************************************************************/ + + +/** + * Include WDT code only if WDT is present + */ +#ifdef XFSBL_WDT_PRESENT +/** + * WDT driver wrapper functions + */ + +/*****************************************************************************/ +/** + * This function is used to initialize the system + * + * @param None + * + * @return None + * + *****************************************************************************/ +u32 XFsbl_InitWdt() +{ + u32 Status = XFSBL_SUCCESS; + XWdtPs_Config *ConfigPtr; /* Config structure of the WatchDog Timer */ + u32 CounterValue = 1; + + /** + * Initialize the WDT timer + */ + ConfigPtr = XWdtPs_LookupConfig(XFSBL_WDT_DEVICE_ID); + Status = XWdtPs_CfgInitialize(&Watchdog, + ConfigPtr, + ConfigPtr->BaseAddress); + if (Status != XST_SUCCESS) { + XFsbl_Printf(DEBUG_INFO, "XFSBL_WDT_INIT_FAILED\n\r"); + Status = XFSBL_WDT_INIT_FAILED; + goto END; + } + + /** + * Setting the divider value + */ + XWdtPs_SetControlValue(&Watchdog, + XWDTPS_CLK_PRESCALE, + XWDTPS_CCR_PSCALE_4096); + /** + * Convert time to Watchdog counter reset value + */ + CounterValue = XFsbl_ConvertTime_WdtCounter(XFSBL_WDT_EXPIRE_TIME); + + /** + * Set the Watchdog counter reset value + */ + XWdtPs_SetControlValue(&Watchdog, + XWDTPS_COUNTER_RESET, + CounterValue); + /** + * enable reset output, as we are only using this as a basic counter + */ + XWdtPs_EnableOutput(&Watchdog, XWDTPS_RESET_SIGNAL); + + /** + * Start the Watchdog timer + */ + XWdtPs_Start(&Watchdog); + + XWdtPs_RestartWdt(&Watchdog); + +END: + return Status; +} + + +/****************************************************************************** +* +* This function converts time into Watchdog counter value +* +* @param watchdog expire time in seconds +* +* @return +* Counter value for Watchdog +* +* @note None +* +*******************************************************************************/ +u32 XFsbl_ConvertTime_WdtCounter(u32 seconds) +{ + double time = 0.0; + double CounterValue; + u32 Crv = 0; + u32 Prescaler=0; + u32 PrescalerValue=0; + + Prescaler = XWdtPs_GetControlValue(&Watchdog, XWDTPS_CLK_PRESCALE); + + if (Prescaler == XWDTPS_CCR_PSCALE_0008) { + PrescalerValue = 8; + } if (Prescaler == XWDTPS_CCR_PSCALE_0064) { + PrescalerValue = 64; + } if (Prescaler == XWDTPS_CCR_PSCALE_4096) { + PrescalerValue = 4096; + } + + time = (double)(PrescalerValue) / (double)XPAR_PS8_WDT_0_WDT_CLK_FREQ_HZ; + + CounterValue = seconds / time; + + Crv = (u32)CounterValue; + Crv >>= XFSBL_WDT_CRV_SHIFT; + + return Crv; +} + +/****************************************************************************** +* +* This function is used to restart Watchdog +* +* @param None +* +* @return None +* +* @note None +* +*******************************************************************************/ +void XFsbl_RestartWdt() +{ + XWdtPs_RestartWdt(&Watchdog); +} + +/****************************************************************************** +* +* This function is used to stop Watchdog +* +* @param None +* +* @return None +* +* @note None +* +*******************************************************************************/ +void XFsbl_StopWdt() +{ + XWdtPs_Stop(&Watchdog); +} + +#endif /** end of WDT wrapper code */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.h new file mode 100644 index 00000000..62d9f600 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.h @@ -0,0 +1,117 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_misc_drivers.h +* +* This is the header file which contains declarations for wrapper functions +* for WDT, CSUDMA drivers +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_MISC_DRIVERS_H +#define XFSBL_MISC_DRIVERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" + +/************************** Constant Definitions *****************************/ + +#ifdef XFSBL_WDT_PRESENT +#define XFSBL_WDT_DEVICE_ID (XPAR_XWDTPS_0_DEVICE_ID) +#define XFSBL_WDT_EXPIRE_TIME (100U) +#define XFSBL_WDT_CRV_SHIFT (12U) +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +#ifdef XFSBL_WDT_PRESENT +u32 XFsbl_InitWdt(); +u32 XFsbl_ConvertTime_WdtCounter(u32 seconds); +#endif + +/************************** Variable Definitions *****************************/ + +typedef struct { + u32 DeviceBaseAddress; /**< Flash device base address */ + u32 (*DeviceInit) (); + /**< Function pointer for Device initialization code */ + u32 (*DeviceCopy) (u32 SrcAddress, PTRSIZE DestAddress, u32 Length); + /**< Function pointer for device copy */ + u32 (*DeviceRelease) (); + /**< Function pointer for device release */ +} XFsblPs_DeviceOps; + + +/** + * SD driver functions + */ +#ifdef XFSBL_SD +u32 XFsbl_SdInit(void ); +u32 XFsbl_SdCopy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length); +u32 XFsbl_SdRelease(void ); +#endif + +/** + * NAND driver functions + */ +#ifdef XFSBL_NAND +u32 XFsbl_NandInit(void ); +u32 XFsbl_NandCopy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length); +u32 XFsbl_NandRelease(void ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_MISC_DRIVERS_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_nand.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_nand.c new file mode 100644 index 00000000..0044d8b7 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_nand.c @@ -0,0 +1,159 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_nand.c +* +* This is the file which contains nand related code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   04/21/14 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" + +#ifdef XFSBL_NAND + +#include "xnandps8.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +#define NAND_DEVICE_ID 0 + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ +XNandPs8_Config *Config; +XNandPs8 NandInstance; /* XNand Instance */ +XNandPs8 *NandInstPtr = &NandInstance; + + +/*****************************************************************************/ +/** + * This function is used to initialize the qspi controller and driver + * + * @param None + * + * @return None + * + *****************************************************************************/ +u32 XFsbl_NandInit(void ) +{ + u32 Status = XFSBL_SUCCESS; + + Config = XNandPs8_LookupConfig(NAND_DEVICE_ID); + if (Config == NULL) { + Status = XFSBL_ERROR_NAND_INIT; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_NAND_INIT\r\n"); + goto END; + } + /** + * Initialize the NAND flash driver. + */ + Status = (u32 )XNandPs8_CfgInitialize(NandInstPtr, Config, + Config->BaseAddress); + if (Status != XST_SUCCESS) { + Status = XFSBL_ERROR_NAND_INIT; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_NAND_INIT\r\n"); + goto END; + } + + XFsbl_Printf(DEBUG_INFO,"Nand Init Success\r\n"); +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function is used to copy the data from NAND to destination + * address + * + * @param SrcAddress is the address of the NAND flash where copy should + * start from + * + * @param DestAddress is the address of the destination where it + * should copy to + * + * @param Length Length of the bytes to be copied + * + * @return + * - XFSBL_SUCCESS for successful copy + * - errors as mentioned in xfsbl_error.h + * + *****************************************************************************/ +u32 XFsbl_NandCopy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length) +{ + u32 Status = XFSBL_SUCCESS; + + Status = (u32 )XNandPs8_Read(NandInstPtr, (u64)SrcAddress, (u64)Length, + (u8 *) DestAddress); + if (Status != XST_SUCCESS) { + Status = XFSBL_ERROR_NAND_READ; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_NAND_READ\r\n"); + goto END; + } +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function is used to release the nand settings + * + * @param None + * + * @return None + * + *****************************************************************************/ +u32 XFsbl_NandRelease(void ) +{ + + return XFSBL_SUCCESS; +} + + +#endif /* end of #ifdef XFSBL_NAND */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_partition_load.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_partition_load.c new file mode 100644 index 00000000..a9db45de --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_partition_load.c @@ -0,0 +1,1056 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_partition_load.c +* +* This is the file which contains partition load code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xil_cache.h" +#include "xfsbl_hw.h" +#include "xfsbl_main.h" +#include "xfsbl_image_header.h" +#include "xfsbl_hooks.h" +#include "xfsbl_authentication.h" +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +#define XFSBL_IVT_LENGTH (0x8U) + +/** + * Different Memory types + */ +#define XFSBL_R5_0_TCM (0x1U) +#define XFSBL_R5_1_TCM (0x2U) +#define XFSBL_R5_L_TCM (0x3U) + +/************************** Function Prototypes ******************************/ +static u32 XFsbl_PartitionHeaderValidation(XFsblPs * FsblInstancePtr, + u32 PartitionNum); +static u32 XFsbl_PartitionCopy(XFsblPs * FsblInstancePtr, u32 PartitionNum); +static u32 XFsbl_PartitionValidation(XFsblPs * FsblInstancePtr, + u32 PartitionNum); +static u32 XFsbl_CheckHandoffCpu (XFsblPs * FsblInstancePtr, + u32 DestinationCpu); +static void XFsbl_ConfigureMemory(u32 RunningCpu, u32 DestinationCpu, + u64 Address, u32 Length); +void XFsbl_EccInitialize(u32 Address, u32 Length); +u32 XFsbl_GetLoadAddress(u32 DestinationCpu, u64 * LoadAddressPtr, u32 Length); + +/************************** Variable Definitions *****************************/ +static int IsR50TcmEccInitialized = FALSE; +static int IsR51TcmEccInitialized = FALSE; +static int IsR5LTcmEccInitialized = FALSE; + +u8 TcmVectorArray[32]; +u32 TcmSkipLength=0U; +PTRSIZE TcmSkipAddress=0U; +/*****************************************************************************/ +/** + * This function loads the partition + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @param PartitionNum is the partition number in the image to be loaded + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + * + *****************************************************************************/ +u32 XFsbl_PartitionLoad(XFsblPs * FsblInstancePtr, u32 PartitionNum) +{ + u32 Status=XFSBL_SUCCESS; + + /** + * Load and validate the partition + */ + + /** + * Partition Header Validation + */ + Status = XFsbl_PartitionHeaderValidation(FsblInstancePtr, PartitionNum); + + /** + * FSBL is not partition owner and skip this partition + */ + if (Status == XFSBL_SUCCESS_NOT_PARTITION_OWNER) + { + Status = XFSBL_SUCCESS; + goto END; + } else if (XFSBL_SUCCESS != Status) + { + goto END; + } else { + /** + * for MISRA C compliance + */ + } + + /** + * Partition Copy + */ + Status = XFsbl_PartitionCopy(FsblInstancePtr, PartitionNum); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * Partition Validation + */ + Status = XFsbl_PartitionValidation(FsblInstancePtr, PartitionNum); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function validates the partition header + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @param PartitionNum is the partition number in the image to be loaded + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + *****************************************************************************/ +static u32 XFsbl_PartitionHeaderValidation(XFsblPs * FsblInstancePtr, + u32 PartitionNum) +{ + u32 Status=XFSBL_SUCCESS; + XFsblPs_PartitionHeader * PartitionHeader; + + /** + * Assign the partition header to local variable + */ + PartitionHeader = + &FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum]; + + /** + * Check the check sum of the partition header + */ + Status = XFsbl_ValidateChecksum( (u32 *)PartitionHeader, XIH_PH_LEN/4U); + if (XFSBL_SUCCESS != Status) + { + Status = XFSBL_ERROR_PH_CHECKSUM_FAILED; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_PH_CHECKSUM_FAILED\n\r"); + goto END; + } + + /** + * Check if partition belongs to FSBL + */ + if (XFsbl_GetPartitionOwner(PartitionHeader) != + XIH_PH_ATTRB_PART_OWNER_FSBL) + { + /** + * If the partition doesn't belong to FSBL, skip the partition + */ + XFsbl_Printf(DEBUG_GENERAL,"Skipping the Partition 0x%0lx\n", + PartitionNum); + Status = XFSBL_SUCCESS_NOT_PARTITION_OWNER; + goto END; + } + + /** + * Validate the fields of partition + */ + Status = XFsbl_ValidatePartitionHeader( + PartitionHeader, FsblInstancePtr->ProcessorID); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + +END: + return Status; +} + +/****************************************************************************/ +/** + * This function is used to check whether cpu has handoff address stored + * in the handoff structure + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @param DestinationCpu is the cpu which needs to be checked + * + * @return + * - XFSBL_SUCCESS if cpu handoff address is not present + * - XFSBL_FAILURE if cpu handoff address is present + * + * @note + * + *****************************************************************************/ +static u32 XFsbl_CheckHandoffCpu (XFsblPs * FsblInstancePtr, + u32 DestinationCpu) +{ + u32 ValidHandoffCpuNo=0U; + u32 Status=XFSBL_SUCCESS; + u32 Index=0U; + u32 CpuId=0U; + + + ValidHandoffCpuNo = FsblInstancePtr->HandoffCpuNo; + + for (Index=0U;IndexHandoffValues[Index].CpuSettings & + XIH_PH_ATTRB_DEST_CPU_MASK; + if (CpuId == DestinationCpu) + { + Status = XFSBL_FAILURE; + break; + } + } + + return Status; +} + +/*****************************************************************************/ +/** + * This function checks the power state and reset for the memory type + * and release the reset if required + * + * @param MemoryType is the memory to be checked + * - XFSBL_R5_0_TCM + * - XFSBL_R5_1_TCM + * (to be added) + * - XFSBL_R5_0_TCMA + * - XFSBL_R5_0_TCMB + * - XFSBL_PS_DDR + * - XFSBL_PL_DDR + * + * @return none + *****************************************************************************/ +static void XFsbl_PowerUpMemory(u32 MemoryType) +{ + u32 RegValue; + /** + * Check the power status of the memory + * Power up if required + * + * Release the reset of the memory if present + */ + switch (MemoryType) + { + case XFSBL_R5_0_TCM: + { + /** + * To access TCM, + * Release reset to R5 and enable the clk + * R5 is under halt state + * + * If R5 are out of reset and clk is enabled so doing + * again is no issue. R5 might be under running state + */ + + /** + * Place R5, TCM in split mode + */ + RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); + RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK; + RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK); + RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK); + XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue); + + /** + * Place R5-0 in HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_0_CFG); + RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK); + XFsbl_Out32(RPU_RPU_0_CFG, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL); + RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK; + XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue); + + /** + * Provide some delay, + * so that clock propogates properly. + */ + (void)usleep(0x50U); + + /** + * Release reset to R5-0 + */ + RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK); + XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue); + } break; + + case XFSBL_R5_1_TCM: + { + + /** + * Place R5 in split mode + */ + RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); + RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK; + RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK); + RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK); + XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue); + + /** + * Place R5-1 in HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_1_CFG); + RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK); + XFsbl_Out32(RPU_RPU_1_CFG, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL); + RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK; + XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue); + + /** + * Provide some delay, + * so that clock propogates properly. + */ + (void )usleep(0x50U); + + /** + * Release reset to R5-1 + */ + RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK); + XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue); + } break; + + case XFSBL_R5_L_TCM: + { + /** + * Place R5 in lock step mode + * Combine TCM's + */ + RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); + RegValue |= RPU_RPU_GLBL_CNTL_SLCLAMP_MASK; + RegValue &= ~(RPU_RPU_GLBL_CNTL_SLSPLIT_MASK); + RegValue |= RPU_RPU_GLBL_CNTL_TCM_COMB_MASK; + XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue); + + /** + * Place R5-0 in HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_0_CFG); + RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK); + XFsbl_Out32(RPU_RPU_0_CFG, RegValue); + + /** + * Place R5-1 in HALT state + */ + RegValue = XFsbl_In32(RPU_RPU_1_CFG); + RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK); + XFsbl_Out32(RPU_RPU_1_CFG, RegValue); + + /** + * Enable the clock + */ + RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL); + RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK; + XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue); + + /** + * Provide some delay, + * so that clock propogates properly. + */ + (void )usleep(0x50U); + + /** + * Release reset to R5-0,R5-1 + */ + RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK); + RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK); + XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue); + } break; + + default: + /* nothing to do */ + break; + } + + return ; +} + +void XFsbl_EccInitialize(u32 Address, u32 Length) +{ + u32 Index=0U; + + while (Index XFSBL_R5_TCM_END_ADDRESS) + { + Status = XFSBL_ERROR_LOAD_ADDRESS; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_LOAD_ADDRESS\r\n"); + goto END; + } + + /** + * Update Address to the higher TCM address + */ + Address = XFSBL_R50_HIGH_TCM_START_ADDRESS + Address; + + } else + /** + * Update for R5-1 TCM address + */ + if ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_1) && + (Address <= XFSBL_R5_TCM_END_ADDRESS)) + { + /** + * Check if fits to TCM or not + */ + if ((Address + Length) > XFSBL_R5_TCM_END_ADDRESS) + { + Status = XFSBL_ERROR_LOAD_ADDRESS; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_LOAD_ADDRESS\r\n"); + goto END; + } + /** + * Update Address to the higher TCM address + */ + Address = XFSBL_R51_HIGH_TCM_START_ADDRESS + Address; + } else + /** + * Update for the R5-L TCM address + */ + if ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_L) && + (Address <= XFSBL_R5L_TCM_END_ADDRESS)) + { + /** + * Check if fits to TCM or not + */ + if ((Address + Length) > XFSBL_R5L_TCM_END_ADDRESS) + { + Status = XFSBL_ERROR_LOAD_ADDRESS; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_LOAD_ADDRESS\r\n"); + goto END; + } + /** + * Update Address to the higher TCM address + */ + Address = XFSBL_R50_HIGH_TCM_START_ADDRESS + Address; + } else + { + /** + * For MISRA complaince + */ + } + + /** + * Update the LoadAddress + */ + *LoadAddressPtr = Address; + +END: + return Status; +} + + + +/*****************************************************************************/ +/** + * This function calculates the load address based on the destination + * cpu. For R5 cpu's TCM address is remapped to the higher TCM address + * so that any cpu can globally access it + * + * @param DestinationCpu is the cpu which partition will run + * + * @param LoadAddress will be updated according to the cpu and address + * + * @param Length of the data to be copied. This is required only to + * check for the error case + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + *****************************************************************************/ +static void XFsbl_ConfigureMemory(u32 RunningCpu, u32 DestinationCpu, + u64 Address, u32 Length) +{ + + /** + * Configure R50 TCM Memory + */ + if ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_0) && + (Address >= XFSBL_R50_HIGH_TCM_START_ADDRESS) && + (Address < (XFSBL_R50_HIGH_TCM_START_ADDRESS + + XFSBL_R5_TCM_LENGTH))) + { + + /** + * Power up and release reset to the memory + */ + if (RunningCpu != DestinationCpu) + { + XFsbl_PowerUpMemory(XFSBL_R5_0_TCM); + } + + /** + * ECC initialize TCM + */ + if (IsR50TcmEccInitialized == FALSE) + { + XFsbl_EccInitialize(XFSBL_R50_HIGH_TCM_START_ADDRESS, + XFSBL_R5_TCM_LENGTH); + } + IsR50TcmEccInitialized = TRUE; + + } else + /** + * Update for R5-1 TCM address + */ + if ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_1) && + (Address >= XFSBL_R51_HIGH_TCM_START_ADDRESS) && + (Address < (XFSBL_R51_HIGH_TCM_START_ADDRESS + + XFSBL_R5_TCM_LENGTH))) + { + /** + * Power up and release reset to the memory + */ + if (RunningCpu != DestinationCpu) + { + XFsbl_PowerUpMemory(XFSBL_R5_1_TCM); + } + + /** + * ECC initialize TCM + */ + if (IsR51TcmEccInitialized == FALSE) + { + XFsbl_EccInitialize(XFSBL_R51_HIGH_TCM_START_ADDRESS, + XFSBL_R5_TCM_LENGTH); + } + IsR51TcmEccInitialized = TRUE; + } else + /** + * Update for the R5-L TCM address + */ + if ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_L) && + (Address >= XFSBL_R50_HIGH_TCM_START_ADDRESS) && + (Address < (XFSBL_R50_HIGH_TCM_START_ADDRESS + + (XFSBL_R5_TCM_LENGTH*2U)))) + { + /** + * Power up and release reset to the memory + */ + if (RunningCpu != DestinationCpu) + { + XFsbl_PowerUpMemory(XFSBL_R5_L_TCM); + } + + /** + * ECC initialize TCM + */ + if (IsR5LTcmEccInitialized == FALSE) + { + XFsbl_EccInitialize(XFSBL_R50_HIGH_TCM_START_ADDRESS, + XFSBL_R5_TCM_LENGTH*2U); + } + IsR5LTcmEccInitialized = TRUE; + } else + { + /** + * For MISRA complaince + */ + } + + return; +} + + +/*****************************************************************************/ +/** + * This function copies the partition to specified destination + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @param PartitionNum is the partition number in the image to be loaded + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + *****************************************************************************/ +static u32 XFsbl_PartitionCopy(XFsblPs * FsblInstancePtr, u32 PartitionNum) +{ + u32 Status=XFSBL_SUCCESS; + u32 DestinationCpu=0U; + u32 CpuNo=0U; + u32 DestinationDevice=0U; + u32 ExecState=0U; + XFsblPs_PartitionHeader * PartitionHeader; + u32 SrcAddress=0U; + u64 LoadAddress=0U; + u32 Length=0U; + u32 RunningCpu=0U; + + /** + * Assign the partition header to local variable + */ + PartitionHeader = + &FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum]; + + RunningCpu = FsblInstancePtr->ProcessorID; + + /** + * Check for XIP image + * No need to copy for XIP image + */ + DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader); + + /** + * Get the execution state + */ + ExecState = XFsbl_GetA53ExecState(PartitionHeader); + + /** + * if destination cpu is not present, it means it is for same cpu + */ + if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE) + { + DestinationCpu = FsblInstancePtr->ProcessorID; + } + + if (PartitionHeader->UnEncryptedDataWordLength == 0U) + { + /** + * Update the Handoff address only for the first application + * of that cpu + * This is for XIP image. For other partitions it handoff + * address is updated after partition validation + */ + CpuNo = FsblInstancePtr->HandoffCpuNo; + if (XFsbl_CheckHandoffCpu(FsblInstancePtr, + DestinationCpu) == XFSBL_SUCCESS) + { + FsblInstancePtr->HandoffValues[CpuNo].CpuSettings = + DestinationCpu | ExecState; + FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress = + PartitionHeader->DestinationExecutionAddress; + FsblInstancePtr->HandoffCpuNo += 1U; + } else { + /** + * + * if two partitions has same destination cpu, error can + * be triggered here + */ + } + Status = XFSBL_SUCCESS; + goto END; + } + + /** + * Copy the PL to temporary DDR Address + * Copy the PS to Load Address + * Copy the PMU firmware to PMU RAM + * (It may be good if we copy to DDR instead of PMU RAM + * And finish the PMU RAM copy at handoff so that PMU is + * not in waiting state - Need to check the exact working of PMU) + */ + DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader); + LoadAddress = PartitionHeader->DestinationLoadAddress; + + if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL) + { + /** + * + * Need to check when bitstream support is added + */ + if (LoadAddress == 0U) + { + LoadAddress = XFSBL_DDR_TEMP_ADDRESS; + } + } + + /** + * Get the source(flash offset) address where it needs to copy + */ + SrcAddress = FsblInstancePtr->ImageOffsetAddress + + ((PartitionHeader->DataWordOffset) * + XIH_PARTITION_WORD_LENGTH); + + /** + * Length of the partition to be copied + */ + Length = (PartitionHeader->TotalDataWordLength) * + XIH_PARTITION_WORD_LENGTH; + + + /** + * When destination device is R5-0/R5-1/R5-L and load address is in TCM + * copy to high address of TCM address map + * Update the LoadAddress + */ + Status = XFsbl_GetLoadAddress(DestinationCpu, &LoadAddress, Length); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * Configure the memory + */ + XFsbl_ConfigureMemory(RunningCpu, DestinationCpu, + LoadAddress, Length); + + /** + * + * Do not copy the IVT if FSBL is running in R5-0/R5-L at 0x0 TCM + * Update the SrcAddress, LoadAddress and Len based on the + * above condition + */ +#if 1 + if (((FsblInstancePtr->ProcessorID == + XIH_PH_ATTRB_DEST_CPU_R5_0) || + (FsblInstancePtr->ProcessorID == + XIH_PH_ATTRB_DEST_CPU_R5_L)) && + ((LoadAddress > XFSBL_R50_HIGH_TCM_START_ADDRESS) && + (LoadAddress < + XFSBL_R50_HIGH_TCM_START_ADDRESS + XFSBL_IVT_LENGTH))) + { + + /** + * Get the length of the IVT area to be + * skipped from Load Address + */ + TcmSkipAddress = LoadAddress/XFSBL_IVT_LENGTH; + TcmSkipLength = XFSBL_IVT_LENGTH - TcmSkipAddress; + + /** + * Check if Length is less than SkipLength + */ + if (TcmSkipLength > Length) + { + TcmSkipLength = Length; + } + + /** + * Copy the Skip length to a local array + */ + Status = FsblInstancePtr->DeviceOps.DeviceCopy(SrcAddress, + (PTRSIZE )TcmVectorArray, TcmSkipLength); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + SrcAddress += TcmSkipLength; + LoadAddress += TcmSkipLength; + Length -= TcmSkipLength; + } +#endif + + /** + * Copy the partition to PS_DDR/PL_DDR/TCM + */ + Status = FsblInstancePtr->DeviceOps.DeviceCopy(SrcAddress, + LoadAddress, Length); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function validates the partition + * + * @param FsblInstancePtr is pointer to the XFsbl Instance + * + * @param PartitionNum is the partition number in the image to be loaded + * + * @return returns the error codes described in xfsbl_error.h on any error + * returns XFSBL_SUCCESS on success + * + *****************************************************************************/ +static u32 XFsbl_PartitionValidation(XFsblPs * FsblInstancePtr, + u32 PartitionNum) +{ + u32 Status=XFSBL_SUCCESS; + u32 ChecksumType=0U; + s32 IsEncryptionEnabled=FALSE; + s32 IsAuthenticationEnabled=FALSE; + u32 DestinationDevice=0U; + u32 DestinationCpu=0U; + u32 ExecState=0U; + u32 CpuNo=0U; +#ifdef XFSBL_RSA + u32 Length=0U; + u32 HashLen=0U; + u64 LoadAddress=0U; +#endif + XFsblPs_PartitionHeader * PartitionHeader; + + /** + * Update the variables + */ + PartitionHeader = + &FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum]; + ChecksumType = XFsbl_GetChecksumType(PartitionHeader); + + /** + * Check the encryption status + */ + if (XFsbl_IsEncrypted(PartitionHeader) == + XIH_PH_ATTRB_ENCRYPTION ) + { + IsEncryptionEnabled = TRUE; + } + + /** + * check the authentication status + */ + if (XFsbl_IsRsaSignaturePresent(PartitionHeader) == + XIH_PH_ATTRB_RSA_SIGNATURE ) + { + IsAuthenticationEnabled = TRUE; + } + DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader); + DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader); + + + /** + * Get the execution state + */ + ExecState = XFsbl_GetA53ExecState(PartitionHeader); + + /** + * if destination cpu is not present, it means it is for same cpu + */ + if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE) + { + DestinationCpu = FsblInstancePtr->ProcessorID; + } + + + /** + * Checksum Validation + */ + if (ChecksumType == XIH_PH_ATTRB_CHECKSUM_MD5) + { + /** + * Do the checksum validation + */ + } + + /** + * Authentication Check + */ + if (IsAuthenticationEnabled == TRUE) + { + XFsbl_Printf(DEBUG_INFO,"Authentication Enabled\r\n"); +#ifdef XFSBL_RSA + /** + * Get the Sha type to be used from + * boot header attributes + */ + if ((FsblInstancePtr->BootHdrAttributes & + XIH_BH_IMAGE_ATTRB_SHA2_MASK) == + XIH_BH_IMAGE_ATTRB_SHA2_MASK) + { + HashLen = XFSBL_HASH_TYPE_SHA2; + } else { + HashLen = XFSBL_HASH_TYPE_SHA3; + } + + LoadAddress = PartitionHeader->DestinationLoadAddress; + Length = PartitionHeader->TotalDataWordLength * 4U; + Status = XFsbl_GetLoadAddress(DestinationCpu, + &LoadAddress, Length); + if (XFSBL_SUCCESS != Status) + { + goto END; + } + + /** + * cache disbale can be removed + */ + Xil_DCacheFlush(); + Xil_DCacheDisable(); + + /** + * Do the authentication validation + */ + Status = XFsbl_Authentication( LoadAddress, Length, + (LoadAddress + Length) - XFSBL_AUTH_CERT_MIN_SIZE, + HashLen); + + /* cache enable can be removed */ + Xil_DCacheEnable(); + + if (Status != XFSBL_SUCCESS) + { + goto END; + } +#else + XFsbl_Printf(DEBUG_GENERAL,"Rsa code not Enabled\r\n"); + Status = XFSBL_ERROR_RSA_NOT_ENABLED; + goto END; +#endif + } + + /** + * Decrypt image for PS and PMU through CSU DMA + */ + if ( ((DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PS) || + (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PMU)) && + (IsEncryptionEnabled == TRUE)) + { + /** + * configure SSS + */ + + /** + * Use CSU DMA and decrypt the image + */ + } + + /** + * for PL image use CSU DMA to route to PL + */ + if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL) + { + /** + * Fsbl hook before bit stream download + */ + Status = XFsbl_HookBeforeBSDownload(); + if (Status != XFSBL_SUCCESS) + { + Status = XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD\r\n"); + goto END; + } + + /** + * Configure SSS + */ + + /** + * Use CSU DMA to load Bit stream to PL + * Decrypt the PL if it is encrypted + */ + + /** + * Fsbl hook after bit stream download + */ + Status = XFsbl_HookAfterBSDownload(); + if (Status != XFSBL_SUCCESS) + { + Status = XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD\r\n"); + goto END; + } + } + + /** + * Update the handoff details + */ + CpuNo = FsblInstancePtr->HandoffCpuNo; + if (XFsbl_CheckHandoffCpu(FsblInstancePtr, + DestinationCpu) == XFSBL_SUCCESS) + { + FsblInstancePtr->HandoffValues[CpuNo].CpuSettings = + DestinationCpu | ExecState; + FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress = + PartitionHeader->DestinationExecutionAddress; + FsblInstancePtr->HandoffCpuNo += 1U; + } + +END: + return Status; +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c new file mode 100644 index 00000000..a6eb0036 --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c @@ -0,0 +1,640 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_qspi.c +* +* This is the file which contains qspi related code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" +#include "xparameters.h" + +#ifdef XFSBL_QSPI +#include "xqspips.h" +#include "xfsbl_qspi.h" + +/************************** Constant Definitions *****************************/ +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +void XFsbl_PrintArray (u32 DebugType, const u8 *Buf, u32 Len, const char *Str); + +/************************** Variable Definitions *****************************/ +static XQspiPs QspiInstance; +static XQspiPs *QspiInstancePtr; +static u32 QspiFlashSize=0; +static u32 QspiFlashMake=0; +static u32 ReadCommand=0; + +/* + * The following variables are used to read and write to the eeprom and they + * are global to avoid having large buffers on the stack + */ +static u8 ReadBuffer[DATA_SIZE + DATA_OFFSET + DUMMY_SIZE]; +static u8 WriteBuffer[DATA_OFFSET + DUMMY_SIZE]; + +/****************************************************************************** +* +* This function reads serial FLASH ID connected to the SPI interface. +* It then deduces the make and size of the flash and obtains the +* connection mode to point to corresponding parameters in the flash +* configuration table. The flash driver will function based on this and +* it presently supports Micron and Spansion - 128, 256 and 512Mbit and +* Winbond 128Mbit +* +* @param none +* +* @return XST_SUCCESS if read id, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static u32 FlashReadID(void) +{ + u32 Status = XFSBL_SUCCESS; + + /* + * Read ID in Auto mode. + */ + WriteBuffer[COMMAND_OFFSET] = READ_ID_CMD; + WriteBuffer[ADDRESS_1_OFFSET] = 0x00; /* 3 dummy bytes */ + WriteBuffer[ADDRESS_2_OFFSET] = 0x00; + WriteBuffer[ADDRESS_3_OFFSET] = 0x00; + + Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, ReadBuffer, + RD_ID_SIZE); + if (Status != XST_SUCCESS) { + Status = XFSBL_ERROR_QSPI_READ_ID; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ_ID\r\n"); + goto END; + } + + XFsbl_Printf(DEBUG_INFO,"Single Flash Information\r\n"); + + XFsbl_Printf(DEBUG_INFO,"FlashID=0x%x 0x%x 0x%x\r\n", ReadBuffer[1], + ReadBuffer[2], + ReadBuffer[3]); + + /* + * Deduce flash make + */ + if (ReadBuffer[1] == MICRON_ID) { + QspiFlashMake = MICRON_ID; + XFsbl_Printf(DEBUG_INFO, "MICRON "); + } else if(ReadBuffer[1] == SPANSION_ID) { + QspiFlashMake = SPANSION_ID; + XFsbl_Printf(DEBUG_INFO, "SPANSION "); + } else if(ReadBuffer[1] == WINBOND_ID) { + QspiFlashMake = WINBOND_ID; + XFsbl_Printf(DEBUG_INFO, "WINBOND "); + } else { + Status = XFSBL_ERROR_UNSUPPORTED_QSPI; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_UNSUPPORTED_QSPI\r\n"); + goto END; + } + + /* + * Deduce flash Size + */ + if (ReadBuffer[3] == FLASH_SIZE_ID_128M) { + QspiFlashSize = FLASH_SIZE_128M; + XFsbl_Printf(DEBUG_INFO, "128M Bits\r\n"); + } else if (ReadBuffer[3] == FLASH_SIZE_ID_256M) { + QspiFlashSize = FLASH_SIZE_256M; + XFsbl_Printf(DEBUG_INFO, "256M Bits\r\n"); + } else if (ReadBuffer[3] == FLASH_SIZE_ID_512M) { + QspiFlashSize = FLASH_SIZE_512M; + XFsbl_Printf(DEBUG_INFO, "512M Bits\r\n"); + } else if (ReadBuffer[3] == FLASH_SIZE_ID_1G) { + QspiFlashSize = FLASH_SIZE_1G; + XFsbl_Printf(DEBUG_INFO, "1G Bits\r\n"); + }else { + Status = XFSBL_ERROR_UNSUPPORTED_QSPI; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_UNSUPPORTED_QSPI\r\n"); + goto END; + } + +END: + return Status; +} + + +/*****************************************************************************/ +/** + * This function is used to initialize the qspi controller and driver + * + * @param None + * + * @return None + * + *****************************************************************************/ +u32 XFsbl_Qspi24Init() +{ + XQspiPs_Config *QspiConfig; + u32 Status = XFSBL_SUCCESS; + + QspiInstancePtr = &QspiInstance; + + /** + * Initialize the qspi driver + */ + + /** + * Initialize the QSPI driver so that it's ready to use + */ + QspiConfig = XQspiPs_LookupConfig(QSPI_DEVICE_ID); + if (NULL == QspiConfig) { + Status = XFSBL_ERROR_QSPI_INIT; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_INIT\r\n"); + goto END; + } + + Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig, + QspiConfig->BaseAddress); + if (Status != XST_SUCCESS) { + Status = XFSBL_ERROR_QSPI_INIT; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_INIT\r\n"); + goto END; + } + + /** + * Set the pre-scaler for QSPI clock + */ + Status = XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8); + if (Status != XST_SUCCESS) { + Status = XFSBL_ERROR_QSPI_INIT; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_INIT\r\n"); + goto END; + } + + /** + * Set Auto Start and Manual Chip select options and drive the + * HOLD_B high. + */ + Status = XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | + XQSPIPS_HOLD_B_DRIVE_OPTION); + if (Status != XST_SUCCESS) { + Status = XFSBL_ERROR_QSPI_INIT; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_INIT\r\n"); + goto END; + } + + /** + * + * configure the qspi in linear mode if running in XIP + * Configure the the qspi in IO mode + */ + + switch (XPAR_PS8_QSPI_0_QSPI_MODE) { + + case XQSPIPS_CONNECTION_MODE_SINGLE: + { + XFsbl_Printf(DEBUG_INFO,"QSPI is in single flash connection\r\n"); + /** + * Single flash IO read + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + SINGLE_QSPI_IO_CONFIG_QUAD_READ); + } break; + + case XQSPIPS_CONNECTION_MODE_PARALLEL: + { + XFsbl_Printf(DEBUG_INFO,"QSPI is in Dual Parallel connection\r\n"); + + /** + * Dual parallel flash IO read + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + DUAL_QSPI_PARALLEL_IO_CONFIG_QUAD_READ); + } break; + + case XQSPIPS_CONNECTION_MODE_STACKED: + { + XFsbl_Printf(DEBUG_INFO,"QSPI is in Dual Stack connection\r\n"); + + /** + * Dual Stack flash IO read + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + DUAL_QSPI_STACK_IO_CONFIG_READ); + }break; + + default: + { + Status = XFSBL_ERROR_INVALID_QSPI_CONNECTION; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_INVALID_QSPI_CONNECTION\r\n"); + goto END; + }break; + + } + + + /** + * add code for 1x, 2x and 4x + * + */ + ReadCommand = QUAD_READ_CMD; + + /** + * Assert the FLASH chip select. + */ + Status = XQspiPs_SetSlaveSelect(QspiInstancePtr); + if (Status != XST_SUCCESS) { + Status = XFSBL_ERROR_QSPI_INIT; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_INIT\r\n"); + goto END; + } + + /** + * Read Flash ID and extract Manufacture and Size information + */ + Status = FlashReadID(); + if (Status != XFSBL_SUCCESS) { + goto END; + } + + /** + * add code: For a Stacked connection, read second Flash ID + */ + if ((XPAR_PS8_QSPI_0_QSPI_MODE == XQSPIPS_CONNECTION_MODE_PARALLEL) || + (XPAR_PS8_QSPI_0_QSPI_MODE == XQSPIPS_CONNECTION_MODE_STACKED) ) { + QspiFlashSize = 2 * QspiFlashSize; + } + +END: + return Status; +} + + + +/****************************************************************************** +* +* This functions translates the address based on the type of interconnection. +* In case of stacked, this function asserts the corresponding slave select. +* +* @param Address which is to be accessed +* +* @return QspiAddr is the actual flash address to be accessed - for single +* it is unchanged; for stacked, the lower flash size is subtracted; +* for parallel the address is divided by 2. +* +* @note None. +* +* +******************************************************************************/ +static u32 XFsbl_GetQspiAddr(u32 Address ) +{ + u32 LqspiCr=0; + u32 QspiAddr=0; + + switch(XPAR_PS8_QSPI_0_QSPI_MODE) { + + case XQSPIPS_CONNECTION_MODE_SINGLE: + QspiAddr = Address; + break; + + case XQSPIPS_CONNECTION_MODE_STACKED: + /** + * Get the current LQSPI Config reg value + */ + LqspiCr = XQspiPs_GetLqspiConfigReg(QspiInstancePtr); + + /* Select lower or upper Flash based on sector address */ + if(Address > QspiFlashSize) { + /** + * Set selection to U_PAGE + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK); + + /** + * Subtract first flash size when accessing second flash + */ + QspiAddr = Address - QspiFlashSize; + + }else{ + + /** + * Set selection to L_PAGE + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK)); + + QspiAddr = Address; + } + + /** + * Assert the Flash chip select. + */ + XQspiPs_SetSlaveSelect(QspiInstancePtr); + break; + + case XQSPIPS_CONNECTION_MODE_PARALLEL: + /** + * The effective address in each flash is the actual + * address / 2 + */ + QspiAddr = Address / 2; + break; + default: + /* RealAddr wont be assigned in this case; */ + break; + + } + + return(QspiAddr); +} + + +/****************************************************************************** +* +* This functions selects the current bank +* +* @param QspiPtr is a pointer to the QSPI driver component to use. +* @param Pointer to the write buffer which contains data to be transmitted +* @param BankSel is the bank to be selected in the flash device(s). +* +* @return XST_SUCCESS if bank selected, otherwise XST_FAILURE. +* +* @note None. +* +* +******************************************************************************/ +static int SendBankSelect(u32 BankSel) +{ + u32 Status = XFSBL_SUCCESS; + u8 WriteEnableCmd = { WRITE_ENABLE_CMD }; + + /** + * Bank select commands for Micron and Spansion are different + */ + if(QspiFlashMake == MICRON_ID) { + /** + * For Micron command WREN should be sent first + * except for some specific feature set + */ + Status = XQspiPs_PolledTransfer(QspiInstancePtr, &WriteEnableCmd, NULL, + sizeof(WriteEnableCmd)); + if (Status != XST_SUCCESS) { + Status = XFSBL_FAILURE; + goto END; + } + + + WriteBuffer[COMMAND_OFFSET] = EXTADD_REG_WR; + WriteBuffer[ADDRESS_1_OFFSET] = BankSel; + + /** + * Send the Extended address register write command + * written, no receive buffer required + */ + Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, NULL, + BANK_SEL_SIZE); + if (Status != XST_SUCCESS) { + Status = XFSBL_FAILURE; + goto END; + } + } + if(QspiFlashMake == SPANSION_ID) { + WriteBuffer[COMMAND_OFFSET] = BANK_REG_WR; + WriteBuffer[ADDRESS_1_OFFSET] = BankSel; + + /** + * Send the Extended address register write command + * written, no receive buffer required + */ + Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, NULL, + BANK_SEL_SIZE); + if (Status != XST_SUCCESS) { + Status = XFSBL_FAILURE; + goto END; + } + } + + /* Winbond can be added here */ +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function is used to copy the data from QSPI flash to destination + * address + * + * @param SrcAddress is the address of the QSPI flash where copy should + * start from + * + * @param DestAddress is the address of the destination where it + * should copy to + * + * @param Length Length of the bytes to be copied + * + * @return + * - XFSBL_SUCCESS for successful copy + * - errors as mentioned in xfsbl_error.h + * + *****************************************************************************/ +u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length) +{ + u32 Status = XFSBL_SUCCESS; + u32 QspiAddr=0; + u32 BankSel=0; + u32 RemainingBytes=0; + u32 OverHeadBytes=0; + u32 TransferBytes=0; + + XFsbl_Printf(DEBUG_INFO,"QSPI Reading Src 0x%0lx, Dest %0lx, Length %0lx\r\n", + SrcAddress, DestAddress, Length); + + /** + * Check the read length with Qspi flash size + */ + if ((SrcAddress + Length) > QspiFlashSize) + { + Status = XFSBL_ERROR_QSPI_LENGTH; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_LENGTH\r\n"); + goto END; + } + + + /** + * Update no of bytes to be copied + */ + RemainingBytes = Length; + + while(RemainingBytes != 0) { + + /** + * Copy bytes in terms of 4K blocks from flash + */ + if (RemainingBytes > DATA_SIZE) + { + TransferBytes = DATA_SIZE; + } else { + TransferBytes = RemainingBytes; + } + + /** + * Translate address based on type of connection + * If stacked assert the slave select based on address + */ + QspiAddr = XFsbl_GetQspiAddr((u32 )SrcAddress); + + /** + * Select bank + * check logic for DualQspi + */ + if(QspiFlashSize > BANKSIZE) { + BankSel = QspiAddr/BANKSIZE; + Status = SendBankSelect(BankSel); + if (Status != XFSBL_SUCCESS) { + Status = XFSBL_ERROR_QSPI_READ; + XFsbl_Printf(DEBUG_GENERAL, + "XFSBL_ERROR_QSPI_READ\r\n"); + goto END; + } + } + + /** + * If data to be read spans beyond the current bank, then + * calculate Transfer Bytes in current bank. Else + * transfer bytes are same + * check logic for DualQspi + */ + if((QspiAddr & BANKMASK) != ((QspiAddr+TransferBytes) & BANKMASK)) { + TransferBytes = (QspiAddr & BANKMASK) + BANKSIZE - QspiAddr; + } + + + /** + * Setup the read command with the specified address and data for the + * Flash + */ + WriteBuffer[COMMAND_OFFSET] = ReadCommand; + WriteBuffer[ADDRESS_1_OFFSET] = (u8)((QspiAddr & 0xFF0000) >> 16); + WriteBuffer[ADDRESS_2_OFFSET] = (u8)((QspiAddr & 0xFF00) >> 8); + WriteBuffer[ADDRESS_3_OFFSET] = (u8)(QspiAddr & 0xFF); + + if ((ReadCommand == FAST_READ_CMD) || (ReadCommand == DUAL_READ_CMD) || + (ReadCommand == QUAD_READ_CMD)) + { + OverHeadBytes = OVERHEAD_SIZE + DUMMY_SIZE; + } else { + OverHeadBytes = OVERHEAD_SIZE; + } + + /** + * Send the read command to the Flash to read the specified number + * of bytes from the Flash, send the read command and address and + * receive the specified number of bytes of data in the data buffer + */ + Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, + ReadBuffer,TransferBytes + OverHeadBytes); + if (Status != XST_SUCCESS) { + Status = XFSBL_ERROR_QSPI_READ; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n"); + goto END; + } + + /** + * remove if not required + */ + XFsbl_PrintArray(DEBUG_DETAILED, ReadBuffer, + TransferBytes + OverHeadBytes, "QSPI READ DATA"); + + /** + * Moving the data from local buffer to DDR destination address + */ + XFsbl_MemCpy((u8 *)DestAddress, &ReadBuffer[OverHeadBytes], + TransferBytes); + + XFsbl_Printf(DEBUG_INFO,"."); + XFsbl_Printf(DEBUG_DETAILED, + "QSPI Read Src 0x%0lx, Dest %0lx, Length %0lx\r\n", + QspiAddr, DestAddress, TransferBytes); + + /** + * Update the variables + */ + RemainingBytes -= TransferBytes; + DestAddress += TransferBytes; + SrcAddress += TransferBytes; + + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function is used to release the Qspi settings + * + * @param None + * + * @return None + * + *****************************************************************************/ +u32 XFsbl_Qspi24Release() +{ + u32 Status = XFSBL_SUCCESS; + + return Status; +} + + +#endif /* endof XFSBL_QSPI */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h new file mode 100644 index 00000000..61948c8f --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h @@ -0,0 +1,193 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_qspi.h +* +* This is the header file which contains qspi declarations for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   10/21/13 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XFSBL_QSPI_H +#define XFSBL_QSPI_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xfsbl_hw.h" + +#ifdef XFSBL_QSPI + +/************************** Constant Definitions *****************************/ + +/* + * The following constants define the commands which may be sent to the FLASH + * device. + */ +#define FAST_READ_CMD (0x0BU) +#define DUAL_READ_CMD (0x3BU) +#define QUAD_READ_CMD (0x6BU) +#define READ_ID_CMD (0x9FU) + +#define WRITE_ENABLE_CMD (0x06U) +#define BANK_REG_RD (0x16U) +#define BANK_REG_WR (0x17U) +/* Bank register is called Extended Address Reg in Micron */ +#define EXTADD_REG_RD (0xC8U) +#define EXTADD_REG_WR (0xC5U) + +#define COMMAND_OFFSET (0U) /* FLASH instruction */ +#define ADDRESS_1_OFFSET (1U) /* MSB byte of address to read or write */ +#define ADDRESS_2_OFFSET (2U) /* Middle byte of address to read or write */ +#define ADDRESS_3_OFFSET (3U) /* LSB byte of address to read or write */ +#define DATA_OFFSET (4U) /* Start of Data for Read/Write */ +#define DUMMY_OFFSET (4U) /* Dummy byte offset for fast, dual and quad + reads */ +#define DUMMY_SIZE (1U) /* Number of dummy bytes for fast, dual and + quad reads */ +#define RD_ID_SIZE (4U) /* Read ID command + 3 bytes ID response */ +#define BANK_SEL_SIZE (2U) /* BRWR or EARWR command + 1 byte bank value */ +#define WRITE_ENABLE_CMD_SIZE (1U) /* WE command */ +/* + * The following constants specify the extra bytes which are sent to the + * FLASH on the QSPI interface, that are not data, but control information + * which includes the command and address + */ +#define OVERHEAD_SIZE (4U) + +/* + * The following constants specify the max amount of data and the size of the + * the buffer required to hold the data and overhead to transfer the data to + * and from the FLASH. + */ +#define DATA_SIZE (4096U) + +/* + * The following defines are for dual flash interface. + */ +#define LQSPI_CR_FAST_QUAD_READ (0x0000006BU) /* Fast Quad Read output */ +#define LQSPI_CR_1_DUMMY_BYTE (0x00000100U) /* 1 Dummy Byte between + address and return data */ + +#define SINGLE_QSPI_IO_CONFIG_QUAD_READ (LQSPI_CR_1_DUMMY_BYTE | \ + LQSPI_CR_FAST_QUAD_READ) + +#define DUAL_QSPI_PARALLEL_IO_CONFIG_QUAD_READ \ + (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \ + XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \ + LQSPI_CR_1_DUMMY_BYTE | \ + LQSPI_CR_FAST_QUAD_READ) + + +#define DUAL_QSPI_STACK_IO_CONFIG_READ (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \ + LQSPI_CR_1_DUMMY_BYTE | \ + LQSPI_CR_FAST_QUAD_READ) + +/** + * Flash connection type as defined in PCW + */ +#define FLASH_SIZE_16MB (0x1000000U) +#define BANKSIZE (FLASH_SIZE_16MB) + +/* + * Bank mask + */ +#define BANKMASK (0xF000000U) + +/* + * Identification of Flash + * Micron: + * Byte 0 is Manufacturer ID; + * Byte 1 is first byte of Device ID - 0xBB or 0xBA + * Byte 2 is second byte of Device ID describes flash size: + * 128Mbit : 0x18; 256Mbit : 0x19; 512Mbit : 0x20 + * Spansion: + * Byte 0 is Manufacturer ID; + * Byte 1 is Device ID - Memory Interface type - 0x20 or 0x02 + * Byte 2 is second byte of Device ID describes flash size: + * 128Mbit : 0x18; 256Mbit : 0x19; 512Mbit : 0x20 + */ + +#define MICRON_ID (0x20U) +#define SPANSION_ID (0x01U) +#define WINBOND_ID (0xEFU) + +#define FLASH_SIZE_ID_128M (0x18U) +#define FLASH_SIZE_ID_256M (0x19U) +#define FLASH_SIZE_ID_512M (0x20U) +#define FLASH_SIZE_ID_1G (0x21U) + +/* + * Size in bytes + */ +#define FLASH_SIZE_128M (0x1000000U) +#define FLASH_SIZE_256M (0x2000000U) +#define FLASH_SIZE_512M (0x4000000U) +#define FLASH_SIZE_1G (0x8000000U) + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +u32 XFsbl_Qspi24Init(void ); +u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length); +u32 XFsbl_Qspi24Release(void ); + +/************************** Variable Definitions *****************************/ + + +#endif /* end of XFSBL_QSPI */ + +#ifdef __cplusplus +} +#endif + +#endif /* XFSBL_QSPI_H */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_rsa_sha.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_rsa_sha.c new file mode 100644 index 00000000..73d6e45e --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_rsa_sha.c @@ -0,0 +1,497 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +*******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xfsbl_rsa_sha.c + * + * This contains code for the RSA and SHA functionality. + * If the Hash type is SHA3 then CSU h/w will be used + * else we will use SoftSHA256 s/w library for SHA2-256. + * For RSA-4096 we will always use CSU h/w. + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date        Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00  kc   07/22/14  Initial release
+ *
+ * 
+ * + * @note + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xfsbl_authentication.h" +#include "xfsbl_csu_dma.h" +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +static u32 XFsbl_Sha3Len; +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_Sha3Padd(u8 *Dst, u32 MsgLen) +{ + /** + * SHA3 HASH value is not generated correctly + * when used 2nd time on REMUS 1.9 + */ + XFsbl_MemSet(Dst, 0, MsgLen); + Dst[0] = 0x1; + Dst[MsgLen -1] |= 0x80; +} +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_Sha3Start(void) +{ + + XFsbl_Sha3Len = 0; + + /** + * Reset SHA3 engine. + */ + XFsbl_Out32(CSU_SHA_RESET, CSU_SHA_RESET_RESET_MASK); + XFsbl_Out32(CSU_SHA_RESET, 0); + + /** + * Configure the SSS for SHA3 hashing. + */ + XFsbl_SssSetup(XFsbl_SssInputSha3(XFSBL_CSU_SSS_SRC_SRC_DMA)); + + /** + * Start SHA3 engine. + */ + XFsbl_Out32(CSU_SHA_START, CSU_SHA_START_START_MSG_MASK); +} + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_Sha3Update(u8 * Data, u32 Size) +{ + + XFsbl_Sha3Len += Size; + + XASSERT_VOID((Size & 3) == 0); + + XFsbl_CsuDmaStart(XFSBL_CSU_DMA_SRC, (u32 )(PTRSIZE)Data, Size); + + /* Checking the SHA3 done bit should be enough. */ + XFsbl_CsuDmaWaitForDone(XFSBL_CSU_DMA_SRC); + +} + + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_Sha3WaitForDone(void) +{ + volatile u32 Status; + + do + { + Status = XFsbl_In32(CSU_SHA_DONE); + } while (CSU_SHA_DONE_SHA_DONE_MASK != + (Status & CSU_SHA_DONE_SHA_DONE_MASK)); +} + + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_Sha3Finish(u8 *Hash) +{ + u32 *HashPtr = (u32 *)Hash; + u32 PartialLen = XFsbl_Sha3Len % XFSBL_SHA3_BLOCK_LEN; + + /** + * DT 780552 (SHA3 HASH value is not generated correctly + * when used 2nd time on REMUS 1.9) + */ + PartialLen = (PartialLen == 0)?(XFSBL_SHA3_BLOCK_LEN) : + (XFSBL_SHA3_BLOCK_LEN - PartialLen); + + XFsbl_Sha3Padd(XFsbl_RsaSha3Array, PartialLen); + + XFsbl_CsuDmaStart(XFSBL_CSU_DMA_SRC, (u32 )(PTRSIZE)XFsbl_RsaSha3Array, + PartialLen | XFSBL_CSU_DMA_SIZE_EOP); + + /* Check the SHA3 DONE bit. */ + XFsbl_Sha3WaitForDone(); + + + /* If requested, read out the Hash in reverse order. */ + if (Hash) + { + u32 Index = 0; + u32 Val = 0; + for (Index=0; Index < 12; Index++) + { + Val = XFsbl_In32(CSU_SHA_DIGEST_0 + (Index * 4)); + HashPtr[11 - Index] = Val; + } + } + +} + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_Sha3Digest(const u8 *In, const u32 Size, u8 *Out) +{ + + XFsbl_Sha3Start(); + XFsbl_Sha3Update((u8 *)In, Size); + XFsbl_Sha3Finish(Out); + +} +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +static void XFsbl_RsaPutData(u32 * WrData, u8 RamOffset) +{ + u32 Index = 0; + u32 DataOffset = 0; + u32 TmpIndex = 0; + u32 Data = 0; + + + /** Each of this loop will write 192 bits of data*/ + for (DataOffset = 0; DataOffset < 22; DataOffset++) + { + for (Index = 0; Index < 6; Index++) + { + TmpIndex = (DataOffset*6) + Index; + /** + * DT 776670: CSU Boot ROM fails with error code 0x30E + * (RSA status register give done with error 0x5) + * Added this condition as we need only 4 bytes + * and rest of the data needs to be 0 + */ + if(XFSBL_CSU_RSA_RAM_EXPO == RamOffset) + { + if(0 == TmpIndex ) + { + Data = XFsbl_Htonl(*WrData); + } + else + { + Data = 0x0; + } + } + else + { + if(TmpIndex >=128) + { + Data = 0x0; + } + else + { + /** + * The RSA data in Image is in Big Endian. + * So reverse it before putting in RSA memory, + * becasue RSA h/w expects it in Little endian. + */ + + Data = XFsbl_Htonl(WrData[127-TmpIndex]); + } + } + XFsbl_Out32((RSA_WR_DATA_0 + Index * 4), Data); + } + XFsbl_Out32(RSA_WR_ADDR, ((RamOffset * 22) + DataOffset)); + } +} + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +static void XFsbl_RsaGetData(u32 * RdData) +{ + u32 Index = 0; + u32 DataOffset = 0; + int TmpIndex = 0; + + + /** Each of this loop will write 192 bits of data*/ + for (DataOffset = 0; DataOffset < 22; DataOffset++) + { + XFsbl_Out32(RSA_RD_ADDR, + (XFSBL_CSU_RSA_RAM_RES_Y * 22) + DataOffset); + + Index = (DataOffset == 0) ? 2: 0; + for (; Index < 6; Index++) + { + TmpIndex = 129 - ((DataOffset*6) + Index); + if(TmpIndex < 0) + { + break; + } + /** + * The Signature digest is compared in Big endian. + * So becasue RSA h/w results in Little endian, + * reverse it after reading it from RSA memory, + */ + RdData[TmpIndex] = XFsbl_Htonl( + XFsbl_In32(RSA_RD_DATA_0 + + (Index * 4))); + } + } + +} + +/***************************************************************************** + * + * @param u32 *Mod + * + * @return None + * + * @notes MINV is the 32-bit value of "-M mod 2**32" + * where M is LSB 32 bits of the original modulus + * DT 776670: CSU Boot ROM fails with error code 0x30E + * (RSA status register give done with error 0x5) + * + ******************************************************************************/ + +static void XFsbl_Mod32Inverse(u32 *Mod) +{ + /** Calculate the MINV*/ + u8 Count = 0; + u32 ModVal = XFsbl_Htonl(Mod[127]); + u32 Inv = 2 - ModVal; + + for (Count = 0; Count < 4; ++Count) + { + Inv = (Inv * (2- ( ModVal * Inv ) ) ); + } + + Inv = -Inv; + + /** Put the value in MINV registers*/ + XFsbl_Out32(RSA_CORE_MINV0, (Inv & 0xFF )); + XFsbl_Out32(RSA_CORE_MINV1, ((Inv >> 8) & 0xFF )); + XFsbl_Out32(RSA_CORE_MINV2, ((Inv >> 16) & 0xFF )); + XFsbl_Out32(RSA_CORE_MINV3, ((Inv >> 24) & 0xFF )); +} + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +u32 XFsbl_RsaDecrypt(u8* EncText, u8* Mod, u8* ModExt, u8* ModExpo, u8* Result, u8 Reuse) +{ + volatile u32 Status = XFSBL_SUCCESS; + u32 ErrorCode = XFSBL_SUCCESS; + + /** + * Populate the RSA parameters in h/w. + */ + + /** + * We will reuse the RSA config values, + * incase of FSBL Signature Authentication, + * because Boot header Signautre Authentication, + * also uses the same SPK Key. + */ + if(0 == Reuse) + { + /** + * DT 776670: CSU Boot ROM fails with error code 0x30E + * (RSA status register give done with error 0x5) + * Initialize Modular exponentiation + */ + XFsbl_RsaPutData((u32 *)ModExpo, XFSBL_CSU_RSA_RAM_EXPO); + + + /** + * Initialize Modular. + */ + XFsbl_RsaPutData((u32 *)Mod, XFSBL_CSU_RSA_RAM_MOD); + + + /** + * DT 776670: CSU Boot ROM fails with error code 0x30E + * (RSA status register give done with error 0x5) + * Initialize MINV values from Mod. + */ + XFsbl_Mod32Inverse((u32 *)Mod); + } + + /** + * Initialize Modular extension (R*R Mod M) + */ + XFsbl_RsaPutData((u32 *)ModExt, XFSBL_CSU_RSA_RAM_RES_Y); + + /** + * Initialize Digest + */ + XFsbl_RsaPutData((u32 *)EncText, XFSBL_CSU_RSA_RAM_DIGEST); + + + /** + * Start the RSA operation. + */ + XFsbl_Out32(RSA_CORE_CTRL, XFSBL_CSU_RSA_CONTROL_MASK); + + /** + * Check and wait for status + */ + do + { + Status = XFsbl_In32(RSA_CORE_STATUS); + if(RSA_CORE_STATUS_ERROR_MASK == + (Status & RSA_CORE_STATUS_ERROR_MASK)) + { + ErrorCode = XFSBL_FAILURE; + goto END; + } + }while (RSA_CORE_STATUS_DONE_MASK != + (Status & RSA_CORE_STATUS_DONE_MASK)); + + + /** + * Copy the result + */ + XFsbl_RsaGetData((u32 *)Result); + +END: + return ErrorCode; +} + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_ShaDigest(const u8 *In, const u32 Size, u8 *Out, u32 HashLen) +{ + + if(XFSBL_HASH_TYPE_SHA3 == HashLen) + { + XFsbl_Sha3Digest(In, Size, Out); + } +} + + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_ShaStart( void * Ctx, u32 HashLen) +{ + if(XFSBL_HASH_TYPE_SHA3 == HashLen) + { + XFsbl_Sha3Start(); + } +} + + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_ShaUpdate( void * Ctx, u8 * Data, u32 Size, u32 HashLen) +{ + if(XFSBL_HASH_TYPE_SHA3 == HashLen) + { + XFsbl_Sha3Update(Data, Size); + } +} + +/***************************************************************************** + * + * @param None + * + * @return None + * + ******************************************************************************/ +void XFsbl_ShaFinish( void * Ctx, u8 * Hash, u32 HashLen) +{ + + if(XFSBL_HASH_TYPE_SHA3 == HashLen) + { + XFsbl_Sha3Finish(Hash); + } +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_sd.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_sd.c new file mode 100644 index 00000000..fbaf228e --- /dev/null +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_sd.c @@ -0,0 +1,189 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xfsbl_sd.c +* +* This is the file which contains sd related code for the FSBL. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  kc   04/21/14 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ +/***************************** Include Files *********************************/ +#include "xfsbl_hw.h" + +#ifdef XFSBL_SD + +#include "xparameters.h" +#include "ff.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +extern void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName, u32 MultibootReg); + + +/************************** Variable Definitions *****************************/ + +static FIL fil; /* File object */ +static FATFS fatfs; + +/*****************************************************************************/ +/** + * This function is used to initialize the qspi controller and driver + * + * @param None + * + * @return None + * + *****************************************************************************/ +u32 XFsbl_SdInit(void ) +{ + u32 Status = XFSBL_SUCCESS; + FRESULT rc; + char buffer[32]; + char *boot_file = buffer; + u32 MultiBootOffset=0U; + + /* Register volume work area, initialize device */ + rc = f_mount(0, &fatfs); + XFsbl_Printf(DEBUG_INFO,"SD: rc= %.8x\n\r", rc); + + if (rc != FR_OK) { + Status = XFSBL_ERROR_SD_INIT; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SD_INIT\n\r"); + goto END; + } + + /** + * Read the Multiboot Register + */ + MultiBootOffset = XFsbl_In32(CSU_CSU_MULTI_BOOT); + + /** + * Create boot image name + */ + XFsbl_MakeSdFileName(boot_file, MultiBootOffset); + + rc = f_open(&fil, boot_file, FA_READ); + if (rc) { + XFsbl_Printf(DEBUG_INFO, + "SD: Unable to open file %s: %d\n", boot_file, rc); + Status = XFSBL_ERROR_SD_F_OPEN; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SD_F_OPEN\n\r"); + goto END; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function is used to copy the data from SD/eMMC to destination + * address + * + * @param SrcAddress is the address of the SD flash where copy should + * start from + * + * @param DestAddress is the address of the destination where it + * should copy to + * + * @param Length Length of the bytes to be copied + * + * @return + * - XFSBL_SUCCESS for successful copy + * - errors as mentioned in xfsbl_error.h + * + *****************************************************************************/ +u32 XFsbl_SdCopy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length) +{ + u32 Status = XFSBL_SUCCESS; + + FRESULT rc; /* Result code */ + UINT br=0U; + + rc = f_lseek(&fil, SrcAddress); + if (rc != 0) { + XFsbl_Printf(DEBUG_INFO, + "SD: Unable to seek to %x\n", SrcAddress); + Status = XFSBL_ERROR_SD_F_LSEEK; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SD_F_LSEEK\n\r"); + goto END; + } + + rc = f_read(&fil, (void*)DestAddress, Length, &br); + + if (rc != 0) { + XFsbl_Printf(DEBUG_GENERAL, + "SD: f_read returned %d\r\n", rc); + Status = XFSBL_ERROR_SD_F_READ; + XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SD_F_READ\n\r"); + goto END; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * This function is used to release the sd settings + * + * @param None + * + * @return None + * + *****************************************************************************/ +u32 XFsbl_SdRelease(void ) +{ + (void )f_close(&fil); + + return XFSBL_SUCCESS; +} + +#endif /* end of XFSBL_SD */