From addcc9f6cc8423564bccbcc6c6229f95fddd43fe Mon Sep 17 00:00:00 2001
From: Nikolay Amiantov <ab@fmap.me>
Date: Thu, 22 Aug 2019 14:26:30 +0300
Subject: [PATCH] Implement reboot-to-bootloader call

Use a special file at filesystem root for that.
---
 bootloader/main.c              | 20 ++++++++++++++++++--
 epicardium/epicardium.h        |  2 +-
 epicardium/modules/lifecycle.c |  8 +++++++-
 pycardium/modules/os.c         | 11 ++++++++---
 4 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/bootloader/main.c b/bootloader/main.c
index 560bb517..85ad2edb 100644
--- a/bootloader/main.c
+++ b/bootloader/main.c
@@ -28,6 +28,10 @@
 
 #define PARTITION_START (0x10000000 + 64 * 1024)
 #define PARTITION_END (0x10000000 + 1024 * 1024 - 1)
+#define MSC_MAGIC 0x6E697807
+
+/* TODO: Make this address part of the linker script */
+void* API_CALL_MEM = (void*)0x20080000;
 
 DIR dir;
 FATFS FatFs;
@@ -68,6 +72,18 @@ int mount(void)
 	return 0;
 }
 
+int get_msc_flag(void)
+{
+	// We use the API call memory to store a magic value there.
+	uint32_t* flag = (uint32_t*)API_CALL_MEM;
+	if (*flag == MSC_MAGIC) {
+		*flag = 0;
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
 int check_integrity(void)
 {
 	FIL file;
@@ -242,8 +258,8 @@ int main(void)
 
 	bootloader_display_init();
 
-	// If the button is pressed, we go into MSC mode.
-	if (PB_Get(3)) {
+	// If the button is pressed or a flag in memory is detected, we go into MSC mode.
+	if (PB_Get(3) || get_msc_flag()) {
 		msc();
 	}
 
diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index eb34e17b..1385839b 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -242,7 +242,7 @@ API(API_SYSTEM_EXEC, int __epic_exec(char *name));
 /**
  * Reset/Restart card10
  */
-API(API_SYSTEM_RESET, void epic_system_reset(void));
+API(API_SYSTEM_RESET, void epic_system_reset(int to_bootloader));
 
 /**
  * PMIC API
diff --git a/epicardium/modules/lifecycle.c b/epicardium/modules/lifecycle.c
index 375cfef6..214fe4a7 100644
--- a/epicardium/modules/lifecycle.c
+++ b/epicardium/modules/lifecycle.c
@@ -17,6 +17,8 @@
 
 #define PYCARDIUM_IVT (void *)0x10080000
 #define BLOCK_WAIT pdMS_TO_TICKS(1000)
+#define MSC_MAGIC 0x6E697807
+
 /*
  * Loading an empty filename into Pycardium will drop straight into the
  * interpreter.  This define is used to make it more clear when we intend
@@ -282,8 +284,12 @@ static void load_menu(bool reset)
 /*
  * Restart the firmware
  */
-void epic_system_reset(void)
+void epic_system_reset(int to_bootloader)
 {
+	// Set a flag for the bootloader.
+	uint32_t* flag = (uint32_t*)API_CALL_MEM;
+	*flag = to_bootloader ? MSC_MAGIC : 0;
+
 	card10_reset();
 }
 
diff --git a/pycardium/modules/os.c b/pycardium/modules/os.c
index 874a0693..f858b868 100644
--- a/pycardium/modules/os.c
+++ b/pycardium/modules/os.c
@@ -77,14 +77,19 @@ static mp_obj_t mp_os_exec(mp_obj_t name_in)
 }
 static MP_DEFINE_CONST_FUN_OBJ_1(exec_obj, mp_os_exec);
 
-static mp_obj_t mp_os_reset(void)
+static mp_obj_t mp_os_reset(size_t n_args, const mp_obj_t *args)
 {
-	epic_system_reset();
+	int bootloader_mode = 0;
+	if (n_args == 1) {
+		bootloader_mode = mp_obj_get_int(args[0]);
+	}
+
+	epic_system_reset(bootloader_mode);
 
 	/* unreachable */
 	return mp_const_none;
 }
-static MP_DEFINE_CONST_FUN_OBJ_0(reset_obj, mp_os_reset);
+static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(reset_obj, 0, 1, mp_os_reset);
 
 static mp_obj_t mp_os_listdir(mp_obj_t py_path)
 {
-- 
GitLab