From df366e055d7c3831bd40d96efe3a91cdeb31e2dd Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Sat, 11 Oct 2014 15:15:02 +1100
Subject: [PATCH] Don't run user application in the bootloader unless a valid
 app is present (thanks to Alex Kazik).

---
 Bootloaders/CDC/BootloaderCDC.c               |  4 ++
 Bootloaders/DFU/BootloaderDFU.c               |  9 ++++-
 .../MassStorage/BootloaderMassStorage.c       | 17 ++++++--
 Bootloaders/Printer/BootloaderPrinter.c       | 40 +++++++++++++++++++
 LUFA/DoxygenPages/ChangeLog.txt               |  5 ++-
 5 files changed, 68 insertions(+), 7 deletions(-)

diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c
index f66a483e6..c7eeb929a 100644
--- a/Bootloaders/CDC/BootloaderCDC.c
+++ b/Bootloaders/CDC/BootloaderCDC.c
@@ -91,6 +91,10 @@ void Application_Jump_Check(void)
 	if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
 	  JumpToApplication |= true;
 
+	/* Don't run the user application if the reset vector is blank (no app loaded) */
+	if (pgm_read_word_near(0) == 0xFFFF)
+	  JumpToApplication = false;
+
 	/* If a request has been made to jump to the user application, honor it */
 	if (JumpToApplication)
 	{
diff --git a/Bootloaders/DFU/BootloaderDFU.c b/Bootloaders/DFU/BootloaderDFU.c
index 0385bfc49..160b9f657 100644
--- a/Bootloaders/DFU/BootloaderDFU.c
+++ b/Bootloaders/DFU/BootloaderDFU.c
@@ -127,6 +127,10 @@ void Application_Jump_Check(void)
 	if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
 	  JumpToApplication |= true;
 
+	/* Don't run the user application if the reset vector is blank (no app loaded) */
+
+	  JumpToApplication = false;
+
 	/* If a request has been made to jump to the user application, honor it */
 	if (JumpToApplication)
 	{
@@ -751,8 +755,9 @@ static void ProcessWriteCommand(void)
 			}
 			else                                                               // Start via jump
 			{
-				/* Set the flag to terminate the bootloader at next opportunity */
-				RunBootloader = false;
+				/* Set the flag to terminate the bootloader at next opportunity if a valid application has been loaded */
+				if (pgm_read_word_near(0) == 0xFFFF)
+				  RunBootloader = false;
 			}
 		}
 	}
diff --git a/Bootloaders/MassStorage/BootloaderMassStorage.c b/Bootloaders/MassStorage/BootloaderMassStorage.c
index cfe0cdbf8..191d49efc 100644
--- a/Bootloaders/MassStorage/BootloaderMassStorage.c
+++ b/Bootloaders/MassStorage/BootloaderMassStorage.c
@@ -116,13 +116,22 @@ void Application_Jump_Check(void)
 
 	/* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
 	if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
-	{
-		MagicBootKey      = 0;
-		JumpToApplication = true;
-	}
+	  JumpToApplication |= true;
+
+	/* Don't run the user application if the reset vector is blank (no app loaded) */
+	if (pgm_read_word_near(0) == 0xFFFF)
+	  JumpToApplication = false;
 
+	/* If a request has been made to jump to the user application, honor it */
 	if (JumpToApplication)
 	{
+		/* Turn off the watchdog */
+		MCUSR &= ~(1<<WDRF);
+		wdt_disable();
+
+		/* Clear the boot key and jump to the user application */
+		MagicBootKey = 0;
+
 		// cppcheck-suppress constStatement
 		((void (*)(void))0x0000)();
 	}
diff --git a/Bootloaders/Printer/BootloaderPrinter.c b/Bootloaders/Printer/BootloaderPrinter.c
index a19cb0674..716a23a1f 100644
--- a/Bootloaders/Printer/BootloaderPrinter.c
+++ b/Bootloaders/Printer/BootloaderPrinter.c
@@ -119,9 +119,49 @@ uint16_t MagicBootKey ATTR_NO_INIT;
  */
 void Application_Jump_Check(void)
 {
+	bool JumpToApplication = false;
+
+	#if (BOARD == BOARD_LEONARDO)
+		/* Enable pull-up on the IO13 pin so we can use it to select the mode */
+		PORTC |=  (1 << 7);
+		Delay_MS(10);
+
+		/* If IO13 is not jumpered to ground, start the user application instead */
+		JumpToApplication |= ((PINC & (1 << 7)) != 0);
+
+		/* Disable pull-up after the check has completed */
+		PORTC &= ~(1 << 7);
+	#elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+		/* Disable JTAG debugging */
+		JTAG_DISABLE();
+
+		/* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
+		PORTF |= (1 << 4);
+		Delay_MS(10);
+
+		/* If the TCK pin is not jumpered to ground, start the user application instead */
+		JumpToApplication |= ((PINF & (1 << 4)) != 0);
+
+		/* Re-enable JTAG debugging */
+		JTAG_ENABLE();
+	#endif
+
 	/* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
 	if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
+	  JumpToApplication |= true;
+
+	/* Don't run the user application if the reset vector is blank (no app loaded) */
+	if (pgm_read_word_near(0) == 0xFFFF)
+	  JumpToApplication = false;
+
+	/* If a request has been made to jump to the user application, honor it */
+	if (JumpToApplication)
 	{
+		/* Turn off the watchdog */
+		MCUSR &= ~(1<<WDRF);
+		wdt_disable();
+
+		/* Clear the boot key and jump to the user application */
 		MagicBootKey = 0;
 
 		// cppcheck-suppress constStatement
diff --git a/LUFA/DoxygenPages/ChangeLog.txt b/LUFA/DoxygenPages/ChangeLog.txt
index 738ee68f0..57277ebee 100644
--- a/LUFA/DoxygenPages/ChangeLog.txt
+++ b/LUFA/DoxygenPages/ChangeLog.txt
@@ -11,7 +11,10 @@
   *   - None.
   *
   *  <b>Changed:</b>
-  *   - None.
+  *  - Library Applications:
+  *   - The CDC, DFU, Mass Storage and Printer class bootloaders will no longer run the user application if the application reset
+  *     vector is blank (thanks to Alex Kazik)
+  *   - The Printer class bootloader is now compatible with the original Atmel XPLAIN and Arduino Leonardo boards.
   *
   *  <b>Fixed:</b>
   *   - None.
-- 
GitLab