From 63a7256739cc6db0664e601fd0f9f534a345479a Mon Sep 17 00:00:00 2001
From: schneider <schneider@blinkenlichts.net>
Date: Wed, 24 Apr 2019 15:51:44 +0200
Subject: [PATCH] add initial bootloader. untested.

---
 bootloader/Makefile         |   1 +
 bootloader/bootloader-usb.c | 329 ++++++++++++++++++++++++++
 bootloader/main.c           | 452 +++++++++++++++++-------------------
 bootloader/mscmem.c         |   7 +
 lib/card10/mx25lba.c        |  10 +-
 lib/ff13/Source/diskio.c    |  10 +-
 lib/ff13/Source/diskio.h    |   3 -
 7 files changed, 568 insertions(+), 244 deletions(-)
 create mode 100644 bootloader/bootloader-usb.c

diff --git a/bootloader/Makefile b/bootloader/Makefile
index 38a6b7d1..abc96c8c 100644
--- a/bootloader/Makefile
+++ b/bootloader/Makefile
@@ -67,6 +67,7 @@ CMSIS_ROOT=$(LIBS_DIR)/CMSIS
 # Source files for this test (add path to VPATH below)
 SRCS  = main.c
 SRCS += mscmem.c
+SRCS += bootloader-usb.c
 SRCS += ../lib/card10/mx25lba.c
 
 # Where to find source files for this test
diff --git a/bootloader/bootloader-usb.c b/bootloader/bootloader-usb.c
new file mode 100644
index 00000000..b6b3924e
--- /dev/null
+++ b/bootloader/bootloader-usb.c
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, 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.
+ *
+ * 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 MAXIM INTEGRATED 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 Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *
+ * $Id: main.c 31505 2017-10-20 21:16:29Z zach.metzinger $
+ *
+ *******************************************************************************
+ */
+
+/**
+ * @file    main.c
+ * @brief   USB Mass Storage Class example
+ * @details This project creates a mass storage device using either on-board RAM or 
+ *          external SPI flash memory.  Load the project, connect a cable from the PC
+ *          to the USB connector.  A new external drive should appear than can be read
+ *          and written.
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include "mxc_config.h"
+#include "mxc_sys.h"
+#include "mxc_delay.h"
+#include "board.h"
+#include "led.h"
+#include "usb.h"
+#include "usb_event.h"
+#include "enumerate.h"
+#include "msc.h"
+#include "descriptors.h"
+#include "mscmem.h"
+
+
+/***** Definitions *****/
+#define EVENT_ENUM_COMP     MAXUSB_NUM_EVENTS
+#define EVENT_REMOTE_WAKE   (EVENT_ENUM_COMP + 1)
+
+/***** Global Data *****/
+volatile int configured;
+volatile int suspended;
+volatile unsigned int event_flags;
+int remote_wake_en;
+
+/***** Function Prototypes *****/
+static int setconfig_callback(usb_setup_pkt *sud, void *cbdata);
+static int setfeature_callback(usb_setup_pkt *sud, void *cbdata);
+static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata);
+static int event_callback(maxusb_event_t evt, void *data);
+static void usb_app_sleep(void);
+static void usb_app_wakeup(void);
+
+/***** File Scope Variables *****/
+
+/* This EP assignment must match the Configuration Descriptor */
+static const msc_cfg_t msc_cfg = {
+  1,                    /* EP OUT */
+  MXC_USBHS_MAX_PACKET, /* OUT max packet size */
+  2,                    /* EP IN */
+  MXC_USBHS_MAX_PACKET, /* IN max packet size */
+};
+
+static const msc_idstrings_t ids = {
+    "MAXIM",            /* Vendor string.  Maximum of 8 bytes */
+    "MSC Example",       /* Product string.  Maximum of 16 bytes */
+    "1.0"              /* Version string.  Maximum of 4 bytes */
+};
+
+/* Functions to control "disk" memory. See msc.h for definitions. */
+static const msc_mem_t mem = {
+    mscmem_init,
+    mscmem_start,
+    mscmem_stop,
+    mscmem_ready,
+    mscmem_size,
+    mscmem_read,
+    mscmem_write,
+};
+
+/* This callback is used to allow the driver to call part specific initialization functions. */
+int usb_startup_cb()
+{
+    const sys_cfg_usbhs_t sys_usbhs_cfg = NULL;
+    return SYS_USBHS_Init(&sys_usbhs_cfg);
+}
+
+int usb_shutdown_cb()
+{
+    return SYS_USBHS_Shutdown();
+}
+
+/* User-supplied function to delay usec micro-seconds */
+void delay_us(unsigned int usec)
+{
+    /* mxc_delay() takes unsigned long, so can't use it directly */
+    mxc_delay(usec);
+}
+
+
+/******************************************************************************/
+void run_usbmsc(void)
+{
+    maxusb_cfg_options_t usb_opts;
+
+    printf("Waiting for VBUS...\n");
+
+    /* Initialize state */
+    configured = 0;
+    suspended = 0;
+    event_flags = 0;
+    remote_wake_en = 0;
+
+    /* Start out in full speed */
+    usb_opts.enable_hs = 0;
+    usb_opts.delay_us = delay_us; /* Function which will be used for delays */
+    usb_opts.init_callback = usb_startup_cb;
+    usb_opts.shutdown_callback = usb_shutdown_cb;
+
+    /* Initialize the usb module */
+    if (usb_init(&usb_opts) != 0) {
+        printf("usb_init() failed\n");
+        while (1);
+    }
+
+    /* Initialize the enumeration module */
+    if (enum_init() != 0) {
+        printf("enum_init() failed\n");
+        while (1);
+    }
+
+    /* Register enumeration data */
+    enum_register_descriptor(ENUM_DESC_DEVICE, (uint8_t*)&device_descriptor, 0);
+    enum_register_descriptor(ENUM_DESC_CONFIG, (uint8_t*)&config_descriptor, 0);
+    enum_register_descriptor(ENUM_DESC_STRING, lang_id_desc, 0);
+    enum_register_descriptor(ENUM_DESC_STRING, mfg_id_desc, 1);
+    enum_register_descriptor(ENUM_DESC_STRING, prod_id_desc, 2);
+    enum_register_descriptor(ENUM_DESC_STRING, serial_id_desc, 3);
+
+    /* Handle configuration */
+    enum_register_callback(ENUM_SETCONFIG, setconfig_callback, NULL);
+
+    /* Handle feature set/clear */
+    enum_register_callback(ENUM_SETFEATURE, setfeature_callback, NULL);
+    enum_register_callback(ENUM_CLRFEATURE, clrfeature_callback, NULL);
+
+    /* Initialize the class driver */
+    if (msc_init(&config_descriptor.msc_interface_descriptor, &ids, &mem) != 0) {
+        printf("msc_init() failed\n");
+        while (1);
+    }
+
+    /* Register callbacks */
+    usb_event_enable(MAXUSB_EVENT_NOVBUS, event_callback, NULL);
+    usb_event_enable(MAXUSB_EVENT_VBUS, event_callback, NULL);
+
+    /* Start with USB in low power mode */
+    usb_app_sleep();
+    NVIC_EnableIRQ(USB_IRQn);
+
+    /* Wait for events */
+    while (1) {
+
+        if (suspended || !configured) {
+            LED_Off(0);
+        } else {
+            LED_On(0);
+        }
+
+        if (event_flags) {
+            /* Display events */
+            if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_NOVBUS)) {
+                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_NOVBUS);
+                printf("VBUS Disconnect\n");
+            } else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_VBUS)) {
+                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_VBUS);
+                printf("VBUS Connect\n");
+            } else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_BRST)) {
+                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_BRST);
+                printf("Bus Reset\n");
+            } else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_SUSP)) {
+                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_SUSP);
+                printf("Suspended\n");
+            } else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_DPACT)) {
+                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_DPACT);
+                printf("Resume\n");
+            } else if (MXC_GETBIT(&event_flags, EVENT_ENUM_COMP)) {
+                MXC_CLRBIT(&event_flags, EVENT_ENUM_COMP);
+                printf("Enumeration complete.\n");
+            } else if (MXC_GETBIT(&event_flags, EVENT_REMOTE_WAKE)) {
+                MXC_CLRBIT(&event_flags, EVENT_REMOTE_WAKE);
+                printf("Remote Wakeup\n");
+            }
+        }
+    }
+}
+
+/******************************************************************************/
+static int setconfig_callback(usb_setup_pkt *sud, void *cbdata)
+{
+    /* Confirm the configuration value */
+    if (sud->wValue == config_descriptor.config_descriptor.bConfigurationValue) {
+        configured = 1;
+        MXC_SETBIT(&event_flags, EVENT_ENUM_COMP);
+        return msc_configure(&msc_cfg); /* Configure the device class */
+    } else if (sud->wValue == 0) {
+        configured = 0;
+        return msc_deconfigure();
+    }
+
+    return -1;
+}
+
+/******************************************************************************/
+static int setfeature_callback(usb_setup_pkt *sud, void *cbdata)
+{
+    if(sud->wValue == FEAT_REMOTE_WAKE) {
+        remote_wake_en = 1;
+    } else {
+        // Unknown callback
+        return -1;
+    }
+
+    return 0;
+}
+
+/******************************************************************************/
+static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata)
+{
+    if(sud->wValue == FEAT_REMOTE_WAKE) {
+        remote_wake_en = 0;
+    } else {
+        // Unknown callback
+        return -1;
+    }
+    
+    return 0;
+}
+
+/******************************************************************************/
+static void usb_app_sleep(void)
+{
+    /* TODO: Place low-power code here */
+    suspended = 1;
+}
+
+/******************************************************************************/
+static void usb_app_wakeup(void)
+{
+    /* TODO: Place low-power code here */
+    suspended = 0;
+}
+
+/******************************************************************************/
+static int event_callback(maxusb_event_t evt, void *data)
+{
+    /* Set event flag */
+    MXC_SETBIT(&event_flags, evt);
+
+    printf("event: %d\n", evt);
+    switch (evt) {
+        case MAXUSB_EVENT_NOVBUS:
+            usb_event_disable(MAXUSB_EVENT_BRST);
+            usb_event_disable(MAXUSB_EVENT_SUSP);
+            usb_event_disable(MAXUSB_EVENT_DPACT);
+            usb_disconnect();
+            configured = 0;
+            enum_clearconfig();
+            msc_deconfigure();
+            usb_app_sleep();
+            break;
+        case MAXUSB_EVENT_VBUS:
+            usb_event_clear(MAXUSB_EVENT_BRST);
+            usb_event_enable(MAXUSB_EVENT_BRST, event_callback, NULL);
+            usb_event_clear(MAXUSB_EVENT_SUSP);
+            usb_event_enable(MAXUSB_EVENT_SUSP, event_callback, NULL);
+            usb_connect();
+            usb_app_sleep();
+            break;
+        case MAXUSB_EVENT_BRST:
+            usb_app_wakeup();
+            enum_clearconfig();
+            msc_deconfigure();
+            configured = 0;
+            suspended = 0;
+            break;
+        case MAXUSB_EVENT_SUSP:
+            usb_app_sleep();
+            break;
+        case MAXUSB_EVENT_DPACT:
+            usb_app_wakeup();
+            break;
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+/******************************************************************************/
+void USB_IRQHandler(void)
+{
+    usb_event_handler();
+}
diff --git a/bootloader/main.c b/bootloader/main.c
index 0c3250fe..ae105486 100644
--- a/bootloader/main.c
+++ b/bootloader/main.c
@@ -45,292 +45,268 @@
 
 #include <stdio.h>
 #include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+
 #include "mxc_config.h"
 #include "mxc_sys.h"
 #include "mxc_delay.h"
+#include "flc.h"
+#include "icc.h"
+#include "crc.h"
 #include "board.h"
 #include "led.h"
-#include "usb.h"
-#include "usb_event.h"
-#include "enumerate.h"
-#include "msc.h"
-#include "descriptors.h"
-#include "mscmem.h"
-
-
-/***** Definitions *****/
-#define EVENT_ENUM_COMP     MAXUSB_NUM_EVENTS
-#define EVENT_REMOTE_WAKE   (EVENT_ENUM_COMP + 1)
-
-#define BUFFER_SIZE  64
-
-#define STRINGIFY(x) #x
-#define TOSTRING(x) STRINGIFY(x)
-
-/***** Global Data *****/
-volatile int configured;
-volatile int suspended;
-volatile unsigned int event_flags;
-int remote_wake_en;
-
-/***** Function Prototypes *****/
-static int setconfig_callback(usb_setup_pkt *sud, void *cbdata);
-static int setfeature_callback(usb_setup_pkt *sud, void *cbdata);
-static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata);
-static int event_callback(maxusb_event_t evt, void *data);
-static void usb_app_sleep(void);
-static void usb_app_wakeup(void);
-
-/***** File Scope Variables *****/
-
-/* This EP assignment must match the Configuration Descriptor */
-static const msc_cfg_t msc_cfg = {
-  1,                    /* EP OUT */
-  MXC_USBHS_MAX_PACKET, /* OUT max packet size */
-  2,                    /* EP IN */
-  MXC_USBHS_MAX_PACKET, /* IN max packet size */
-};
+#include "ff.h"
 
-static const msc_idstrings_t ids = {
-    "MAXIM",            /* Vendor string.  Maximum of 8 bytes */
-    "MSC Example",       /* Product string.  Maximum of 16 bytes */
-    "1.0"              /* Version string.  Maximum of 4 bytes */
-};
+#define GPIO_PORT_IN                PORT_1
+#define GPIO_PIN_IN                 PIN_6
 
-/* Functions to control "disk" memory. See msc.h for definitions. */
-static const msc_mem_t mem = {
-    mscmem_init,
-    mscmem_start,
-    mscmem_stop,
-    mscmem_ready,
-    mscmem_size,
-    mscmem_read,
-    mscmem_write,
-};
 
-/* This callback is used to allow the driver to call part specific initialization functions. */
-int usb_startup_cb()
-{
-    const sys_cfg_usbhs_t sys_usbhs_cfg = NULL;
-    return SYS_USBHS_Init(&sys_usbhs_cfg);
-}
+#define PARTITION_START (0x10000000 + 64 * 1024)
+#define PARTITION_END (0x10000000 + 512 * 1024 - 1) /* TODO: check if 1 MB also works. Might have to enable the second bank */
+//#define PARTITION_END (0x10000000 + 1024 * 1024 - 1)
 
-int usb_shutdown_cb()
-{
-    return SYS_USBHS_Shutdown();
-}
+extern void run_usbmsc(void);
+DIR dir;                /* Directory object */
+FATFS FatFs;
 
-/* User-supplied function to delay usec micro-seconds */
-void delay_us(unsigned int usec)
+static void crc_sw(uint32_t *crcval, uint8_t *data, uint8_t len, uint32_t polynomial)
 {
-    /* mxc_delay() takes unsigned long, so can't use it directly */
-    mxc_delay(usec);
+	int i, j;
+	uint32_t temp;
+
+	for(i = 0; i < len; ++i) {
+		temp = (data[i] & 0xFF);
+		for(j = 0; j < 8; ++j) {
+			if((temp ^ *crcval) & 1) {
+				*crcval >>= 1;
+				*crcval ^= polynomial;
+			} else {
+				*crcval >>= 1;
+			}
+			temp >>= 1;
+		}
+	}
 }
 
 
-/******************************************************************************/
-int main(void)
+bool mount(void)
 {
-    maxusb_cfg_options_t usb_opts;
-  
-    printf("\n\n***** " TOSTRING(TARGET) " USB Mass Storage Example *****\n");
-    printf("Waiting for VBUS...\n");
-
-    /* Initialize state */
-    configured = 0;
-    suspended = 0;
-    event_flags = 0;
-    remote_wake_en = 0;
-
-    /* Start out in full speed */
-    usb_opts.enable_hs = 0;
-    usb_opts.delay_us = delay_us; /* Function which will be used for delays */
-    usb_opts.init_callback = usb_startup_cb;
-    usb_opts.shutdown_callback = usb_shutdown_cb;
-
-    /* Initialize the usb module */
-    if (usb_init(&usb_opts) != 0) {
-        printf("usb_init() failed\n");
-        while (1);
-    }
-
-    /* Initialize the enumeration module */
-    if (enum_init() != 0) {
-        printf("enum_init() failed\n");
-        while (1);
+    FRESULT res;
+    res=f_mount(&FatFs,"/",0);
+    if(res != FR_OK) {
+        printf("f_mount error %d\n", res);
+        return false;
     }
 
-    /* Register enumeration data */
-    enum_register_descriptor(ENUM_DESC_DEVICE, (uint8_t*)&device_descriptor, 0);
-    enum_register_descriptor(ENUM_DESC_CONFIG, (uint8_t*)&config_descriptor, 0);
-    enum_register_descriptor(ENUM_DESC_STRING, lang_id_desc, 0);
-    enum_register_descriptor(ENUM_DESC_STRING, mfg_id_desc, 1);
-    enum_register_descriptor(ENUM_DESC_STRING, prod_id_desc, 2);
-    enum_register_descriptor(ENUM_DESC_STRING, serial_id_desc, 3);
-
-    /* Handle configuration */
-    enum_register_callback(ENUM_SETCONFIG, setconfig_callback, NULL);
-
-    /* Handle feature set/clear */
-    enum_register_callback(ENUM_SETFEATURE, setfeature_callback, NULL);
-    enum_register_callback(ENUM_CLRFEATURE, clrfeature_callback, NULL);
-
-    /* Initialize the class driver */
-    if (msc_init(&config_descriptor.msc_interface_descriptor, &ids, &mem) != 0) {
-        printf("msc_init() failed\n");
-        while (1);
+    res = f_opendir(&dir, "0:");
+    if(res != FR_OK) {
+        printf("f_opendir error %d\n", res);
+        return false;
     }
 
-    /* Register callbacks */
-    usb_event_enable(MAXUSB_EVENT_NOVBUS, event_callback, NULL);
-    usb_event_enable(MAXUSB_EVENT_VBUS, event_callback, NULL);
-
-    /* Start with USB in low power mode */
-    usb_app_sleep();
-    NVIC_EnableIRQ(USB_IRQn);
+    return true;
+}
 
-    /* Wait for events */
-    while (1) {
+bool check_integrity(void)
+{
+    FIL file;
+    UINT readbytes;
+    char *filename = "card10.bin";
+    uint8_t data[512];
+    FRESULT res;
+
+    res=f_open(&file, filename, FA_OPEN_EXISTING|FA_READ);
+    if(res != FR_OK) {
+        printf("f_open error %d\n", res);
+        return false;
+    }
 
-        if (suspended || !configured) {
-            LED_Off(0);
-        } else {
-            LED_On(0);
+    uint32_t crcval = 0;
+    do {
+        res = f_read(&file, data, sizeof(data), &readbytes);
+        if(res != FR_OK) {
+            printf("f_read error %d\n", res);
+            crcval = 1; // Make sure to fail the test
+            break;
         }
+        crc_sw(&crcval, data, readbytes, TPU_CRC_CCITT);
+    } while (readbytes == sizeof(data));
 
-        if (event_flags) {
-            /* Display events */
-            if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_NOVBUS)) {
-                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_NOVBUS);
-                printf("VBUS Disconnect\n");
-            } else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_VBUS)) {
-                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_VBUS);
-                printf("VBUS Connect\n");
-            } else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_BRST)) {
-                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_BRST);
-                printf("Bus Reset\n");
-            } else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_SUSP)) {
-                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_SUSP);
-                printf("Suspended\n");
-            } else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_DPACT)) {
-                MXC_CLRBIT(&event_flags, MAXUSB_EVENT_DPACT);
-                printf("Resume\n");
-            } else if (MXC_GETBIT(&event_flags, EVENT_ENUM_COMP)) {
-                MXC_CLRBIT(&event_flags, EVENT_ENUM_COMP);
-                printf("Enumeration complete.\n");
-            } else if (MXC_GETBIT(&event_flags, EVENT_REMOTE_WAKE)) {
-                MXC_CLRBIT(&event_flags, EVENT_REMOTE_WAKE);
-                printf("Remote Wakeup\n");
-            }
-        }
+    f_close(&file);
+
+    if(crcval == 0) {
+        return true;
+    } else {
+        printf("CRC check failed. Final CRC: %d\n", crcval);
+        return true;
+        return false;
     }
 }
 
-/******************************************************************************/
-static int setconfig_callback(usb_setup_pkt *sud, void *cbdata)
+bool is_update_needed(void)
 {
-    /* Confirm the configuration value */
-    if (sud->wValue == config_descriptor.config_descriptor.bConfigurationValue) {
-        configured = 1;
-        MXC_SETBIT(&event_flags, EVENT_ENUM_COMP);
-        return msc_configure(&msc_cfg); /* Configure the device class */
-    } else if (sud->wValue == 0) {
-        configured = 0;
-        return msc_deconfigure();
+    FIL file;
+    UINT readbytes;
+    char *filename = "card10.bin";
+    uint8_t data[512];
+    FRESULT res;
+
+    res=f_open(&file, filename, FA_OPEN_EXISTING|FA_READ);
+    if(res != FR_OK) {
+        printf("f_open error %d\n", res);
+        return false;
     }
 
-    return -1;
-}
+    uint8_t *partition = (uint8_t *)(intptr_t)PARTITION_START;
+    bool different = false;
+    do {
+        res = f_read(&file, data, sizeof(data), &readbytes);
+        if(res != FR_OK) {
+            printf("f_read error %d\n", res);
+            break; /* Going to return false, don't want to use this file */
+        }
+        if(memcmp(partition, data, readbytes)) {
+            different = true;
+            break;
+        }
+        partition += readbytes;
+    } while (readbytes == sizeof(data));
 
-/******************************************************************************/
-static int setfeature_callback(usb_setup_pkt *sud, void *cbdata)
-{
-    if(sud->wValue == FEAT_REMOTE_WAKE) {
-        remote_wake_en = 1;
-    } else {
-        // Unknown callback
-        return -1;
-    }
+    f_close(&file);
 
-    return 0;
+    //different = true;
+    return different;
 }
 
-/******************************************************************************/
-static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata)
+void erase_partition(void)
 {
-    if(sud->wValue == FEAT_REMOTE_WAKE) {
-        remote_wake_en = 0;
-    } else {
-        // Unknown callback
-        return -1;
+    int ret = FLC_MultiPageErase(PARTITION_START, PARTITION_END);
+    if(ret != E_NO_ERROR) {
+        printf("FLC_MultiPageErase failed with %d\n", ret);
+        while(1);
     }
-    
-    return 0;
 }
 
-/******************************************************************************/
-static void usb_app_sleep(void)
+void flash_partition(void)
 {
-    /* TODO: Place low-power code here */
-    suspended = 1;
+    FIL file;
+    UINT readbytes;
+    char *filename = "card10.bin";
+    uint8_t data[512];
+    FRESULT res;
+
+    res=f_open(&file, filename, FA_OPEN_EXISTING|FA_READ);
+    if(res != FR_OK) {
+        printf("f_open error %d\n", res);
+        while(1);
+    }
+
+    uint32_t partition = PARTITION_START;
+
+    ICC_Disable();
+    do {
+        res = f_read(&file, data, sizeof(data), &readbytes);
+        if(res != FR_OK) {
+            printf("f_read error %d\n", res);
+            break; /* Going to return false, don't want to use this file */
+        }
+        int ret = FLC_Write(partition, readbytes, (uint32_t *)data); /* wild cast. not sure if this works */
+        if(ret != E_NO_ERROR) {
+            printf("FLC_Write failed with %d\n", ret);
+            while(1);
+        }
+        partition += readbytes;
+    } while (readbytes == sizeof(data));
+    ICC_Enable();
+
+    f_close(&file);
 }
 
-/******************************************************************************/
-static void usb_app_wakeup(void)
+#if 0
+void test(void)
 {
-    /* TODO: Place low-power code here */
-    suspended = 0;
+    FRESULT res;
+    FIL file;
+    UINT readbytes;
+    char *filename = "card10.bin";
+    int len = 512;
+    char data[512];
+
+    res=f_open(&file, filename, FA_OPEN_EXISTING|FA_READ);
+    if(res != FR_OK) printf("f_open error %d\n", res);
+
+    res = f_read(&file, data, len, &readbytes);
+    if(res != FR_OK) printf("f_read error %d\n", res);
+
+    f_close(&file);
+
+    data[readbytes] = 0;
+
+    printf("data: %s\n", data);
 }
+#endif
+
+static inline void boot(const void * vtable){
+    SCB->VTOR = (uintptr_t) vtable;
+
+	// Reset stack pointer & branch to the new reset vector.
+	__asm(  "mov r0, %0\n"
+			"ldr sp, [r0]\n"
+			"ldr r0, [r0, #4]\n"
+			"bx r0\n"
+			:
+			: "r"(vtable)
+			: "%sp", "r0");
+};
+
 
 /******************************************************************************/
-static int event_callback(maxusb_event_t evt, void *data)
+int main(void)
 {
-    /* Set event flag */
-    MXC_SETBIT(&event_flags, evt);
-
-    switch (evt) {
-        case MAXUSB_EVENT_NOVBUS:
-            usb_event_disable(MAXUSB_EVENT_BRST);
-            usb_event_disable(MAXUSB_EVENT_SUSP);
-            usb_event_disable(MAXUSB_EVENT_DPACT);
-            usb_disconnect();
-            configured = 0;
-            enum_clearconfig();
-            msc_deconfigure();
-            usb_app_sleep();
-            break;
-        case MAXUSB_EVENT_VBUS:
-            usb_event_clear(MAXUSB_EVENT_BRST);
-            usb_event_enable(MAXUSB_EVENT_BRST, event_callback, NULL);
-            usb_event_clear(MAXUSB_EVENT_SUSP);
-            usb_event_enable(MAXUSB_EVENT_SUSP, event_callback, NULL);
-            usb_connect();
-            usb_app_sleep();
-            break;
-        case MAXUSB_EVENT_BRST:
-            usb_app_wakeup();
-            enum_clearconfig();
-            msc_deconfigure();
-            configured = 0;
-            suspended = 0;
-            break;
-        case MAXUSB_EVENT_SUSP:
-            usb_app_sleep();
-            break;
-        case MAXUSB_EVENT_DPACT:
-            usb_app_wakeup();
-            break;
-        default:
-            break;
+
+    printf("\n\nBootloader\n");
+
+    gpio_cfg_t gpio_in;
+    gpio_in.port = GPIO_PORT_IN;
+    gpio_in.mask = GPIO_PIN_IN;
+    gpio_in.pad = GPIO_PAD_PULL_UP;
+    gpio_in.func = GPIO_FUNC_IN;
+    GPIO_Config(&gpio_in);
+
+    // If the button is pressed, we go into MSC mode.
+    if (!GPIO_InGet(&gpio_in)) {
+        run_usbmsc();
+
+        // If we return, don't try to boot. Maybe rather trigger a software reset.
+        // Reason: Not sure in which state the USB peripheral is and what kind
+        // of interrupts are active.
+        while(1);
     }
 
-    return 0;
-}
 
-/******************************************************************************/
-void USB_IRQHandler(void)
-{
-    usb_event_handler();
+    if(mount()) {
+        if(check_integrity()) {
+            if(is_update_needed()) {
+                MXC_FLC0->clkdiv = 54;
+                erase_partition();
+                flash_partition();
+            } else {
+                printf("No update needed\n");
+            }
+        } else {
+            printf("Integrity check failed\n");
+        }
+    }
+
+
+    printf("Trying to boot\n");
+    // boot partition
+    boot((uintptr_t *) PARTITION_START);
+
+    while (1) {
+        // Should never be reached.
+    }
 }
 
 /******************************************************************************/
diff --git a/bootloader/mscmem.c b/bootloader/mscmem.c
index d6daa95d..70f2429d 100644
--- a/bootloader/mscmem.c
+++ b/bootloader/mscmem.c
@@ -62,40 +62,47 @@
 /******************************************************************************/
 int mscmem_init()
 {
+    printf("%s\n", __func__);
 	return mx25_init();
 }
 /******************************************************************************/
 uint32_t mscmem_size(void)
 {
+    printf("%s\n", __func__);
 	return mx25_size();
 }
 
 /******************************************************************************/
 int mscmem_read(uint32_t lba, uint8_t* buffer)
 {
+    printf("%s\n", __func__);
 	return mx25_read(lba, buffer);
 }
 
 /******************************************************************************/
 int mscmem_write(uint32_t lba, uint8_t* buffer)
 {
+    printf("%s\n", __func__);
     return mx25_write(lba, buffer);
 }
 
 /******************************************************************************/
 int mscmem_start()
 {
+    printf("%s\n", __func__);
     return mx25_start();
 }
 
 /******************************************************************************/
 int mscmem_stop()
 {
+    printf("%s\n", __func__);
     return mx25_stop();
 }
 
 /******************************************************************************/
 int mscmem_ready()
 {
+    printf("%s\n", __func__);
     return mx25_ready();
 }
diff --git a/lib/card10/mx25lba.c b/lib/card10/mx25lba.c
index 609d3c67..f7fd61ae 100644
--- a/lib/card10/mx25lba.c
+++ b/lib/card10/mx25lba.c
@@ -129,6 +129,7 @@ static uint32_t getSector(uint32_t num)
 /******************************************************************************/
 int mx25_init()
 {
+    printf("%s\n", __func__);
 
     if(!initialized) {
         MX25_Init();
@@ -142,6 +143,7 @@ int mx25_init()
 /******************************************************************************/
 uint32_t mx25_size(void)
 {
+    printf("%s\n", __func__);
     /* Get number of 512 byte chunks the MX25 contains. */
     return (MX25_SECTOR_SIZE >> LBA_SIZE_SHIFT) * MX25_NUM_SECTORS;
 }
@@ -149,6 +151,7 @@ uint32_t mx25_size(void)
 /******************************************************************************/
 int mx25_read(uint32_t lba, uint8_t* buffer)
 {
+    printf("%s\n", __func__);
     uint32_t addr;
 
     /* Convert to MX25 sector number. */
@@ -170,6 +173,7 @@ int mx25_read(uint32_t lba, uint8_t* buffer)
 /******************************************************************************/
 int mx25_write(uint32_t lba, uint8_t* buffer)
 {
+    printf("%s\n", __func__);
     uint32_t addr;
 
     /* Convert to MX25 sector number. */
@@ -192,9 +196,10 @@ int mx25_write(uint32_t lba, uint8_t* buffer)
 /******************************************************************************/
 int mx25_start()
 {
+    printf("%s\n", __func__);
     /* Turn on the MX25 if it is not already. */
     if(!initialized) {
-        mscmem_init();
+        mx25_init();
     }
 
     /* Check if the initialization succeeded. If it has, start running. */
@@ -209,6 +214,7 @@ int mx25_start()
 /******************************************************************************/
 int mx25_stop()
 {
+    printf("%s\n", __func__);
     /* TODO - could shut down XIPF interface here. */
 
     /* Flush the currently cached sector if necessary. */
@@ -222,6 +228,7 @@ int mx25_stop()
 /******************************************************************************/
 int mx25_sync()
 {
+    printf("%s\n", __func__);
     /* Flush the currently cached sector if necessary. */
     if(getSector(INVALID_SECTOR)) {
         return 1;
@@ -231,6 +238,7 @@ int mx25_sync()
 /******************************************************************************/
 int mx25_ready()
 {
+    printf("%s -> %d\n", __func__, running);
     return running;
 }
 
diff --git a/lib/ff13/Source/diskio.c b/lib/ff13/Source/diskio.c
index 1c06d6d8..69458836 100644
--- a/lib/ff13/Source/diskio.c
+++ b/lib/ff13/Source/diskio.c
@@ -17,6 +17,9 @@
 
 #define SECTOR_SIZE     512UL
 
+/*local vaiables*/
+static uint8_t rtc_en;
+
 #if SDHC
 /* # of times to check for a card, should be > 1 to detect both SD and MMC */
 #define INIT_CARD_RETRIES 10
@@ -38,6 +41,7 @@ extern uint32_t mx25_size(void);
 extern int mx25_read(uint32_t lba, uint8_t* buffer);
 extern int mx25_write(uint32_t lba, uint8_t* buffer);
 extern int mx25_sync(void);
+extern int mx25_ready(void);
 
 /*-----------------------------------------------------------------------*/
 /* Get Drive Status                                                      */
@@ -55,7 +59,9 @@ DSTATUS disk_status (
 
     DSTATUS status = 0;
     if(pdrv == 0) {
-        return STA_NOINIT;
+        if(mx25_ready()) {
+            status = RES_OK;
+         }
     }
 
 #if SDHC
@@ -97,7 +103,7 @@ DSTATUS disk_initialize (
 #endif
 
     if(pdrv == 0) {
-        if(mx25_start()) {
+        if(mx25_start() == 0) {
             status = RES_OK;
         }
     }
diff --git a/lib/ff13/Source/diskio.h b/lib/ff13/Source/diskio.h
index b8e9cbcd..40551fbd 100644
--- a/lib/ff13/Source/diskio.h
+++ b/lib/ff13/Source/diskio.h
@@ -20,9 +20,6 @@ extern "C" {
 /* Status of Disk Functions */
 typedef BYTE	DSTATUS;
 
-/*local vaiables*/
-static uint8_t rtc_en;
-
 /* Results of Disk Functions */
 typedef enum {
 	RES_OK = 0,		/* 0: Successful */
-- 
GitLab