Introduce SPIN_ON_BL1_EXIT build flag

This patch introduces a new build flag, SPIN_ON_BL1_EXIT, which
puts an infinite loop in BL1. It is intended to help debugging
the post-BL2 phase of the Trusted Firmware by stopping execution
in BL1 just before handing over to BL31. At this point, the
developer may take control of the target using a debugger.

This feature is disabled by default and can be enabled by
rebuilding BL1 with SPIN_ON_BL1_EXIT=1.

User Guide updated accordingly.

Change-Id: I6b6779d5949c9e5571dd371255520ef1ac39685c
diff --git a/Makefile b/Makefile
index 7a4be44..c3252c2 100644
--- a/Makefile
+++ b/Makefile
@@ -89,6 +89,9 @@
 PROGRAMMABLE_RESET_ADDRESS	:= 0
 # Build flag to treat usage of deprecated platform and framework APIs as error.
 ERROR_DEPRECATED		:= 0
+# Flag to introduce an infinite loop in BL1 just before it exits into the next
+# image. This is meant to help debugging the post-BL2 phase.
+SPIN_ON_BL1_EXIT		:= 0
 
 
 ################################################################################
@@ -348,6 +351,7 @@
 $(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID))
 $(eval $(call assert_boolean,ERROR_DEPRECATED))
 $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
+$(eval $(call assert_boolean,SPIN_ON_BL1_EXIT))
 
 
 ################################################################################
@@ -370,6 +374,7 @@
 $(eval $(call add_define,PSCI_EXTENDED_STATE_ID))
 $(eval $(call add_define,ERROR_DEPRECATED))
 $(eval $(call add_define,ENABLE_PLAT_COMPAT))
+$(eval $(call add_define,SPIN_ON_BL1_EXIT))
 
 
 ################################################################################
diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S
index 0bd0485..ee66ef0 100644
--- a/bl1/aarch64/bl1_exceptions.S
+++ b/bl1/aarch64/bl1_exceptions.S
@@ -207,6 +207,12 @@
 	bl	disable_mmu_icache_el3
 	tlbi	alle3
 
+#if SPIN_ON_BL1_EXIT
+	bl	print_debug_loop_message
+debug_loop:
+	b	debug_loop
+#endif
+
 	bl	bl1_plat_prepare_exit
 
 	ldp	x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index f62f31d..73f023a 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -208,3 +208,11 @@
 	NOTICE("BL1: Booting BL3-1\n");
 	print_entry_point_info(bl31_ep_info);
 }
+
+#if SPIN_ON_BL1_EXIT
+void print_debug_loop_message(void)
+{
+	NOTICE("BL1: Debug loop, spinning forever\n");
+	NOTICE("BL1: Please connect the debugger to continue\n");
+}
+#endif
diff --git a/docs/user-guide.md b/docs/user-guide.md
index a7a0c11..3db7a86 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -372,6 +372,12 @@
     Firmware as error. It can take the value 1 (flag the use of deprecated
     APIs as error) or 0. The default is 0.
 
+*   `SPIN_ON_BL1_EXIT`: This option introduces an infinite loop in BL1. It can
+    take either 0 (no loop) or 1 (add a loop). 0 is the default. This loop stops
+    execution in BL1 just before handing over to BL31. At this point, all
+    firmware images have been loaded in memory and the MMU as well as the caches
+    are turned off. Refer to the "Debugging options" section for more details.
+
 #### ARM development platform specific build options
 
 *   `ARM_TSP_RAM_LOCATION`: location of the TSP binary. Options:
@@ -500,6 +506,25 @@
     BL33=<path-to>/<bl33_image>                                \
     make PLAT=<platform> DEBUG=1 V=1 all fip
 
+It is also possible to introduce an infinite loop to help in debugging the
+post-BL2 phase of the Trusted Firmware. This can be done by rebuilding BL1 with
+the `SPIN_ON_BL1_EXIT=1` build flag. Refer to the "Summary of build options"
+section. In this case, the developer may take control of the target using a
+debugger when indicated by the console output. When using DS-5, the following
+commands can be used:
+
+    # Stop target execution
+    interrupt
+
+    #
+    # Prepare your debugging environment, e.g. set breakpoints
+    #
+
+    # Jump over the debug loop
+    set var $AARCH64::$Core::$PC = $AARCH64::$Core::$PC + 4
+
+    # Resume execution
+    continue
 
 ### Building the Test Secure Payload