Add README.
[gps-watch.git] / src / bootloader / bootloader.rs
index 95f4e97f639dfb7f1a044eaec07401d09e4f7dd9..d4a686b5ea83a290f16f4518f251c71a5f3fc03f 100644 (file)
@@ -29,6 +29,7 @@ const COMMAND_ERASE     : u32 = 0x49e89a20;
 const COMMAND_PROGRAM   : u32 = 0x37f7dc8d;
 const COMMAND_VERIFY    : u32 = 0x4a213efb;
 const COMMAND_LOADCHUNK : u32 = 0x1b329768;
+const COMMAND_START_APP : u32 = 0xd27df1bf;
 
 pub struct Bootloader {
     command: u32,
@@ -45,6 +46,7 @@ enum Error {
     UnknownCommand = 1,
     InvalidArgument,
     ChecksumMismatch,
+    PermissionDenied,
 }
 
 extern {
@@ -120,7 +122,7 @@ impl Bootloader {
         }
     }
 
-    pub fn run(&mut self) {
+    pub fn run(&mut self) -> bool {
         if self.command_bytes < 4 {
             if let Some(b) = try_read_u8() {
                 self.command >>= 8;
@@ -130,10 +132,14 @@ impl Bootloader {
             }
         }
 
-        if self.command_bytes == 4 {
+        if self.command_bytes != 4 {
+            true
+        } else {
             self.command_bytes = 0;
 
             self.process_command();
+
+            self.command != COMMAND_START_APP
         }
     }
 
@@ -172,6 +178,9 @@ impl Bootloader {
                     write_ack();
                 }
             },
+            COMMAND_START_APP => {
+                write_ack();
+            },
             _ => {
                 write_nak(Error::UnknownCommand);
             }
@@ -183,6 +192,11 @@ impl Bootloader {
 
         if sector > 0xff {
             Err(Error::InvalidArgument)
+        } else if sector == 0x01 {
+            // The second sector contains the flash configuration field,
+            // and keeping it in the erased state has the potential
+            // to brick the device.
+            Err(Error::PermissionDenied)
         } else {
             flash::erase(sector);