summaryrefslogtreecommitdiff
path: root/bootwrapper
diff options
context:
space:
mode:
authorRobin Randhawa <robin.randhawa@arm.com>2011-10-12 16:07:02 +0100
committerRobin Randhawa <robin.randhawa@arm.com>2011-10-12 16:07:02 +0100
commit0656dea51f48c51a57e77187de4d5f66a6ba1337 (patch)
tree5b93e8967b0aa1cadd2724689346c6251cb47669 /bootwrapper
downloadswitcher-0656dea51f48c51a57e77187de4d5f66a6ba1337.tar.gz
Initial commit of the virtualizer v2.0 release.
This will be the basis for the VSM.
Diffstat (limited to 'bootwrapper')
-rwxr-xr-xbootwrapper/Makefile130
l---------bootwrapper/acsr1
l---------bootwrapper/big-little1
-rwxr-xr-xbootwrapper/big-little-mp1.mxscript71
-rwxr-xr-xbootwrapper/big-little-mp4.mxscript89
-rwxr-xr-xbootwrapper/boot.S191
-rwxr-xr-xbootwrapper/boot.map.template56
-rw-r--r--bootwrapper/bootargs.S65
-rw-r--r--bootwrapper/bootwrapper.h62
-rw-r--r--bootwrapper/c_start.c269
-rw-r--r--bootwrapper/emubuild.s44
-rw-r--r--bootwrapper/filesystem.S20
-rwxr-xr-xbootwrapper/helpers.S1312
-rw-r--r--bootwrapper/helpers.h214
-rw-r--r--bootwrapper/kernel.S19
-rwxr-xr-xbootwrapper/makemap166
-rw-r--r--bootwrapper/payload/fsimg0
-rw-r--r--bootwrapper/payload/kernelbin0 -> 65856 bytes
-rw-r--r--bootwrapper/uart.c108
-rw-r--r--bootwrapper/vectors.S66
-rw-r--r--bootwrapper/vgic.h51
21 files changed, 2935 insertions, 0 deletions
diff --git a/bootwrapper/Makefile b/bootwrapper/Makefile
new file mode 100755
index 0000000..c2ec64f
--- /dev/null
+++ b/bootwrapper/Makefile
@@ -0,0 +1,130 @@
+# $Copyright:
+# ----------------------------------------------------------------
+# This confidential and proprietary software may be used only as
+# authorised by a licensing agreement from ARM Limited
+# (C) COPYRIGHT 2008-2011 ARM Limited
+# ALL RIGHTS RESERVED
+# The entire notice above must be reproduced on all authorised
+# copies and copies may only be made to the extent permitted
+# by a licensing agreement from ARM Limited.
+# ----------------------------------------------------------------
+# File: Makefile
+# ----------------------------------------------------------------
+# $
+
+# Decrease the verbosity of the make script
+# can be made verbose by passing V=1 at the make command line
+ifdef V
+ KBUILD_VERBOSE = $(V)
+else
+ KBUILD_VERBOSE = 0
+endif
+
+ifeq "$(KBUILD_VERBOSE)" "0"
+ Q=@
+else
+ Q=
+endif
+
+VE?=TRUE
+T2?=FALSE
+L2_POLICY?=WF
+LOBASE?=0x800
+KERNADDR?=$(LOBASE)08000
+# megabyte at which the vectors are located (almost always zero)
+VECTBASE?=$(LOBASE)
+# Set the megabyte that the BIOS code will execute at
+HIBASE?=0x8FF
+FSADDR?=0x8e400000
+DEBUG=TRUE
+
+ifeq "$(BA)" ""
+BOOTARGS=mem=255M console=ttyAMA0,115200 migration_cost=500 cachepolicy=writealloc
+BA=$(BOOTARGS)
+else
+BOOTARGS=$(BA)
+endif
+
+V7_ASFLAGS=--apcs /inter --cpu=Eagle --keep \
+ --pd "BOOTARGS SETS \"$(BOOTARGS)\"" \
+ --pd "L2_POLICY SETS \"$(L2_POLICY)\"" \
+ --pd "VE SETL {$(VE)}" \
+ --pd "HIBASE SETS \"$(HIBASE)\""
+
+CFLAGS:=--cpu=Eagle -O2 \
+ -DT2=$(T2) \
+ -DSETUPMMU=$(SETUPMMU) \
+ -DHIBASE=$(HIBASE) \
+ -DVE=$(VE) \
+ -DVECTBASE=$(VECTBASE)
+
+ifdef DEBUG
+CFLAGS += -g -O0
+ASFLAGS += -g
+V7_ASFLAGS += -g
+endif
+
+OBJS= boot.o bootargs.o c_start.o helpers.o kernel.o filesystem.o uart.o vectors.o bl_sec.o bl.o
+
+.PHONY: all
+all: img.axf
+
+.PHONY: bl
+bl:
+ make -C big-little bl.axf
+
+.PHONY: bl_sec
+bl_sec:
+ make -C big-little bl_sec.axf
+
+.PHONY: clean
+
+clean:
+ @echo " CLEAN"
+ $(Q)rm -f $(OBJS) img.axf *.map bl.S bl_sec.S
+ make -C big-little clean
+
+# Extra dependencies
+boot.o: emubuild.s
+helpers.o : emubuild.s
+
+%.o: %.S
+ @echo " AS $<"
+ $(Q)armasm $(V7_ASFLAGS) -o $@ $<
+
+%.o: %.c
+ @echo " CC $<"
+ $(Q)armcc $(CFLAGS) -o $@ -c $<
+
+bl.S:
+ make -C big-little bl.axf
+ @echo " MAP"
+ $(Q)./makemap big-little/bl.axf bl
+
+bl.o: bl.S
+ @echo " AS $<"
+ $(Q)armasm $(V7_ASFLAGS) -o $@ $<
+
+bl_sec.S:
+ make -C big-little bl_sec.axf
+ @echo " MAP"
+ $(Q)./makemap big-little/bl_sec.axf bl_sec
+
+bl_sec.o: bl_sec.S
+ @echo " AS $<"
+ $(Q)armasm $(V7_ASFLAGS) -o $@ $<
+
+img.axf: $(OBJS)
+ $(Q)cat boot.map.template > boot.map
+ $(Q)cat bl_sec.map >> boot.map
+ $(Q)cat bl.map >> boot.map
+ $(Q)sed -i \
+ -e "s/KERNADDRBA/$(shell perl -e "printf('0x%08X',$(KERNADDR)-0x7f00)")/g" \
+ -e "s/FSADDR/${FSADDR}/g" \
+ -e "s/HIBASE/${HIBASE}/g" \
+ -e "s/KERNADDR/${KERNADDR}/g" \
+ -e "s/VECTBASE/${VECTBASE}/g" \
+ boot.map
+ @echo " LD $@"
+ $(Q)armlink --entry $(VECTBASE)00000 -o $@ --scatter boot.map $(OBJS)
+
diff --git a/bootwrapper/acsr b/bootwrapper/acsr
new file mode 120000
index 0000000..87fe232
--- /dev/null
+++ b/bootwrapper/acsr
@@ -0,0 +1 @@
+../acsr \ No newline at end of file
diff --git a/bootwrapper/big-little b/bootwrapper/big-little
new file mode 120000
index 0000000..a482b29
--- /dev/null
+++ b/bootwrapper/big-little
@@ -0,0 +1 @@
+../big-little \ No newline at end of file
diff --git a/bootwrapper/big-little-mp1.mxscript b/bootwrapper/big-little-mp1.mxscript
new file mode 100755
index 0000000..99d90c2
--- /dev/null
+++ b/bootwrapper/big-little-mp1.mxscript
@@ -0,0 +1,71 @@
+// Replace the string with the absolute path of the Kingfisher model executable
+// e.g. string model = "/home/working_dir/RTSM_VE_Cortex-A15x1-A7x1";
+string model = "<path to the model>";
+
+// Replace the string with the absolute path of the Virutalizer+Payload software image
+// e.g. string app = "/home/working_dir/bootwrapper/img.axf"
+string app = "<path to the software image>";
+
+int ctr = 0;
+
+// NOTE
+//
+// Uncomment the next 4 'string' variables and update them _only_ if the run is required
+// to generate trace output as described in docs/04-Cache-hit-rate-howto.txt. Also,
+// comment out the system() invocation on line 47 and uncomment the system() command on line 34.
+// Each 'trace' parameter is described below.
+
+// Add the path to the trace plugin
+// string trace_plugin = " --trace-plugin <path to>/GenericTrace.so";
+
+// Parameters for selecting the trace sources to monitor outbound cache hits
+// string trace_sources = " --parameter TRACE.GenericTrace.trace-sources=\*sw_trace_event\*,\*read_for_3_came_from_snoop\*,\*read_for_4_came_from_snoop\* ";
+
+// Add the path to the trace file where all the output will be collected
+// string trace_file = " --parameter TRACE.GenericTrace.trace-file=<path to trace file> ";
+
+// Miscellaneous parameters. The frequency at which the performance metrics of the
+// model appear in the trace source can be changed here (default is 0x100).
+// string trace_misc = " -C TRACE.GenericTrace.perf-period=0x100 -C TRACE.GenericTrace.flush=1 ";
+
+// The commented 'system' command below will launch the model and register the trace
+// sources selected in 'trace_sources' with the Generic Trace plugin selected using
+// 'trace_plugin'. Other parameters are specified in 'trace_file' & 'trace_misc'.
+// system(model + trace_plugin + trace_sources + trace_file + trace_misc + " -C coretile.cache_state_modelled=1" + " -a coretile.cluster0.\*=" + app + " -a coretile.cluster1.\*=" + app + " --verbose -S &");
+
+// NOTE
+//
+// _Only_ if a run is needed using an optional rootfs MMC image built using the instructions in
+// docs/06-Optional-rootfs-build.txt, then comment out the system() invocation
+// below (on line 47) and uncomment the following lines taking care to update
+// the paths accordingly.
+// string mmcimage = "<path to mmc.img>";
+// system(model + " -C motherboard.mmc.p_mmc_file=" + mmcimage + trace_plugin + trace_sources + trace_file + trace_misc + " -C coretile.cache_state_modelled=1" + " -a coretile.cluster0.\*=" + app + " -a coretile.cluster1.\*=" + app + " --verbose -S &");
+
+// Invoke the model. It then listens for connection requests from the model debugger
+// Vanilla invocation of the model.
+system(model + " -C coretile.cache_state_modelled=1" + " -a coretile.cluster0.\*=" + app + " -a coretile.cluster1.\*=" + app + " --verbose -S &");
+
+// Wait for the model to load before connecting to it. There will be times when we
+// try connecting before the model has loded resulting in a "Connection refused"
+// error. Increasing 'ctr' or retrying should solve the problem.
+while(ctr < 400000000)
+{
+ ctr++;
+}
+
+// Model listens at port 7000
+connectToModel("7000");
+
+// The following lines can be uncommented to set any breakpoints on each cluster
+selectTarget("coretile.cluster0.cpu0");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+selectTarget("coretile.cluster1.cpu0");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+
+// Select the primary cpu on the primary cluster and set the ball rolling
+selectTarget("coretile.cluster0.cpu0");
+run();
+
diff --git a/bootwrapper/big-little-mp4.mxscript b/bootwrapper/big-little-mp4.mxscript
new file mode 100755
index 0000000..fb817a9
--- /dev/null
+++ b/bootwrapper/big-little-mp4.mxscript
@@ -0,0 +1,89 @@
+// Replace the string with the absolute path of the Kingfisher model executable
+// e.g. string model = "/home/working_dir/models/RTSM_VE_Cortex-A15x4-A7x4"
+string model = "<path to the model>";
+
+// Replace the string with the absolute path of the Virutalizer+Payload software image
+// e.g. string app = "/home/working_dir/bootwrapper/img.axf"
+string app = "<path to the software image>";
+
+int ctr = 0;
+
+// NOTE
+//
+// Uncomment the next 4 'string' variables and update them _only_ if the run is required
+// to generate trace output as described in docs/04-Cache-hit-rate-howto.txt. Also,
+// comment out the system() invocation on line 47 and uncomment the system() command on line 34.
+// Each 'trace' parameter is described below.
+
+// Add the path to the trace plugin
+// string trace_plugin = " --trace-plugin <path to>/GenericTrace.so";
+
+// Parameters for selecting the trace sources to monitor outbound cache hits
+// string trace_sources = " --parameter TRACE.GenericTrace.trace-sources=\*sw_trace_event\*,\*read_for_3_came_from_snoop\*,\*read_for_4_came_from_snoop\* ";
+
+// Add the path to the trace file where all the output will be collected
+// string trace_file = " --parameter TRACE.GenericTrace.trace-file=<path to trace file> ";
+
+// Miscellaneous parameters. The frequency at which the performance metrics of the
+// model appear in the trace source can be changed here (default is 0x100).
+// string trace_misc = " -C TRACE.GenericTrace.perf-period=0x100 -C TRACE.GenericTrace.flush=1 ";
+
+// The commented 'system' command below will launch the model and register the trace
+// sources selected in 'trace_sources' with the Generic Trace plugin selected using
+// 'trace_plugin'. Other parameters are specified in 'trace_file' & 'trace_misc'.
+// system(model + trace_plugin + trace_sources + trace_file + trace_misc + " -C coretile.cache_state_modelled=1" + " -a coretile.cluster0.\*=" + app + " -a coretile.cluster1.\*=" + app + " --verbose -S &");
+
+// NOTE
+//
+// _Only_ if a run is needed using an optional rootfs MMC image built using the instructions in
+// doc/06-Optional-rootfs-build.txt, then comment out the system() invocation
+// below (on line 47) and uncomment the following lines taking care to update
+// the paths accordingly.
+// string mmcimage = "<path to mmc.img>";
+// system(model + " -C motherboard.mmc.p_mmc_file=" + mmcimage + trace_plugin + trace_sources + trace_file + trace_misc + " -C coretile.cache_state_modelled=1" + " -a coretile.cluster0.\*=" + app + " -a coretile.cluster1.\*=" + app + " --verbose -S &");
+
+// Invoke the model. It then listens for connection requests from the model debugger
+// Vanilla invocation of the model.
+system(model + " -C coretile.cache_state_modelled=1" + " -a coretile.cluster0.\*=" + app + " -a coretile.cluster1.\*=" + app + " --verbose -S &");
+
+// Wait for the model to load before connecting to it. There will be times when we
+// try connecting before the model has loded resulting in a "Connection refused"
+// error. Increasing 'ctr' or retrying should solve the problem.
+while(ctr < 400000000)
+{
+ ctr++;
+}
+
+// Model listens at port 7000
+connectToModel("7000");
+
+// The following lines can be uncommented to set any breakpoints on each cluster
+selectTarget("coretile.cluster0.cpu0");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+selectTarget("coretile.cluster0.cpu1");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+selectTarget("coretile.cluster0.cpu2");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+selectTarget("coretile.cluster0.cpu3");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+selectTarget("coretile.cluster1.cpu0");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+selectTarget("coretile.cluster1.cpu1");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+selectTarget("coretile.cluster1.cpu2");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+selectTarget("coretile.cluster1.cpu3");
+//bpAdd(<address>, "Normal");
+//bpAdd(<address>, "Secure");
+
+// Select the primary cpu on the primary cluster and set the ball rolling
+selectTarget("coretile.cluster0.cpu0");
+run();
+
diff --git a/bootwrapper/boot.S b/bootwrapper/boot.S
new file mode 100755
index 0000000..5842ebe
--- /dev/null
+++ b/bootwrapper/boot.S
@@ -0,0 +1,191 @@
+ ;; $Copyright:
+ ;; ----------------------------------------------------------------
+ ;; This confidential and proprietary software may be used only as
+ ;; authorised by a licensing agreement from ARM Limited
+ ;; (C) COPYRIGHT 2008-2011 ARM Limited
+ ;; ALL RIGHTS RESERVED
+ ;; The entire notice above must be reproduced on all authorised
+ ;; copies and copies may only be made to the extent permitted
+ ;; by a licensing agreement from ARM Limited.
+ ;; ----------------------------------------------------------------
+ ;; File: boot.S
+ ;; ----------------------------------------------------------------
+ ;; $
+
+ AREA |boot|, CODE, ALIGN=2
+ PRESERVE8
+
+ INCLUDE emubuild.s
+
+ IMPORT __use_no_semihosting_swi
+ IMPORT __use_no_heap_region
+ IMPORT output_string
+ IMPORT c_start
+ IMPORT enable_coherency
+ IMPORT stack
+ IMPORT stack_size
+ IMPORT hexword
+ IMPORT read_sctlr
+ IMPORT write_sctlr
+ IMPORT get_sp
+ IMPORT inv_icache_all
+
+ EXPORT start
+ EXPORT dabort
+ EXPORT fiq
+ EXPORT irq
+ EXPORT pabort
+ EXPORT swi
+ EXPORT undef
+ EXPORT unused
+ EXPORT dead
+
+;------------------------------------------------------------------------------
+; Boot code starts here - identify the CPU type, set up stacks and call c_start
+;------------------------------------------------------------------------------
+start
+ bl inv_icache_all
+ ;------------------------------------------------------------------
+ ; Enable ICache, branch predictor and alignment
+ ;------------------------------------------------------------------
+ bl read_sctlr
+ bic r0, r0, #CR_C
+ orr r0, r0, #CR_Z
+ orr r0, r0, #CR_I
+ ;------------------------------------------------------------------
+ ; Set U bit - the C compiler produces non-64-bit-aligned LDRD/STRDs
+ ;------------------------------------------------------------------
+ orr r0, #CR_U
+ bl write_sctlr
+
+ ;------------------------------------------------------------------
+ ; Give yourself a stack to make things easier
+ ;------------------------------------------------------------------
+ ldr r0, =stack
+ ldr r1, =stack_size
+ ldr r1, [r1]
+ bl get_sp
+ mov sp, r0
+
+ ;------------------------------------------------------------------
+ ; Caches are inavlidated at reset & MMU is off. So its safe to
+ ; enable coherency
+ ;------------------------------------------------------------------
+;; bl enable_coherency
+
+ ;------------------------------------------------------------------
+ ; TODO: Enable MMU & coherency here
+ ;------------------------------------------------------------------
+
+ ;------------------------------------------------------------------
+ ; Jump to the C handler
+ ;------------------------------------------------------------------
+ bl c_start
+
+ ;------------------------------------------------------------------
+ ; Should never come here
+ ;------------------------------------------------------------------
+kernel_returned
+ b kernel_returned
+
+; ==============================================================================
+; End of main code
+; ==============================================================================
+
+; ==============================================================================
+; Message strings, etc.
+; ==============================================================================
+
+ LTORG
+ ALIGN
+
+dabort_string
+ DCB " Emubuild-DAB!", 0
+undef_string
+ DCB " Emubuild-UND!", 0
+pabort_string
+ DCB " Emubuild-PAB!", 0
+swi_string
+ DCB " Emubuild-SWI!", 0
+irq_string
+ DCB " Emubuild-IRQ!", 0
+fiq_string
+ DCB " Emubuild-FIQ!", 0
+unused_string
+ DCB " Emubuild-UNU!", 0
+
+ ALIGN
+
+; ==============================================================================
+; Exception handlers - for most exceptions we spin
+; ==============================================================================
+
+dabort
+ mov r12, lr ; save lr, just in case it's interesting
+
+ mov r0, r12
+ bl hexword
+
+ mrc p15,0,r0,c5,c0,0 ; DFSR
+ bl hexword
+
+ mrc p15,0,r0,c6,c0,0 ; DFAR
+ bl hexword
+
+ ldr r0, =dabort_string
+ bl output_string
+ b dead
+
+undef
+ push {r0-r1}
+ ldr r0, [lr,#-4] ; load undeffing instruction
+ ldr r1, =0xf57ff000 ; ignore unimplemented DSB/DMB/ISB/CLRX
+ bic r0, r0, #0x000000ff
+ cmp r0, r1
+ popeq {r0-r1}
+ bxeq lr
+ mov r0, lr ; print lr, just in case it's interesting
+ bl hexword
+ ldr r0, =undef_string
+ bl output_string
+ b dead
+
+pabort
+ mov r0, lr ; print lr, just in case it's interesting
+ bl hexword
+ ldr r0, =pabort_string
+ bl output_string
+ b dead
+
+swi
+ mov r0, lr ; print lr, just in case it's interesting
+ bl hexword
+ ldr r0, =swi_string
+ bl output_string
+ b dead
+
+irq
+ mov r0, lr ; print lr, just in case it's interesting
+ bl hexword
+ ldr r0, =irq_string
+ bl output_string
+ b dead
+
+fiq
+ mov r0, lr ; print lr, just in case it's interesting
+ bl hexword
+ ldr r0, =fiq_string
+ bl output_string
+ b dead
+
+unused
+ mov r0, lr ; print lr, just in case it's interesting
+ bl hexword
+ ldr r0, =unused_string
+ bl output_string
+ b dead
+
+dead
+ B dead
+
+ END
diff --git a/bootwrapper/boot.map.template b/bootwrapper/boot.map.template
new file mode 100755
index 0000000..c5c05b3
--- /dev/null
+++ b/bootwrapper/boot.map.template
@@ -0,0 +1,56 @@
+ ; $Copyright:
+ ; ----------------------------------------------------------------
+ ; This confidential and proprietary software may be used only as
+ ; authorised by a licensing agreement from ARM Limited
+ ; (C) COPYRIGHT 2008-2011 ARM Limited
+ ; ALL RIGHTS RESERVED
+ ; The entire notice above must be reproduced on all authorised
+ ; copies and copies may only be made to the extent permitted
+ ; by a licensing agreement from ARM Limited.
+ ; ----------------------------------------------------------------
+ ; File: boot.map.template
+ ; ----------------------------------------------------------------
+ ; $
+
+VECTORS VECTBASE00000 0x100
+{
+ VECTORSEXEC VECTBASE00000 0x100
+ {
+ vectors.o (+RO,+RW,+ZI)
+ }
+}
+
+BOOTARGS KERNADDRBA 0x4000
+{
+ BOOTARGS KERNADDRBA 0x4000
+ {
+ bootargs.o (+RO,+RW,+ZI)
+ }
+}
+
+KERNEL KERNADDR 0x800000
+{
+ KERNEL KERNADDR 0x800000
+ {
+ kernel.o (kernel)
+ }
+}
+
+FILESYSTEM FSADDR 0x2000000
+{
+ FILESYSTEM FSADDR 0x2000000
+ {
+ filesystem.o (filesystem)
+ }
+}
+
+# BIOS code is placed in the last 128kB of RAM
+# Linux can just be told to use 0-HIBASEMB
+HIGHCODE HIBASEE0000 0x00018000
+{
+ HIGHCODEALL +0
+ {
+ *.o (*)
+ }
+}
+
diff --git a/bootwrapper/bootargs.S b/bootwrapper/bootargs.S
new file mode 100644
index 0000000..4edc17a
--- /dev/null
+++ b/bootwrapper/bootargs.S
@@ -0,0 +1,65 @@
+ ;; $Copyright:
+ ;; ----------------------------------------------------------------
+ ;; This confidential and proprietary software may be used only as
+ ;; authorised by a licensing agreement from ARM Limited
+ ;; (C) COPYRIGHT 2008-2011 ARM Limited
+ ;; ALL RIGHTS RESERVED
+ ;; The entire notice above must be reproduced on all authorised
+ ;; copies and copies may only be made to the extent permitted
+ ;; by a licensing agreement from ARM Limited.
+ ;; ----------------------------------------------------------------
+ ;; File: bootargs.S
+ ;; ----------------------------------------------------------------
+ ;; $
+
+ AREA | bootargs|, CODE, ALIGN=8
+ PRESERVE8
+
+ EXPORT bootargs
+ EXPORT param_biosep
+ IMPORT |filesystem$$Base|
+ IMPORT |filesystem$$Length|
+ INCLUDE emubuild.s
+
+ GBLS args
+ IF L2_POLICY != "NC"
+args SETS BOOTARGS :CC: " l2=alreadyon"
+ ELSE
+args SETS BOOTARGS :CC: " nol2x0"
+ ENDIF
+
+
+; ==============================================================================
+; Linux "Tagged List" is declared here (see linux/Documentation/arm/Booting)
+; ==============================================================================
+ ALIGN 256 ; gets us to 0x100 - where Linux expects
+tags ; to find its boot tags
+; 0x100
+ DCD 0x00000005 ; Size = 5 words
+ DCD 0x54410001 ; ATAG_CORE
+ DCD 0x00000000 ; Flags
+ DCD 0x00000000 ; PageSize
+ DCD 0x00000000 ; RootDev
+; 0x114
+ DCD ( :LEN:args +2+3)/4+7 ; Size in words
+ DCD 0x54410009 ; ATAG_CMDLINE
+
+ ; Basic command line, probably the same as compiled into the kernel
+ DCB " "
+bootargs
+ DCB args
+ DCB " "
+ ; Reserve some space for "biosep=0x<bios_entrypoint>" bootarg
+param_biosep SPACE 20
+ ALIGN 4
+end_cmdline
+initrd2
+ DCD 0x00000004 ; Size = 4 words
+ DCD 0x54420005
+ DCD |filesystem$$Base|
+ DCD |filesystem$$Length|
+ DCD 0x00000000 ; Size = 0 words
+ DCD 0x00000000 ; ATAG_NONE - end of list
+ ALIGN 4
+
+ END
diff --git a/bootwrapper/bootwrapper.h b/bootwrapper/bootwrapper.h
new file mode 100644
index 0000000..7aa6605
--- /dev/null
+++ b/bootwrapper/bootwrapper.h
@@ -0,0 +1,62 @@
+/*
+ * $Copyright:
+ * ----------------------------------------------------------------
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ * ----------------------------------------------------------------
+ * File: bootwrapper.h
+ * ----------------------------------------------------------------
+ * $
+ */
+
+#ifndef __BOOTWRAPPER_H__
+#define __BOOTWRAPPER_H__
+
+/* A stack of 128 words per cpu */
+#define STACK_SIZE 128
+#define NUM_CPUS 4
+#define NUM_CLUSTERS 4
+#define TRUE 1
+#define FALSE 0
+#define PLATFORM_MASK 0x0FFFFFFF
+
+/* Permissions for architected timers/counters */
+#define PL1PCTEN (1 << 0)
+#define PL1PCEN (1 << 1)
+#define PL0PCTEN (1 << 0)
+#define PL0VCTEN (1 << 1)
+#define PL0VTEN (1 << 8)
+#define PL0PTEN (1 << 9)
+#define CP15_TIMER_FREQ 12000000
+
+#define VERSATILE_EXPRESS 2272
+#define UART0_BASE 0X1C090000
+#define VE_SYS_BASE 0X1C010000
+#define CCI_BASE 0x2C090000
+#define SECURE_ACCESS_REG 0x8
+#define FLAGS_SET 0x30
+#define FLAGS_CLR 0x34
+
+#define VE_KFSCB_BASE 0x10020000 /* Kingfisher System Configuration Block */
+#define KFS_ID_OFFSET 0xFFC /* Kingfisher System Platform ID register offset (KFS_ID) */
+#define KFS_ID_ARCH_MASK 0x000F0000 /* Mask for extracting KFS architecture */
+#define KFS_ID_ARCH_SHIFT 16 /* Shift for extracting KFS architecture */
+#define KFS_CFG_R 0x30 /* Kingfisher System static configuration read register */
+#define ACTIVE_CLUSTER_MASK 0x3 /* Returns the value that was driven on the CFG_ACTIVECLUSTER configuration inputs at the last system power-on reset. */
+#define KFS_CFG_R_OFFSET 0x30 /* Kingfisher System Static Configuration Read register */
+#define ACTIVE_CLUSTER_MASK 0x3 /* Returns the value that was driven on the CFG_ACTIVECLUSTER configuration input */
+
+#define CLUSTER_CPU_COUNT(x) (((read32(VE_KFSCB_BASE + KFS_CFG_R) >> 16) >> (x << 2)) & 0xf)
+#define write32(addr, val) (*(volatile unsigned int *)(addr) = (val))
+#define read32(addr) (*(volatile unsigned int *)(addr))
+
+extern void config_uart(void);
+extern void drain_uart_fifo(void);
+extern void start(void);
+
+#endif /* __BOOTWRAPPER_H__ */
diff --git a/bootwrapper/c_start.c b/bootwrapper/c_start.c
new file mode 100644
index 0000000..61b184e
--- /dev/null
+++ b/bootwrapper/c_start.c
@@ -0,0 +1,269 @@
+/*
+ * $Copyright:
+ * ----------------------------------------------------------------
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ * ----------------------------------------------------------------
+ * File: c_start.c
+ * ----------------------------------------------------------------
+ * $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "helpers.h"
+#include "bootwrapper.h"
+#include "vgic.h"
+
+extern void *vector_table, *bl_sec_image;
+extern void bl_image(unsigned, unsigned, unsigned, unsigned);
+extern void kernel_start(int, int, int, int);
+
+/* Reserve some stack space - 512 bytes per CPU -> 2048 bytes total */
+unsigned stack[NUM_CPUS * STACK_SIZE];
+unsigned stack_size = STACK_SIZE * sizeof(unsigned);
+unsigned char cpus_ready[NUM_CLUSTERS][NUM_CPUS];
+unsigned thumb = T2;
+void (*kernel_start_address) (int, int, int, int);
+volatile unsigned model_pen = 0;
+
+unsigned gic_int_num(void)
+{
+ unsigned intcount = 0;
+
+ intcount = read32(GIC_ID_PHY_BASE + GICD_CTR);
+ intcount = ((intcount & 0x1F) + 1) * 32;
+
+ return intcount;
+}
+
+/*
+ * Function to configure the GIC ready for use in Non-Secure State
+ */
+void setup_gic_nonsecure(unsigned cluster_id, unsigned cpu_id)
+{
+ unsigned ctr = 0, num_ints = gic_int_num();
+
+ /* Ensure all GIC interrupts are Non-Secure */
+ write32(GIC_ID_PHY_BASE + GICD_SEC + (ctr << 2), 0xffffffff); /* IRQs 0-31 are Non-Secure */
+ if (cpu_id == 0 && cluster_id == 0) {
+ for (ctr = 1; ctr <= (num_ints >> 5); ctr++)
+ write32(GIC_ID_PHY_BASE + GICD_SEC + (ctr << 2), 0xffffffff); /* Set all SPIs as non-secure */
+ }
+
+ /* Ensure all interrupts can get through the priority mask */
+ write32(GIC_IC_PHY_BASE + GICC_PRIMASK, 0xff);
+}
+
+/*
+ * Function to send wakeup IPI to the secondary CPUs
+ */
+void kick(unsigned cpu_id, int secondary_cpus)
+{
+ int cpu_mask = ((1 << (secondary_cpus + 1)) - 1) & ~(1 << cpu_id);
+
+ write32(VE_SYS_BASE + FLAGS_CLR, 0xffffffff); // clear the flags register
+ write32(VE_SYS_BASE + FLAGS_SET, (unsigned)start); // set the start address in the flags register
+ write32(GIC_ID_PHY_BASE, 0x1); // turn on the GIC distributor
+ write32(GIC_IC_PHY_BASE, 0x1); // turn on the GIC CPU interface
+ write32(GIC_ID_PHY_BASE + GICD_SW, cpu_mask << 16); // send an interrupt to everyone else
+}
+
+/*
+ * This function doesn't retun - it waits for an address to be
+ * written into the FLAGs register, then jumps to that address.
+ */
+void secondary_main(unsigned cluster_id, unsigned cpu_id)
+{
+ unsigned val;
+ void (*secondary_start) (void);
+
+ /* Ensure I cache is on and interrupts are masked */
+ inv_icache_all();
+ write_sctlr(read_sctlr() | (1 << 12));
+ write_cpsr(read_cpsr() | 0x80);
+
+ /* tell CPU0 that we are ready */
+ cpus_ready[cluster_id][cpu_id] = 1;
+
+ /*
+ * We're not the primary core, so we need to wait for the primary
+ * core to tell us what to do. While doing that, go into WFI so we
+ * don't just sit here consuming system resources (i.e. bus
+ * badwidth); make sure a soft IRQ gets through to the core, but
+ * don't actually take the interrupt - that way we'll come out of
+ * WFI without worrying about interrupt vectors (which may have gone
+ * away, since the primary core is playing with our memory).
+ */
+ write32(GIC_IC_PHY_BASE + GICC_CTL, 0x1); /* Enable GIC CPU Interface */
+ write32(GIC_IC_PHY_BASE + GICC_PRIMASK, 0x000000f0); /* Set Priority Mask to allow interrupts */
+
+ /* If the start address isn't already set, go to sleep */
+ while (val = read32(VE_SYS_BASE + FLAGS_SET), val == 0
+ || val == (unsigned)start) {
+ wfi();
+ /* Acknowledge the interrupt that woke us */
+ /* Read the Acknowledge register, write End Of Interrupt */
+ write32(GIC_IC_PHY_BASE + GICC_EOI,
+ read32(GIC_IC_PHY_BASE + GICC_INTACK));
+ }
+
+ /* TODO: If MMU is enabled, then synchronise caches here */
+ secondary_start = (void (*)())val;
+ secondary_start(); /* No return from here */
+}
+
+void wait_for_secondaries(unsigned active_clusters, unsigned secondary_cpus)
+{
+ int i, j, ready;
+
+ printf("Waiting for %d secondary CPUs\n", secondary_cpus);
+
+ while (TRUE) {
+ ready = 0;
+
+ for (i = 0; i < active_clusters; i++)
+ {
+ for (j = 0; j < NUM_CPUS; j++) {
+ if (cpus_ready[i][j]) {
+ ++ready;
+ }
+ }
+ }
+
+ if (ready == secondary_cpus) {
+ break;
+ }
+
+ /* Don't thrash the memory system, give the secondaries some time */
+ for (j = 0; j < 1000; ++j) {
+ __nop();
+ }
+ }
+}
+
+/*
+ * Function to determine number of clusters in the system.
+ * The way to do this will differ on different systems.
+ * Add support for the system you are running on.
+ * At the moment, it supports Kingfisher dual cluster.
+ */
+int get_cluster_count(void)
+{
+ unsigned int kfs_id, active_clusters;
+ int num_clusters = 0;
+
+ kfs_id = read32(VE_KFSCB_BASE + KFS_ID_OFFSET);
+
+ switch (((kfs_id & KFS_ID_ARCH_MASK) >> KFS_ID_ARCH_SHIFT))
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ active_clusters = read32(VE_KFSCB_BASE + KFS_CFG_R_OFFSET) & ACTIVE_CLUSTER_MASK;
+ num_clusters = (active_clusters == 0x3) ? 2 : 1;
+ break;
+ }
+
+ return num_clusters;
+}
+
+void c_start(void)
+{
+ unsigned cpu_id = read_cpuid();
+ unsigned cluster_id = read_clusterid();
+ unsigned secondary_cpus = 0;
+ unsigned platform = VERSATILE_EXPRESS;
+ unsigned active_clusters = get_cluster_count();
+
+ secondary_cpus = CLUSTER_CPU_COUNT(cluster_id) - 1;
+ if (active_clusters > 1) {
+ secondary_cpus += CLUSTER_CPU_COUNT(!cluster_id);
+ }
+
+ write_vbar((unsigned)&vector_table);
+ write_mvbar((unsigned)&bl_sec_image);
+ if (cpu_id == 0 && cluster_id == 0)
+ config_uart();
+
+ enable_user_perfmon_access();
+ enable_perfmon();
+ enable_swp();
+ write_cpacr(read_cpacr() | 0xfffffff);
+ write_nsacr(0x00073fff);
+ enable_coherency();
+
+ /* Also grant NS access to CCI registers */
+ if (cpu_id == 0 && cluster_id == 0)
+ write32(CCI_BASE + SECURE_ACCESS_REG, 0x1);
+
+ /*
+ * Secondaries wait here while initialisation of global peripherals is done
+ */
+ if (model_pen == 0 && (cpu_id || cluster_id)) {
+ do {
+ wfe();
+ } while (model_pen == 0);
+ }
+
+ setup_gic_nonsecure(cluster_id, cpu_id);
+
+ if (cpu_id == 0 && cluster_id == 0) {
+ model_pen = 1;
+ dsb();
+ sev();
+ }
+
+ enter_monitor_mode();
+ write_scr(0x131); /* HVC, NS, FW and AW bits */
+ write_cnthctl(PL1PCTEN | PL1PCEN);
+ write_cntkctl(PL0PCTEN | PL0VCTEN | PL0VTEN | PL0PTEN);
+ write_cntfrq(CP15_TIMER_FREQ);
+
+ /* Start secondary CPUs, if any */
+ if (cpu_id == 0 && cluster_id == 0 && secondary_cpus > 0) {
+ printf("Kicking %d secondary CPU(s)\n", secondary_cpus);
+ drain_uart_fifo();
+ kick(cpu_id, secondary_cpus);
+ }
+
+ enter_nonsecure_world((unsigned)bl_image);
+
+ /* Secondary CPUs go off to secondary_main() */
+ if (cpu_id || cluster_id) {
+ secondary_main(cluster_id, cpu_id); /* no return */
+ }
+
+ /* Primary waits for the secondaries to get ready before loading the payload */
+ wait_for_secondaries(active_clusters, secondary_cpus);
+
+ /* Load the payload kernel */
+ printf("Kernel at 0x%x\n", kernel_start);
+
+ if (thumb)
+ kernel_start_address =
+ (void (*)(int, int, int, int))((unsigned)kernel_start | 1);
+ else
+ kernel_start_address = kernel_start;
+
+ printf("Kernel entry point 0x%x (%s)\n", kernel_start_address,
+ ((unsigned)kernel_start_address & 1) ? "thumb" : "arm");
+
+ drain_uart_fifo();
+
+ /* Clear FLAGS register, as this is what Linux expects to find */
+ write32(VE_SYS_BASE + FLAGS_CLR, 0xffffffff);
+
+ /* TODO: If MMU is enabled then caches need to be cleaned here */
+
+ /* Start the kernel */
+ kernel_start_address(0, platform & PLATFORM_MASK, 0, 0); /* No return from here */
+
+ return;
+}
diff --git a/bootwrapper/emubuild.s b/bootwrapper/emubuild.s
new file mode 100644
index 0000000..abf2103
--- /dev/null
+++ b/bootwrapper/emubuild.s
@@ -0,0 +1,44 @@
+ ;; $Copyright:
+ ;; ----------------------------------------------------------------
+ ;; This confidential and proprietary software may be used only as
+ ;; authorised by a licensing agreement from ARM Limited
+ ;; (C) COPYRIGHT 2008-2011 ARM Limited
+ ;; ALL RIGHTS RESERVED
+ ;; The entire notice above must be reproduced on all authorised
+ ;; copies and copies may only be made to the extent permitted
+ ;; by a licensing agreement from ARM Limited.
+ ;; ----------------------------------------------------------------
+ ;; File: emubuild.s
+ ;; ----------------------------------------------------------------
+ ;; $
+
+;; CPSR Mode bits definitions
+USR_MODE EQU 16
+FIQ_MODE EQU 17
+IRQ_MODE EQU 18
+SVC_MODE EQU 19
+MON_MODE EQU 22
+ABT_MODE EQU 23
+UND_MODE EQU 27
+SYS_MODE EQU 31
+
+;; CPSR mask bit definitions
+CPSR_A EQU (1<<8)
+CPSR_I EQU (1<<7)
+CPSR_F EQU (1<<6)
+
+;; Control Register bits definition
+CR_U EQU (1<<22)
+CR_I EQU (1<<12)
+CR_C EQU (1<<2)
+CR_M EQU (1<<0)
+CR_W EQU (1<<3)
+CR_Z EQU (1<<11)
+CR_XP EQU (1<<23)
+
+PAGE_MASK EQU ~0xfff
+
+CLIENT_ACCESS EQU 0x55555555
+MANAGER_ACCESS EQU 0xffffffff
+
+ END
diff --git a/bootwrapper/filesystem.S b/bootwrapper/filesystem.S
new file mode 100644
index 0000000..80068ea
--- /dev/null
+++ b/bootwrapper/filesystem.S
@@ -0,0 +1,20 @@
+ AREA |filesystem|, CODE, ALIGN=2 ; $Copyright:
+ ;; ----------------------------------------------------------------
+ ;; This confidential and proprietary software may be used only as
+ ;; authorised by a licensing agreement from ARM Limited
+ ;; (C) COPYRIGHT 2008-2011 ARM Limited
+ ;; ALL RIGHTS RESERVED
+ ;; The entire notice above must be reproduced on all authorised
+ ;; copies and copies may only be made to the extent permitted
+ ;; by a licensing agreement from ARM Limited.
+ ;; ----------------------------------------------------------------
+ ;; File: filesystem.S
+ ;; ----------------------------------------------------------------
+ ;; $
+
+ EXPORT fs_start
+ EXPORT fs_end
+fs_start
+ INCBIN payload/fsimg
+fs_end
+ END
diff --git a/bootwrapper/helpers.S b/bootwrapper/helpers.S
new file mode 100755
index 0000000..49e70e2
--- /dev/null
+++ b/bootwrapper/helpers.S
@@ -0,0 +1,1312 @@
+ ;; $Copyright:
+ ;; ----------------------------------------------------------------
+ ;; This confidential and proprietary software may be used only as
+ ;; authorised by a licensing agreement from ARM Limited
+ ;; (C) COPYRIGHT 2008-2011 ARM Limited
+ ;; ALL RIGHTS RESERVED
+ ;; The entire notice above must be reproduced on all authorised
+ ;; copies and copies may only be made to the extent permitted
+ ;; by a licensing agreement from ARM Limited.
+ ;; ----------------------------------------------------------------
+ ;; File: helpers.S
+ ;; ----------------------------------------------------------------
+ ;; $
+
+ EXPORT wfi
+ EXPORT wfe
+ EXPORT sev
+ EXPORT dmb
+ EXPORT dsb
+ EXPORT isb
+ EXPORT smc
+ EXPORT dcisw
+ EXPORT dccsw
+ EXPORT dccisw
+
+ EXPORT read_dacr
+ EXPORT read_ttbr0
+ EXPORT read_cpacr
+ EXPORT read_scr
+ EXPORT read_cpsr
+ EXPORT read_midr
+ EXPORT read_mpidr
+ EXPORT read_cntpct
+ EXPORT read_cntfrq
+ EXPORT read_vmpidr
+ EXPORT read_vmidr
+ EXPORT read_id_pfr0
+ EXPORT read_id_pfr1
+ EXPORT read_id_dfr0
+ EXPORT read_id_afr0
+ EXPORT read_id_mmfr0
+ EXPORT read_id_mmfr1
+ EXPORT read_id_mmfr2
+ EXPORT read_id_mmfr3
+ EXPORT read_id_isar0
+ EXPORT read_id_isar1
+ EXPORT read_id_isar2
+ EXPORT read_id_isar3
+ EXPORT read_id_isar4
+ EXPORT read_id_isar5
+ EXPORT read_cpuid
+ EXPORT read_aidr
+ EXPORT read_ctr
+ EXPORT read_tcmtr
+ EXPORT read_tlbtr
+ EXPORT read_clusterid
+ EXPORT read_sctlr
+ EXPORT read_hsctlr
+ EXPORT read_hdfar
+ EXPORT read_hpfar
+ EXPORT read_vtcr
+ EXPORT read_hcr
+ EXPORT read_hdcr
+ EXPORT read_hcptr
+ EXPORT read_hstr
+ EXPORT read_cnthctl
+ EXPORT read_cntkctl
+ EXPORT read_cntp_ctl
+ EXPORT read_cntp_tval
+ EXPORT read_cnthp_ctl
+ EXPORT read_cnthp_tval
+ EXPORT read_cnthp_cval
+ EXPORT read_ttbcr
+ EXPORT read_clidr
+ EXPORT read_lr
+ EXPORT read_sp
+ EXPORT read_actlr
+ EXPORT read_nsacr
+ EXPORT read_clidr
+ EXPORT read_csselr
+ EXPORT read_ccsidr
+ EXPORT read_nmrr
+ EXPORT read_prrr
+ EXPORT read_mvbar
+ EXPORT read_vbar
+ EXPORT read_hsr
+ EXPORT read_dfar
+ EXPORT read_ifar
+ EXPORT read_dfsr
+ EXPORT read_ifsr
+ EXPORT read_adfsr
+ EXPORT read_aifsr
+
+ EXPORT write_dacr
+ EXPORT write_prrr
+ EXPORT write_nmrr
+ EXPORT write_ttbr0
+ EXPORT write_cpacr
+ EXPORT write_nsacr
+ EXPORT write_cpsr
+ EXPORT write_scr
+ EXPORT write_mvbar
+ EXPORT write_vbar
+ EXPORT write_hvbar
+ EXPORT write_vmpidr
+ EXPORT write_vmidr
+ EXPORT write_csselr
+ EXPORT write_hcr
+ EXPORT write_hdcr
+ EXPORT write_hcptr
+ EXPORT write_hstr
+ EXPORT write_sctlr
+ EXPORT write_actlr
+ EXPORT write_sp
+ EXPORT write_lr
+ EXPORT write_ttbcr
+ EXPORT write_cntfrq
+ EXPORT write_cnthctl
+ EXPORT write_cntkctl
+ EXPORT write_cntp_ctl
+ EXPORT write_cntp_tval
+ EXPORT write_cnthp_ctl
+ EXPORT write_cnthp_tval
+ EXPORT write_cnthp_cval
+ EXPORT write_hsctlr
+ EXPORT write_httbr
+ EXPORT write_vttbr
+ EXPORT write_htcr
+ EXPORT write_vtcr
+ EXPORT write_hmair0
+ EXPORT write_hmair1
+ EXPORT write_dfar
+ EXPORT write_ifar
+ EXPORT write_dfsr
+ EXPORT write_ifsr
+ EXPORT write_adfsr
+ EXPORT write_aifsr
+
+ EXPORT panic
+ EXPORT spin_lock
+ EXPORT spin_trylock
+ EXPORT spin_unlock
+ EXPORT copy_words
+ EXPORT virt_memset
+ EXPORT disable_gic_dist
+ EXPORT enable_gic_dist
+ EXPORT switcher_exit
+ EXPORT hyp_save
+ EXPORT num_secondaries
+ EXPORT virt_dead
+ EXPORT get_sp
+ EXPORT disable_coherency
+ EXPORT enable_coherency
+ EXPORT inv_tlb_all
+ EXPORT inv_icache_all
+ EXPORT inv_bpred_is
+ EXPORT inv_bpred_all
+ EXPORT inv_icache_mva_pou
+ EXPORT inv_dcache_mva_poc
+ EXPORT cln_dcache_mva_pou
+ EXPORT cln_dcache_mva_poc
+ EXPORT enable_user_perfmon_access
+ EXPORT enable_perfmon
+ EXPORT enable_swp
+ EXPORT cache_maint_op
+ EXPORT enter_monitor_mode
+ EXPORT enter_nonsecure_world
+ EXPORT enable_pmu
+
+; Cache maintenance op types
+INV EQU 0x0
+CLN EQU 0x1
+CLN_INV EQU 0x2
+
+ AREA |.text|, CODE
+
+read_cntfrq FUNCTION
+ mrc p15, 0, r0, c14, c0, 0
+ bx lr
+ ENDFUNC
+
+write_cntfrq FUNCTION
+ mcr p15, 0, r0, c14, c0, 0
+ bx lr
+ ENDFUNC
+
+read_cntpct FUNCTION
+ mrrc p15, 0, r2, r3, c14
+ str r2, [r0]
+ str r3, [r1]
+ bx lr
+ ENDFUNC
+
+dcisw FUNCTION
+ mcr p15, 0, r0, c7, c6, 2
+ bx lr
+ ENDFUNC
+
+dccsw FUNCTION
+ mcr p15, 0, r0, c7, c10, 2
+ bx lr
+ ENDFUNC
+
+dccisw FUNCTION
+ mcr p15, 0, r0, c7, c14, 2
+ bx lr
+ ENDFUNC
+
+virt_dead FUNCTION
+ b virt_dead
+ ENDFUNC
+
+disable_gic_dist FUNCTION
+ push {lr}
+ ldr r2, [r1]
+ str r2, [r0]
+ mov r2, #0
+ str r2, [r1]
+ dsb
+ pop {pc}
+ ENDFUNC
+
+enable_gic_dist FUNCTION
+ push {lr}
+ str r0, [r1]
+ dsb
+ pop {pc}
+ ENDFUNC
+
+smc FUNCTION
+ push {r4-r12, lr}
+ smc #0
+ pop {r4-r12, pc}
+ ENDFUNC
+
+dmb FUNCTION
+ dmb
+ bx lr
+ ENDFUNC
+
+wfi FUNCTION
+ wfi
+ bx lr
+ ENDFUNC
+
+wfe FUNCTION
+ wfe
+ bx lr
+ ENDFUNC
+
+sev FUNCTION
+ sev
+ bx lr
+ ENDFUNC
+
+switcher_exit FUNCTION
+ hvc #1
+ bx lr
+ ENDFUNC
+
+hyp_save FUNCTION
+ hvc #2
+ bx lr
+ ENDFUNC
+
+ ; This function takes three arguments
+ ; r0: Destination start address (must be word aligned)
+ ; r1: Source start address (must be word aligned)
+ ; r2: Number of words to copy
+ ; Return value is updated destination pointer (first unwritten word)
+copy_words FUNCTION
+ push {r4, r5}
+0 cmp r2, #3
+ ble %f1
+ ldmia r1!, {r3, r4, r5, r12}
+ stmia r0!, {r3, r4, r5, r12}
+ sub r2, r2, #4
+ b %b0
+
+1 cmp r2, #0
+ beq %f3
+2 ldr r3, [r1], #4
+ str r3, [r0], #4
+ subs r2, r2, #1
+ bne %b2
+
+3 pop {r4, r5}
+ bx lr
+ ENDFUNC
+
+
+virt_memcpy FUNCTION
+ cmp r2, #0
+ bxeq lr
+0 ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ subs r2, #1
+ bne %b0
+ bx lr
+ ENDFUNC
+
+virt_memset FUNCTION
+ cmp r2, #0
+ bxeq lr
+0 strb r1, [r0], #1
+ subs r2, #1
+ bne %b0
+ bx lr
+ ENDFUNC
+
+ AREA APPF_ENTRY_POINT, CODE
+
+ ; Functions we need in the runtime entry point, i.e. before we switch pagetables,
+ ; are placed in this area.
+
+dsb FUNCTION
+ dsb
+ bx lr
+ ENDFUNC
+
+isb FUNCTION
+ isb
+ bx lr
+ ENDFUNC
+
+num_secondaries FUNCTION
+ mrc p15, 1, r0, c9, c0, 2
+ lsr r0, r0, #24
+ and r0, r0, #3
+ bx lr
+ ENDFUNC
+
+read_vmpidr FUNCTION
+ mrc p15, 4, r0, c0, c0, 5
+ bx lr
+ ENDFUNC
+
+read_vmidr FUNCTION
+ mrc p15, 4, r0, c0, c0, 0
+ bx lr
+ ENDFUNC
+
+read_id_pfr0 FUNCTION
+ mrc p15, 0, r0, c0, c1, 0
+ bx lr
+ ENDFUNC
+
+read_id_pfr1 FUNCTION
+ mrc p15, 0, r0, c0, c1, 1
+ bx lr
+ ENDFUNC
+
+read_id_dfr0 FUNCTION
+ mrc p15, 0, r0, c0, c1, 2
+ bx lr
+ ENDFUNC
+
+read_id_afr0 FUNCTION
+ mrc p15, 0, r0, c0, c1, 3
+ bx lr
+ ENDFUNC
+
+read_id_mmfr0 FUNCTION
+ mrc p15, 0, r0, c0, c1, 4
+ bx lr
+ ENDFUNC
+
+read_id_mmfr1 FUNCTION
+ mrc p15, 0, r0, c0, c1, 5
+ bx lr
+ ENDFUNC
+
+read_id_mmfr2 FUNCTION
+ mrc p15, 0, r0, c0, c1, 6
+ bx lr
+ ENDFUNC
+
+read_id_mmfr3 FUNCTION
+ mrc p15, 0, r0, c0, c1, 7
+ bx lr
+ ENDFUNC
+
+read_id_isar0 FUNCTION
+ mrc p15, 0, r0, c0, c2, 0
+ bx lr
+ ENDFUNC
+
+read_id_isar1 FUNCTION
+ mrc p15, 0, r0, c0, c2, 1
+ bx lr
+ ENDFUNC
+
+read_id_isar2 FUNCTION
+ mrc p15, 0, r0, c0, c2, 2
+ bx lr
+ ENDFUNC
+
+read_id_isar3 FUNCTION
+ mrc p15, 0, r0, c0, c2, 3
+ bx lr
+ ENDFUNC
+
+read_id_isar4 FUNCTION
+ mrc p15, 0, r0, c0, c2, 4
+ bx lr
+ ENDFUNC
+
+read_id_isar5 FUNCTION
+ mrc p15, 0, r0, c0, c2, 5
+ bx lr
+ ENDFUNC
+
+read_ctr FUNCTION
+ mrc p15, 0, r0, c0, c0, 1
+ bx lr
+ ENDFUNC
+
+read_tcmtr FUNCTION
+ mrc p15, 0, r0, c0, c0, 2
+ bx lr
+ ENDFUNC
+
+read_tlbtr FUNCTION
+ mrc p15, 0, r0, c0, c0, 3
+ bx lr
+ ENDFUNC
+
+read_aidr FUNCTION
+ mrc p15, 1, r0, c0, c0, 7
+ bx lr
+ ENDFUNC
+
+va_to_pa FUNCTION ; Note: assumes conversion will be successful!
+ mov r1, r0
+ mcr p15, 0, r0, c7, c8, 1 ; Priv Write Current World VA-PA
+ mrc p15, 0, r0, c7, c4, 0 ; Get PA
+ bfc r0, #0, #12 ; We want top bits of translated addr
+ bfc r1, #12, #20 ; plus bottom bits of input addr
+ orr r0, r0, r1
+ bx lr
+ ENDFUNC
+
+read_dacr FUNCTION
+ mrc p15, 0, r0, c3, c0, 0
+ bx lr
+ ENDFUNC
+
+read_ttbr0 FUNCTION
+ mrc p15, 0, r0, c2, c0, 0
+ dsb
+ bx lr
+ ENDFUNC
+
+write_dacr FUNCTION
+ mcr p15, 0, r0, c3, c0, 0
+ isb
+ bx lr
+ ENDFUNC
+
+read_cpacr FUNCTION
+ mrc p15, 0, r0, c1, c0, 2
+ bx lr
+ ENDFUNC
+
+write_cpacr FUNCTION
+ mcr p15, 0, r0, c1, c0, 2
+ bx lr
+ ENDFUNC
+
+read_midr FUNCTION
+ mrc p15, 0, r0, c0, c0, 0;
+ bx lr
+ ENDFUNC
+
+read_mpidr FUNCTION
+ mrc p15, 0, r0, c0, c0, 5
+ bx lr
+ ENDFUNC
+
+read_scr FUNCTION
+ mrc p15, 0, r0, c1, c1, 0
+ bx lr
+ ENDFUNC
+
+write_scr FUNCTION
+ mcr p15, 0, r0, c1, c1, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_nsacr FUNCTION
+ mcr p15, 0, r0, c1, c1, 2
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_cpsr FUNCTION
+ mrs r0, CPSR
+ bx lr
+ ENDFUNC
+
+write_cpsr FUNCTION
+ msr CPSR_c, r0
+ bx lr
+ ENDFUNC
+
+write_mvbar FUNCTION
+ mcr p15, 0, r0, c12, c0, 1
+ bx lr
+ ENDFUNC
+
+write_vbar FUNCTION
+ mcr p15, 0, r0, c12, c0, 0
+ bx lr
+ ENDFUNC
+
+write_hvbar FUNCTION
+ mcr p15, 4, r0, c12, c0, 0
+ bx lr
+ ENDFUNC
+
+read_mvbar FUNCTION
+ mrc p15, 0, r0, c12, c0, 1
+ bx lr
+ ENDFUNC
+
+read_vbar FUNCTION
+ mrc p15, 0, r0, c12, c0, 0
+ bx lr
+ ENDFUNC
+
+read_cpuid FUNCTION
+ mrc p15, 0, r0, c0, c0, 5
+ ands r0, r0, #0xf
+ bx lr
+ ENDFUNC
+
+read_clusterid FUNCTION
+ mrc p15, 0, r0, c0, c0, 5
+ lsr r0, r0, #0x8
+ ands r0, r0, #0xf
+ bx lr
+ ENDFUNC
+
+write_ttbr0 FUNCTION
+ mcr p15, 0, r0, c2, c0, 0
+ mcr p15, 0, r0, c7, c5, 6
+ mcr p15, 0, r0, c8, c7, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_ttbcr FUNCTION
+ mrc p15, 0, r0, c2, c0, 2
+ bx lr
+ ENDFUNC
+
+write_ttbcr FUNCTION
+ mcr p15, 0, r0, c2, c0, 2
+ bx lr
+ ENDFUNC
+
+write_vmpidr FUNCTION
+ mcr p15, 4, r0, c0, c0, 5
+ isb
+ bx lr
+ ENDFUNC
+
+write_vmidr FUNCTION
+ mcr p15, 4, r0, c0, c0, 0
+ isb
+ bx lr
+ ENDFUNC
+
+read_vtcr FUNCTION
+ mrc p15, 4, r0, c2, c1, 2
+ bx lr
+ ENDFUNC
+
+read_hcr FUNCTION
+ mrc p15, 4, r0, c1, c1, 0
+ bx lr
+ ENDFUNC
+
+read_hdcr FUNCTION
+ mrc p15, 4, r0, c1, c1, 1
+ bx lr
+ ENDFUNC
+
+read_hcptr FUNCTION
+ mrc p15, 4, r0, c1, c1, 2
+ bx lr
+ ENDFUNC
+
+read_hstr FUNCTION
+ mrc p15, 4, r0, c1, c1, 3
+ bx lr
+ ENDFUNC
+
+write_hcr FUNCTION
+ mcr p15, 4, r0, c1, c1, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_hdcr FUNCTION
+ mcr p15, 4, r0, c1, c1, 1
+ bx lr
+ ENDFUNC
+
+write_hcptr FUNCTION
+ mcr p15, 4, r0, c1, c1, 2
+ bx lr
+ ENDFUNC
+
+write_hstr FUNCTION
+ mcr p15, 4, r0, c1, c1, 3
+ bx lr
+ ENDFUNC
+
+write_httbr FUNCTION
+ mcrr p15, 4, r0, r1, c2
+ mcr p15, 0, r0, c7, c5, 6
+ mcr p15, 0, r0, c8, c7, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_vttbr FUNCTION
+ mcrr p15, 6, r0, r1, c2
+ mcr p15, 0, r0, c7, c5, 6
+ mcr p15, 0, r0, c8, c7, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_htcr FUNCTION
+ mcr p15, 4, r0, c2, c0, 2
+ bx lr
+ ENDFUNC
+
+write_vtcr FUNCTION
+ mcr p15, 4, r0, c2, c1, 2
+ bx lr
+ ENDFUNC
+
+write_hmair0 FUNCTION
+ mcr p15, 4, r0, c10, c2, 0
+ bx lr
+ ENDFUNC
+
+write_hmair1 FUNCTION
+ mcr p15, 4, r0, c10, c2, 1
+ bx lr
+ ENDFUNC
+
+read_nsacr FUNCTION
+ mrc p15, 0, r0, c1, c1, 2
+ bx lr
+ ENDFUNC
+
+read_sctlr FUNCTION
+ mrc p15, 0, r0, c1, c0, 0
+ bx lr
+ ENDFUNC
+
+write_sctlr FUNCTION
+ mcr p15, 0, r0, c1, c0, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_hsctlr FUNCTION
+ mrc p15, 4, r0, c1, c0, 0
+ bx lr
+ ENDFUNC
+
+read_hdfar FUNCTION
+ mrc p15, 4, r0, c6, c0, 0
+ bx lr
+ ENDFUNC
+
+read_hpfar FUNCTION
+ mrc p15, 4, r0, c6, c0, 4
+ bx lr
+ ENDFUNC
+
+read_hsr FUNCTION
+ mrc p15, 4, r0, c5, c2, 0
+ bx lr
+ ENDFUNC
+
+write_hsctlr FUNCTION
+ mcr p15, 4, r0, c1, c0, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_cnthctl FUNCTION
+ mrc p15, 4, r0, c14, c1, 0
+ bx lr
+ ENDFUNC
+
+read_cntkctl FUNCTION
+ mrc p15, 0, r0, c14, c1, 0
+ bx lr
+ ENDFUNC
+
+read_cnthp_cval FUNCTION
+ mrrc p15, 6, r0, r1, c14
+ bx lr
+ ENDFUNC
+
+read_cnthp_tval FUNCTION
+ mrc p15, 4, r0, c14, c2, 0
+ bx lr
+ ENDFUNC
+
+read_cntp_tval FUNCTION
+ mrc p15, 0, r0, c14, c2, 0
+ bx lr
+ ENDFUNC
+
+read_cntp_ctl FUNCTION
+ mrc p15, 0, r0, c14, c2, 1
+ bx lr
+ ENDFUNC
+
+read_cnthp_ctl FUNCTION
+ mrc p15, 4, r0, c14, c2, 1
+ bx lr
+ ENDFUNC
+
+write_cnthctl FUNCTION
+ mcr p15, 4, r0, c14, c1, 0
+ bx lr
+ ENDFUNC
+
+write_cntkctl FUNCTION
+ mcr p15, 0, r0, c14, c1, 0
+ bx lr
+ ENDFUNC
+
+write_cntp_tval FUNCTION
+ mcr p15, 0, r0, c14, c2, 0
+ isb
+ bx lr
+ ENDFUNC
+
+write_cntp_ctl FUNCTION
+ mcr p15, 0, r0, c14, c2, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_cnthp_cval FUNCTION
+ mcrr p15, 6, r0, r1, c14
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_cnthp_tval FUNCTION
+ mcr p15, 4, r0, c14, c2, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_cnthp_ctl FUNCTION
+ mcr p15, 4, r0, c14, c2, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_clidr FUNCTION
+ mrc p15, 1, r0, c0, c0, 1 ; read clidr
+ bx lr
+ ENDFUNC
+
+read_ccsidr FUNCTION
+ mrc p15, 1, r0, c0, c0, 0 ; read ccsidr
+ bx lr
+ ENDFUNC
+
+read_csselr FUNCTION
+ mrc p15, 2, r0, c0, c0, 0 ; read csselr
+ bx lr
+ ENDFUNC
+
+write_csselr FUNCTION
+ mcr p15, 2, r0, c0, c0, 0 ; read csselr
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_actlr FUNCTION
+ mrc p15, 0, r0, c1, c0, 1
+ bx lr
+ ENDFUNC
+
+write_actlr FUNCTION
+ mcr p15, 0, r0, c1, c0, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_prrr FUNCTION
+ mrc p15, 0, r0, c10, c2, 0
+ bx lr
+ ENDFUNC
+
+read_nmrr FUNCTION
+ mrc p15, 0, r0, c10, c2, 1
+ bx lr
+ ENDFUNC
+
+write_prrr FUNCTION
+ mcr p15, 0, r0, c10, c2, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_nmrr FUNCTION
+ mcr p15, 0, r0, c10, c2, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_dfar FUNCTION
+ mrc p15, 0, r0, c6, c0, 0
+ bx lr
+ ENDFUNC
+
+read_ifar FUNCTION
+ mrc p15, 0, r0, c6, c0, 2
+ bx lr
+ ENDFUNC
+
+read_dfsr FUNCTION
+ mrc p15, 0, r0, c5, c0, 0
+ bx lr
+ ENDFUNC
+
+read_ifsr FUNCTION
+ mrc p15, 0, r0, c5, c0, 1
+ bx lr
+ ENDFUNC
+
+read_adfsr FUNCTION
+ mrc p15, 0, r0, c5, c1, 0
+ bx lr
+ ENDFUNC
+
+read_aifsr FUNCTION
+ mrc p15, 0, r0, c5, c1, 1
+ bx lr
+ ENDFUNC
+
+write_dfar FUNCTION
+ mcr p15, 0, r0, c6, c0, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_ifar FUNCTION
+ mcr p15, 0, r0, c6, c0, 2
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_dfsr FUNCTION
+ mcr p15, 0, r0, c5, c0, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_ifsr FUNCTION
+ mcr p15, 0, r0, c5, c0, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_adfsr FUNCTION
+ mcr p15, 0, r0, c5, c1, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+write_aifsr FUNCTION
+ mcr p15, 0, r0, c5, c1, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+read_lr FUNCTION
+ ; Save r1
+ push {r1}
+ and r0, r0, #0x1f
+ ; Read the current cpsr
+ mrs r1, cpsr
+ and r1, r1, #0x1f
+ ; Check if the desired lr is of the current mode
+ cmp r0, r1
+ moveq r0, LR
+ beq read_lr_out
+ ; Check if desired lr is of user mode
+ cmp r0, #0x10
+ mrseq r0, LR_usr
+ beq read_lr_out
+ ; Check if desired lr is of supervisor mode
+ cmp r0, #0x13
+ mrseq r0, LR_svc
+read_lr_out
+ pop {r1}
+ bx lr
+ ENDFUNC
+
+write_lr FUNCTION
+ ; Save r2
+ push {r2}
+ and r0, r0, #0x1f
+ ; Read the current cpsr
+ mrs r2, cpsr
+ and r2, r2, #0x1f
+ ; Check if the lr is of the current mode
+ cmp r0, r2
+ moveq LR, r1
+ beq write_lr_out
+ ; Check if the lr is of user mode
+ cmp r0, #0x10
+ msreq LR_usr, r1
+ beq write_lr_out
+ ; Check if the lr is of supervisor mode
+ cmp r0, #0x13
+ msreq LR_svc, r1
+write_lr_out
+ pop {r2}
+ bx lr
+ ENDFUNC
+
+read_sp FUNCTION
+ ; Save r1
+ push {r1}
+ and r0, r0, #0x1f
+ ; Read the current cpsr
+ mrs r1, cpsr
+ and r1, r1, #0x1f
+ ; Check if the desired sp is of the current mode
+ cmp r0, r1
+ moveq r0, SP
+ beq read_sp_out
+ ; Check if desired sp is of user mode
+ cmp r0, #0x10
+ mrseq r0, SP_usr
+ beq read_sp_out
+ ; Check if desired sp is of supervisor mode
+ cmp r0, #0x13
+ mrseq r0, SP_svc
+ beq read_sp_out
+ ; Check if desired sp is of irq mode
+ cmp r0, #0x12
+ mrseq r0, SP_irq
+ beq read_sp_out
+ ; Check if desired sp is of supervisor mode
+ cmp r0, #0x1a
+ mrseq r0, SP_hyp
+ beq read_sp_out
+ ; Check if desired sp is of monitor mode
+ cmp r0, #0x16
+ mrseq r0, SP_mon
+read_sp_out
+ pop {r1}
+ bx lr
+ ENDFUNC
+
+write_sp FUNCTION
+ ; Save r2
+ push {r2}
+ and r0, r0, #0x1f
+ ; Read the current cpsr
+ mrs r2, cpsr
+ and r2, r2, #0x1f
+ ; Check if the sp is of the current mode
+ cmp r0, r2
+ moveq SP, r1
+ beq write_sp_out
+ ; Check if the sp is of user mode
+ cmp r0, #0x10
+ msreq SP_usr, r1
+ beq write_sp_out
+ ; Check if the sp is of supervisor mode
+ cmp r0, #0x13
+ msreq SP_svc, r1
+ beq write_sp_out
+ ; Check if the sp is of irq mode
+ cmp r0, #0x12
+ msreq SP_irq, r1
+ beq write_sp_out
+ ; Check if the sp is of hyp mode
+ cmp r0, #0x1a
+ msreq SP_hyp, r1
+ beq write_sp_out
+ ; Check if the sp is of monitor mode
+ cmp r0, #0x16
+ msreq SP_mon, r1
+write_sp_out
+ pop {r2}
+ bx lr
+ ENDFUNC
+
+ ALIGN 4
+
+;--------------------------------------------------------
+; spin_lock
+;--------------------------------------------------------
+spin_lock FUNCTION
+ MOV r2, #1
+sl_tryloop
+ LDREX r1, [r0]
+ CMP r1, #0
+ STREXEQ r1, r2, [r0]
+ CMPEQ r1, #0
+ BNE sl_tryloop
+ MCR p15, 0, r0, c7, c10, 4
+ bx lr
+ ENDFUNC
+
+;--------------------------------------------------------
+; spin_lock
+;--------------------------------------------------------
+spin_trylock FUNCTION
+ MOV r2, #1
+ LDREX r1, [r0]
+ CMP r1, #0
+ STREXEQ r1, r2, [r0]
+ MOV r0, r1
+ MCR p15, 0, r0, c7, c10, 4
+ bx lr
+ ENDFUNC
+
+ ALIGN 4
+
+;--------------------------------------------------------
+; spin_unlock
+;--------------------------------------------------------
+spin_unlock FUNCTION
+ MOV r1, #0
+ STR r1, [r0]
+ MCR p15, 0, r0, c7, c10, 4
+ bx lr
+ ENDFUNC
+
+ ALIGN 4
+
+;--------------------------------------------------------
+; panic
+;--------------------------------------------------------
+panic FUNCTION
+ isb
+ dsb
+ CPSID aif
+ B panic
+ ENDFUNC
+
+;--------------------------------------------------------------
+; Utility function that takes a pointer (r0), stack size (r1).
+; It returns the pointer to the stack offset for the asked cpu
+;--------------------------------------------------------------
+get_sp FUNCTION
+ ldr r2, =0x2c001800
+ ldr r2, [r2]
+ and r2, r2, #0xff
+ clz r2, r2
+ mov r3, #32
+ sub r2, r3, r2
+ mul r2, r2, r1
+ add r0, r0, r2
+ bx lr
+ ENDFUNC
+
+disable_coherency FUNCTION
+ push {lr}
+ bl read_actlr
+ bic r0, r0, #0x40
+ bl write_actlr
+ isb
+ dsb
+ pop {lr}
+ bx lr
+ ENDFUNC
+
+enable_coherency FUNCTION
+ push {lr}
+ bl read_actlr
+ orr r0, r0, #0x40
+ bl write_actlr
+ isb
+ dsb
+ pop {lr}
+ bx lr
+ ENDFUNC
+
+inv_bpred_is FUNCTION
+ mcr p15, 0, r0, c7, c1, 6
+ bx lr
+ ENDFUNC
+
+inv_bpred_all FUNCTION
+ mcr p15, 0, r0, c7, c5, 6
+ bx lr
+ ENDFUNC
+
+inv_tlb_all FUNCTION
+ mcr p15, 0, r0, c8, c7, 0
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+inv_icache_all FUNCTION
+ mcr p15, 0, r10, c7, c5, 0 ; invalidate I cache
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+inv_icache_mva_pou FUNCTION
+ mcr p15, 0, r0, c7, c5, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+cln_dcache_mva_pou FUNCTION
+ mcr p15, 0, r0, c7, c11, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+cln_dcache_mva_poc FUNCTION
+ mcr p15, 0, r0, c7, c10, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+inv_dcache_mva_poc FUNCTION
+ mcr p15, 0, r0, c7, c6, 1
+ isb
+ dsb
+ bx lr
+ ENDFUNC
+
+ ; Clean/Invalidate/Clean and invalidate a specified cache level.
+ ; Ignore if the level does not exist.
+cache_maint_op FUNCTION
+ push {r4-r11}
+ dsb
+ lsl r10, r0, #1 ; start clean at specified cache level
+ mrc p15, 1, r0, c0, c0, 1 ; read clidr
+10
+ add r2, r10, r10, lsr #1 ; work out 3x current cache level
+ mov r3, r0, lsr r2 ; extract cache type bits from clidr
+ and r3, r3, #7 ; mask of the bits for current cache only
+ cmp r3, #2 ; see what cache we have at this level
+ blt %f50 ; skip if no cache, or just i-cache
+ mcr p15, 2, r10, c0, c0, 0 ; select current cache level in cssr
+ isb ; isb to sych the new cssr&csidr
+ mrc p15, 1, r3, c0, c0, 0 ; read the new csidr
+ and r2, r3, #7 ; extract the length of the cache lines
+ add r2, r2, #4 ; add 4 (line length offset)
+ ldr r4, =0x3ff
+ ands r4, r4, r3, lsr #3 ; find maximum number on the way size
+ clz r5, r4 ; find bit position of way size increment
+ ldr r7, =0x7fff
+ ands r7, r7, r3, lsr #13 ; extract max number of the index size
+20
+ mov r9, r4 ; create working copy of max way size
+30
+ orr r11, r10, r9, lsl r5 ; factor way and cache number into r11
+ lsl r6, r9, r5
+ orr r11, r10, r6 ; factor way and cache number into r11
+ orr r11, r11, r7, lsl r2 ; factor index number into r11
+ lsl r6, r7, r2
+ orr r11, r11, r6 ; factor index number into r11
+ cmp r1, #INV
+ mcreq p15, 0, r11, c7, c6, 2 ; invalidate by set/way
+ beq %f40
+ cmp r1, #CLN
+ mcreq p15, 0, r11, c7, c10, 2 ; clean by set/way
+ beq %f40
+ mcr p15, 0, r11, c7, c14, 2 ; clean & invalidate by set/way
+; nop ; nop
+40
+ subs r9, r9, #1 ; decrement the way
+ bge %b30
+ subs r7, r7, #1 ; decrement the index
+ bge %b20
+50
+ mov r10, #0 ; swith back to cache level 0
+ mcr p15, 2, r10, c0, c0, 0 ; select current cache level in cssr
+ dsb
+ isb
+ pop {r4-r11}
+ bx lr
+ ENDFUNC
+
+enable_user_perfmon_access FUNCTION ; V7 and above
+ mov r0, #1
+ mcr p15, 0, r0, c9, c14, 0 ; write PMUSERENR enable
+ bx lr
+ ENDFUNC
+
+enable_perfmon FUNCTION ; V7 and above
+ mov r0, #(1<<1)+(1<<2)+(1<<4) ; set C, P, X bits
+ mcr p15, 0, r0, c9, c12, 0 ; PMCR
+ mov r0, #(1<<31) ; cycle counter enable
+ mcr p15, 0, r0, c9, c12, 1 ; PMCNTENSET
+ bx lr
+ ENDFUNC
+
+enable_swp FUNCTION ; V7 and above
+ mrc p15, 0, r0, c1, c0, 0
+ orr r0, #0x400
+ mcr p15, 0, r0, c1, c0, 0
+ bx lr
+ ENDFUNC
+
+enter_monitor_mode FUNCTION
+ mov r0, sp ; Save current sp
+ mov r2, lr ; Save current lr
+ mrs r1, cpsr ; Get current mode (SVC) in r1
+ bic r3, r1, #0x1f ; Clear all mode bits
+ orr r3, r3, #0x16 ; Set bits for Monitor mode
+ msr cpsr_cxsf, r3 ; We are now in Monitor Mode
+ mov sp, r0 ; Use the same sp as before
+ mov lr, r2 ; Use the same lr as before
+ msr spsr_cxsf, r1 ; Use saved mode for the MOVS jump to the kernel
+ bx lr
+ ENDFUNC
+
+enter_nonsecure_world FUNCTION
+ push {r4-r7}
+ mov r4, sp ; Save current sp
+ mov r5, lr ; Save current lr
+ mrs r6, spsr ; Get target mode (SVC) in r6
+ bic r7, r6, #0x1f ; Clear all mode bits
+ orr r7, r7, #0x1A ; Set bits for HYP mode
+ msr spsr_cxsf, r7
+ adr lr, hyp_entry
+ movs pc, lr
+hyp_entry ; We are now in HYP mode
+ ; Set the HYP spsr to itself, so that the entry point
+ ; does not see the difference between a function call
+ ; and an exception return.
+ msr spsr_cxsf, r7
+ blx r0
+ msr spsr_cxsf, r6 ; Setup SPSR to jump to NS SVC mode
+ adr r7, ns_svc_entry
+ msr elr_hyp, r7
+ ERET
+ns_svc_entry
+ mov sp, r4
+ mov lr, r5
+ pop {r4-r7}
+ bx lr
+ ENDFUNC
+
+enable_pmu FUNCTION
+ mov r0, #0x0000003f
+ mrc p15, 0, r1, c9, c14, 2 ; Disable overflow interrupts
+ orr r1, r1, r0
+ mcr p15, 0, r1, c9, c14, 2 ; Disable overflow interrupts
+ isb
+ mrc p15, 0, r1, c9, c12, 3 ; Clear overflow flags
+ orr r1, r1, r0
+ mcr p15, 0, r1, c9, c12, 3 ; Clear overflow flags
+ isb
+ mrc p15, 0, r1, c9, c12, 1 ; Enable counters
+ orr r1, r1, r0
+ mcr p15, 0, r1, c9, c12, 1 ; Enable counters
+ isb
+ mov r0, #0x3
+ mrc p15, 0, r1, c9, c12, 0 ;
+ orr r1, r1, r0
+ mcr p15, 0, r1, c9, c12, 0 ; Reset and Master Enable counters
+ bx lr
+ ENDFUNC
+
+ END
diff --git a/bootwrapper/helpers.h b/bootwrapper/helpers.h
new file mode 100644
index 0000000..187df86
--- /dev/null
+++ b/bootwrapper/helpers.h
@@ -0,0 +1,214 @@
+/*
+ * $Copyright:
+ * ----------------------------------------------------------------
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ * ----------------------------------------------------------------
+ * File: helpers.h
+ * ----------------------------------------------------------------
+ * $
+ */
+
+#ifndef _VIRT_HELPERS_H_
+#define _VIRT_HELPERS_H_
+
+extern unsigned int DORMANT_BASE;
+/*******************************************************
+ * Export prototypes of the functions which will be used
+ * to save/restore the Non-secure context.
+ *******************************************************/
+extern void wfe(void);
+extern void sev(void);
+extern void wfi(void);
+extern void dmb(void);
+extern void dsb(void);
+extern void isb(void);
+extern void virt_dead(void);
+extern void smc(unsigned, unsigned);
+extern void dcisw(unsigned);
+extern void dccsw(unsigned);
+extern void dccisw(unsigned);
+
+extern void write_sp(unsigned, unsigned);
+extern void write_lr(unsigned, unsigned);
+extern void write_cpsr(unsigned);
+extern void write_sctlr(unsigned);
+extern void write_actlr(unsigned);
+extern void write_nsacr(unsigned);
+extern void write_ttbr0(unsigned);
+extern void write_ttbcr(unsigned);
+extern void write_cntfrq(unsigned);
+extern void write_cnthctl(unsigned);
+extern void write_cntkctl(unsigned);
+extern void write_cnthp_cval(unsigned, unsigned);
+extern void write_cnthp_tval(unsigned);
+extern void write_cnthp_ctl(unsigned);
+extern void write_cntp_ctl(unsigned);
+extern void write_cntp_tval(unsigned);
+extern void write_csselr(unsigned);
+extern void write_hcr(unsigned);
+extern void write_hdcr(unsigned);
+extern void write_hcptr(unsigned);
+extern void write_hstr(unsigned);
+extern void write_hsctlr(unsigned);
+extern void write_httbr(unsigned long long);
+extern void write_vttbr(unsigned long long);
+extern void write_htcr(unsigned);
+extern void write_vtcr(unsigned);
+extern void write_hmair0(unsigned);
+extern void write_hmair1(unsigned);
+extern void write_vmpidr(unsigned);
+extern void write_vmidr(unsigned);
+extern void write_dacr(unsigned);
+extern void write_ttbr0(unsigned);
+extern void write_cpacr(unsigned);
+extern void write_nsacr(unsigned);
+extern void write_scr(unsigned);
+extern void write_mvbar(unsigned);
+extern void write_hvbar(unsigned);
+extern void write_vbar(unsigned);
+extern void write_prrr(unsigned);
+extern void write_nmrr(unsigned);
+extern void write_dfar(unsigned);
+extern void write_ifar(unsigned);
+extern void write_dfsr(unsigned);
+extern void write_ifsr(unsigned);
+extern void write_adfsr(unsigned);
+extern void write_aifsr(unsigned);
+
+extern void read_cntpct(unsigned *, unsigned *);
+extern unsigned read_dfar(void);
+extern unsigned read_ifar(void);
+extern unsigned read_dfsr(void);
+extern unsigned read_ifsr(void);
+extern unsigned read_adfsr(void);
+extern unsigned read_aifsr(void);
+extern unsigned read_cntfrq(void);
+extern unsigned read_hsctlr(void);
+extern unsigned read_hsr(void);
+extern unsigned read_nmrr(void);
+extern unsigned read_prrr(void);
+extern unsigned read_dacr(void);
+extern unsigned read_ttbr0(void);
+extern unsigned read_cpacr(void);
+extern unsigned read_scr(void);
+extern unsigned read_cpsr(void);
+extern unsigned read_midr(void);
+extern unsigned read_mpidr(void);
+extern unsigned read_vmpidr(void);
+extern unsigned read_vmidr(void);
+extern unsigned read_id_pfr0(void);
+extern unsigned read_id_pfr1(void);
+extern unsigned read_id_dfr0(void);
+extern unsigned read_id_afr0(void);
+extern unsigned read_id_mmfr0(void);
+extern unsigned read_id_mmfr1(void);
+extern unsigned read_id_mmfr2(void);
+extern unsigned read_id_mmfr3(void);
+extern unsigned read_id_isar0(void);
+extern unsigned read_id_isar1(void);
+extern unsigned read_id_isar2(void);
+extern unsigned read_id_isar3(void);
+extern unsigned read_id_isar4(void);
+extern unsigned read_id_isar5(void);
+extern unsigned read_aidr(void);
+extern unsigned read_vbar(void);
+extern unsigned read_mvbar(void);
+extern unsigned read_ctr(void);
+extern unsigned read_tcmtr(void);
+extern unsigned read_tlbtr(void);
+extern unsigned read_hcr(void);
+extern unsigned read_hdcr(void);
+extern unsigned read_hcptr(void);
+extern unsigned read_hstr(void);
+extern unsigned read_vtcr(void);
+extern unsigned read_hdfar(void);
+extern unsigned read_hpfar(void);
+extern unsigned read_cpsr(void);
+extern unsigned read_sp(unsigned);
+extern unsigned read_lr(unsigned);
+extern unsigned read_cpuid(void);
+extern unsigned read_clusterid(void);
+extern unsigned read_clidr(void);
+extern unsigned read_ccsidr(void);
+extern unsigned read_csselr(void);
+extern unsigned read_sctlr(void);
+extern unsigned read_actlr(void);
+extern unsigned read_nsacr(void);
+extern unsigned read_ttbr0(void);
+extern unsigned read_ttbcr(void);
+extern unsigned read_cnthctl(void);
+extern unsigned read_cntkctl(void);
+extern unsigned long read_cnthp_cval(void);
+extern unsigned read_cnthp_tval(void);
+extern unsigned read_cnthp_ctl(void);
+extern unsigned read_cntp_ctl(void);
+extern unsigned read_cntp_tval(void);
+extern unsigned num_secondaries(void);
+extern unsigned *copy_words(volatile unsigned *destination,
+ volatile unsigned *source, unsigned num_words);
+extern unsigned *get_sp(unsigned, unsigned);
+
+/*
+ * V7 functions
+ */
+extern void save_performance_monitors(unsigned int *pointer);
+extern void save_banked_registers(unsigned int *pointer);
+extern void save_control_registers(unsigned int *context);
+extern void save_mmu(unsigned int *pointer);
+extern void save_cp15(unsigned int *pointer);
+
+extern void restore_control_registers(unsigned int *context);
+extern void restore_mmu(unsigned int *pointer);
+extern void restore_cp15(unsigned int *pointer);
+extern void restore_performance_monitors(unsigned int *pointer);
+extern void restore_banked_registers(unsigned int *pointer);
+extern void disable_clean_inv_l1_dcache_v7(void);
+extern void cache_maint_op(unsigned, unsigned);
+extern unsigned get_loc(void);
+extern void disable_coherency(void);
+extern void disable_dcache(void);
+extern void enable_coherency(void);
+extern void enable_dcache(void);
+extern void flush_to_loc(void);
+extern void inv_tlb_all(void);
+extern void inv_icache_all(void);
+extern void inv_icache_mva_pou(unsigned *);
+extern void inv_dcache_mva_poc(unsigned *);
+extern void cln_dcache_mva_poc(unsigned *);
+extern void cln_dcache_mva_pou(unsigned *);
+extern void enable_user_perfmon_access(void);
+extern void enable_perfmon(void);
+extern void enable_swp(void);
+extern void enable_pmu(void);
+extern void enter_monitor_mode(void);
+extern void enter_nonsecure_world(unsigned);
+
+/*
+ * GIC functions
+ */
+extern void save_gic_interface(unsigned int *pointer,
+ unsigned gic_interface_address);
+extern int save_gic_distributor_private(unsigned int *pointer,
+ unsigned gic_distributor_address);
+extern int save_gic_distributor_shared(unsigned int *pointer,
+ unsigned gic_distributor_address);
+extern void restore_gic_interface(unsigned int *pointer,
+ unsigned gic_interface_address);
+extern void restore_gic_distributor_private(unsigned int *pointer,
+ unsigned gic_distributor_address);
+extern void restore_gic_distributor_shared(unsigned int *pointer,
+ unsigned gic_distributor_address);
+extern void disable_gic_dist(unsigned int *tmp,
+ volatile unsigned int *dist_base);
+extern void enable_gic_dist(unsigned int tmp, volatile unsigned int *dist_base);
+
+extern void switcher_exit(void);
+extern void hyp_save(unsigned, unsigned);
+
+#endif /* _VIRT_HELPERS_H_ */
diff --git a/bootwrapper/kernel.S b/bootwrapper/kernel.S
new file mode 100644
index 0000000..cdd6c9f
--- /dev/null
+++ b/bootwrapper/kernel.S
@@ -0,0 +1,19 @@
+ ;; $Copyright:
+ ;; ----------------------------------------------------------------
+ ;; This confidential and proprietary software may be used only as
+ ;; authorised by a licensing agreement from ARM Limited
+ ;; (C) COPYRIGHT 2008-2011 ARM Limited
+ ;; ALL RIGHTS RESERVED
+ ;; The entire notice above must be reproduced on all authorised
+ ;; copies and copies may only be made to the extent permitted
+ ;; by a licensing agreement from ARM Limited.
+ ;; ----------------------------------------------------------------
+ ;; File: kernel.S
+ ;; ----------------------------------------------------------------
+ ;; $
+
+ AREA |kernel|, CODE, ALIGN=2
+ EXPORT kernel_start
+kernel_start
+ INCBIN payload/kernel
+ END
diff --git a/bootwrapper/makemap b/bootwrapper/makemap
new file mode 100755
index 0000000..2e9f6c4
--- /dev/null
+++ b/bootwrapper/makemap
@@ -0,0 +1,166 @@
+#! /bin/env perl
+# $Copyright:
+# ----------------------------------------------------------------
+# This confidential and proprietary software may be used only as
+# authorised by a licensing agreement from ARM Limited
+# (C) COPYRIGHT 2008-2011 ARM Limited
+# ALL RIGHTS RESERVED
+# The entire notice above must be reproduced on all authorised
+# copies and copies may only be made to the extent permitted
+# by a licensing agreement from ARM Limited.
+# ----------------------------------------------------------------
+# File: virt_helpers.s
+# ----------------------------------------------------------------
+# $
+
+use strict;
+
+use vars qw(
+ $image
+ $source
+ $obj
+ $map
+ $kernaddr
+ $sh
+ $mh
+ %chunksdone
+ @chunks
+);
+
+sub addchunk($$)
+{
+ my $file = shift;
+ my $addr = shift;
+ my $size = -s $file;
+ my $name = $file;
+ $name =~ s|^.*/([^/]+)$|$1|;
+
+ # Multiple contiguous sections are saved as one chunk, so in that case only process the first
+ if (!defined $chunksdone{$name})
+ {
+ print $sh <<EOF;
+ AREA |$name|, CODE, ALIGN=2
+ INCBIN $file
+EOF
+
+ print $mh <<EOF;
+$name $addr $size
+{
+ ${name}DATA $addr $size
+ {
+ $obj ($name)
+ }
+}
+EOF
+
+ $chunksdone{$name} = 1;
+ push @chunks, [ $addr, $size ];
+ }
+}
+
+sub num($)
+{
+ my $n = shift;
+ $n = oct $n if $n =~ /^0/;
+ return $n;
+}
+
+sub covered($)
+{
+ my $start = num(shift);
+
+ for (@chunks)
+ {
+# printf "Checking $start against chunk $_->[0] (%d), $_->[1] (%d), %d\n",num($_->[0]),num($_->[1]),num($_->[0])+num($_->[0]);
+ return 1 if $start >= num($_->[0]) && $start < num($_->[0])+num($_->[1]);
+ }
+ return 0;
+}
+
+($image=shift) && ($source = shift) or die "\
+Usage: $0 image source [ kernaddr ]
+ Creates source and map files to load the sections of \$image
+ \(if it is an ARM ELF file\), or the whole of \$image at \$kernaddr";
+
+$kernaddr=shift;
+$map="$source.map";
+$obj="$source.o";
+
+open $sh, ">$source.S" or die "Can't create '$source.S'";
+open $mh, ">$map" or die "Can't create '$map'";
+
+# Check if $image is an ELF file
+my $type=`file -L $image`;
+if ( $type =~ /ELF.*ARM/ )
+{
+# print "$image is an ELF file - splitting\n";
+ system("rm -rf $image.bin");
+ system("fromelf --bin $image -o $image.bin");
+ my $fromelfv=`fromelf --vsn`;
+ ($fromelfv=~/FromELF, (RVCT|)([\d\.]+)/) && ($2 >= 4.1) or die "fromelf version '$2' is too old - need 4.1 or greater";
+ my $desc = `fromelf --text $image`;
+ my $chunk;
+ my $chunkdone;
+ my %chunkdefined;
+ my $zichunk;
+
+ for my $line (split /\n/,$desc)
+ {
+ # Program header lines indicate what loadable chunks are present
+ # Handily, these refer to 'Virtual address' rather than 'Address'
+ $chunkdefined{$1} = 1 if $line =~ /^\s+Virtual address:\s+(0x[0-9a-fA-F]+)/;
+
+ # Section entries give the chunk name
+ if ($line =~ /^\*+\s+Section\s+#\d+\s+'([^']+)/)
+ {
+ # If there's only one chunk, fromelf creates a single file not a directory
+ $chunk = -d "$image.bin" ? "$image.bin/$1" : "$image.bin";
+ $zichunk = 0;
+ if ($line =~ / \(SHT_NOBITS\) /)
+ {
+ # We produce an explicit block of zeroes to cope with systems that don't auto-expand ZINIT areas
+ $chunk .= '.zi';
+ $zichunk = 1;
+ }
+ }
+
+ if ($zichunk && ($line =~ /^\s+Size\s*:\s+(\d+)\s+bytes/))
+ {
+ my $size = $1;
+ my $h;
+ open $h, ">$chunk" or die "Can't create ZI chunk '$chunk'";
+ binmode $h;
+ print $h chr(0) x $size;
+ close $h;
+ }
+ if ($line =~ /^\s+Address:\s+(0x[0-9a-fA-F]+)/ && ($zichunk || $chunkdefined{$1}))
+ {
+ # ZI data is already in the binary dump if it is followed by non-ZI data.
+ if ($zichunk && covered($1))
+ {
+ print "ZI data at $1 set by existing data; will not set explicitly\n";
+ $zichunk = 0;
+ # Remove .zi
+ $chunk = substr($chunk,0,-3);
+ }
+ else
+ {
+ # Multiple contiguous sections are saved as one chunk, so in that case only process the first
+ # Here we deal with the case where all the sections are contiguous
+ addchunk("$chunk",$1) if $zichunk || -d "$image.bin" || !$chunkdone;
+ $chunkdone = 1;
+ }
+ }
+
+ $kernaddr=$1 if $line =~ /^\s+Image Entry point:\s+(0x[0-9a-fA-F]+)/;
+ }
+}
+else
+{
+# print "$image being wrapped as plain binary to load at $kernaddr\n";
+ addchunk($image,$kernaddr);
+}
+
+die "No entry point in image or on command line" if !defined $kernaddr;
+
+print $sh " EXPORT ${source}_image\n${source}_image EQU $kernaddr\n END\n";
diff --git a/bootwrapper/payload/fsimg b/bootwrapper/payload/fsimg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bootwrapper/payload/fsimg
diff --git a/bootwrapper/payload/kernel b/bootwrapper/payload/kernel
new file mode 100644
index 0000000..4467aef
--- /dev/null
+++ b/bootwrapper/payload/kernel
Binary files differ
diff --git a/bootwrapper/uart.c b/bootwrapper/uart.c
new file mode 100644
index 0000000..93334ec
--- /dev/null
+++ b/bootwrapper/uart.c
@@ -0,0 +1,108 @@
+/*
+ * $Copyright:
+ * ----------------------------------------------------------------
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ * ----------------------------------------------------------------
+ * File: uart.c
+ * ----------------------------------------------------------------
+ * $
+ *
+ * uart.c - boot code to output characters on a PL011 uart
+ * Not SMP-safe, so make sure you only call these functions
+ * from one CPU at a time.
+ * Call config_uart first.
+ * Implements fputc() so you can use printf() in your code.
+ */
+
+#include <stdio.h>
+#include "bootwrapper.h"
+#include "helpers.h"
+
+//* PL011 Registers Offsets from UART Base adress */
+#define PL011_DR 0x0
+#define PL011_RSR 0x4
+#define PL011_ECR 0x4
+#define PL011_FR 0x18
+#define PL011_ILPR 0x20
+#define PL011_IBRD 0x24
+#define PL011_FBRD 0x28
+#define PL011_LCRH 0x2C
+#define PL011_CR 0x30
+#define PL011_IFLS 0x34
+#define PL011_IMSC 0x38
+#define PL011_RIS 0x3C
+#define PL011_MIS 0x40
+#define PL011_ICR 0x44
+#define PL011_DMACR 0x48
+
+#define PL011_TXFE 0x80
+#define PL011_TXFF 0x20
+
+static unsigned uart_base = NULL;
+
+void config_uart(void)
+{
+ uart_base = UART0_BASE;
+ write32(uart_base + PL011_CR, 0);
+ write32(uart_base + PL011_FBRD, 0x01);
+ write32(uart_base + PL011_IBRD, 0x27);
+ write32(uart_base + PL011_LCRH, 0x70);
+ write32(uart_base + PL011_CR, 0xf01); /* TXE|RXE|En|DTR|CTS */
+}
+
+void drain_uart_fifo(void)
+{
+ while (!(read32(uart_base + PL011_FR) & PL011_TXFE)) {
+ /* Do nothing */
+ }
+}
+
+static __inline void wait_for_space(void)
+{
+ while ((read32(uart_base + PL011_FR) & PL011_TXFF)) {
+ /* Do nothing */
+ }
+}
+
+void output_char(int c)
+{
+ if (c == '\n') {
+ wait_for_space();
+ write32(uart_base + PL011_DR, '\r');
+ }
+ wait_for_space();
+ write32(uart_base + PL011_DR, c);
+}
+
+void output_string(const char *string)
+{
+ int i;
+
+ for (i = 0; string[i]; ++i) {
+ output_char(string[i]);
+ }
+}
+
+void hexword(unsigned value)
+{
+ printf(" 0x%8.8x", value);
+ drain_uart_fifo();
+}
+
+typedef struct __FILE {
+ int dummy;
+} FILE;
+
+FILE __stdout;
+
+int fputc(int c, FILE * f)
+{
+ output_char(c);
+ return c;
+}
diff --git a/bootwrapper/vectors.S b/bootwrapper/vectors.S
new file mode 100644
index 0000000..096d1b6
--- /dev/null
+++ b/bootwrapper/vectors.S
@@ -0,0 +1,66 @@
+;;-----------------------------------------------------------------------------
+;; $Copyright:
+;; ----------------------------------------------------------------
+;; This confidential and proprietary software may be used only as
+;; authorised by a licensing agreement from ARM Limited
+;; (C) COPYRIGHT 2008-2011 ARM Limited
+;; ALL RIGHTS RESERVED
+;; The entire notice above must be reproduced on all authorised
+;; copies and copies may only be made to the extent permitted
+;; by a licensing agreement from ARM Limited.
+;; ----------------------------------------------------------------
+;; File: vectors.S
+;; ----------------------------------------------------------------
+;; $
+
+ AREA | vectors|, CODE, ALIGN=8
+ PRESERVE8
+
+; ==============================================================================
+; Simple vector table
+; ==============================================================================
+ IMPORT start
+ IMPORT undef
+ IMPORT swi
+ IMPORT pabort
+ IMPORT dabort
+ IMPORT unused
+ IMPORT irq
+ IMPORT fiq
+ EXPORT vector_table
+
+vector_table
+ LDR PC, pstart
+ LDR PC, pundef
+ LDR PC, pswi
+ LDR PC, ppabort
+ LDR PC, pdabort
+ LDR PC, punused
+ LDR PC, pirq
+ LDR PC, pfiq
+
+pstart
+ DCD start
+
+pundef
+ DCD undef
+
+pswi
+ DCD swi
+
+ppabort
+ DCD pabort
+
+pdabort
+ DCD dabort
+
+punused
+ DCD unused
+
+pirq
+ DCD irq
+
+pfiq
+ DCD fiq
+
+ END
diff --git a/bootwrapper/vgic.h b/bootwrapper/vgic.h
new file mode 100644
index 0000000..fb76d2f
--- /dev/null
+++ b/bootwrapper/vgic.h
@@ -0,0 +1,51 @@
+/*
+ * $Copyright:
+ * ----------------------------------------------------------------
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ * ----------------------------------------------------------------
+ * File: vgic.h
+ * ----------------------------------------------------------------
+ * $
+ */
+
+#ifndef __VGIC_H__
+#define __VGIC_H__
+
+#define GIC_ID_PHY_BASE 0x2C001000 /* Physical Distributor */
+#define GIC_IC_PHY_BASE 0x2C002000 /* Physical CPU interface */
+
+/* Distributor interface registers */
+#define GICD_CTL 0x0
+#define GICD_CTR 0x4
+#define GICD_SEC 0x80
+#define GICD_ENABLESET 0x100
+#define GICD_ENABLECLEAR 0x180
+#define GICD_PENDINGSET 0x200
+#define GICD_PENDINGCLEAR 0x280
+#define GICD_ACTIVESET 0x300
+#define GICD_ACTIVECLEAR 0x380
+#define GICD_PRI 0x400
+#define GICD_CPUS 0x800
+#define GICD_CONFIG 0xC00
+#define GICD_SW 0xF00
+#define GICD_CPENDSGIR 0xF10
+#define GICD_SPENDSGIR 0xF20
+
+/* Physical CPU Interface registers */
+#define GICC_CTL 0x0
+#define GICC_PRIMASK 0x4
+#define GICC_BP 0x8
+#define GICC_INTACK 0xC
+#define GICC_EOI 0x10
+#define GICC_RUNNINGPRI 0x14
+#define GICC_HIGHESTPEND 0x18
+#define GICC_DEACTIVATE 0x1000
+#define GICC_PRIODROP GICC_EOI
+
+#endif /* __VGIC_H__ */