sim: Verify write alignment

When an alignment greater than one is specified, enforce this in the
simulated flash driver.
diff --git a/sim/src/flash.rs b/sim/src/flash.rs
index 8cf267c..b85651c 100644
--- a/sim/src/flash.rs
+++ b/sim/src/flash.rs
@@ -34,15 +34,22 @@
 pub struct Flash {
     data: Vec<u8>,
     sectors: Vec<usize>,
+    // Alignment required for writes.
+    align: usize,
 }
 
 impl Flash {
     /// Given a sector size map, construct a flash device for that.
-    pub fn new(sectors: Vec<usize>) -> Flash {
+    pub fn new(sectors: Vec<usize>, align: usize) -> Flash {
+        // Verify that the alignment is a positive power of two.
+        assert!(align > 0);
+        assert!(align & (align - 1) == 0);
+
         let total = sectors.iter().sum();
         Flash {
             data: vec![0xffu8; total],
             sectors: sectors,
+            align: align,
         }
     }
 
@@ -74,6 +81,15 @@
             bail!(ebounds("Write outside of device"));
         }
 
+        // Verify the alignment (which must be a power of two).
+        if offset & (self.align - 1) != 0 {
+            bail!(ewrite("Misaligned write address"));
+        }
+
+        if payload.len() & (self.align - 1) != 0 {
+            bail!(ewrite("Write length not multiple of alignment"));
+        }
+
         let mut sub = &mut self.data[offset .. offset + payload.len()];
         if sub.iter().any(|x| *x != 0xFF) {
             bail!(ewrite("Write to non-FF location"));
diff --git a/sim/src/main.rs b/sim/src/main.rs
index 33b2c0c..533e651 100644
--- a/sim/src/main.rs
+++ b/sim/src/main.rs
@@ -79,13 +79,16 @@
         return;
     }
 
+    let align = args.flag_align.map(|x| x.0).unwrap_or(1);
+
     let (mut flash, areadesc) = match args.flag_device {
         None => panic!("Missing mandatory argument"),
         Some(DeviceName::Stm32f4) => {
             // STM style flash.  Large sectors, with a large scratch area.
             let flash = Flash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024,
                                    64 * 1024,
-                                   128 * 1024, 128 * 1024, 128 * 1024]);
+                                   128 * 1024, 128 * 1024, 128 * 1024],
+                                   align as usize);
             let mut areadesc = AreaDesc::new(&flash);
             areadesc.add_image(0x020000, 0x020000, FlashId::Image0);
             areadesc.add_image(0x040000, 0x020000, FlashId::Image1);
@@ -94,7 +97,7 @@
         }
         Some(DeviceName::K64f) => {
             // NXP style flash.  Small sectors, one small sector for scratch.
-            let flash = Flash::new(vec![4096; 128]);
+            let flash = Flash::new(vec![4096; 128], align as usize);
 
             let mut areadesc = AreaDesc::new(&flash);
             areadesc.add_image(0x020000, 0x020000, FlashId::Image0);
@@ -105,7 +108,7 @@
         Some(DeviceName::K64fBig) => {
             // Simulating an STM style flash on top of an NXP style flash.  Underlying flash device
             // uses small sectors, but we tell the bootloader they are large.
-            let flash = Flash::new(vec![4096; 128]);
+            let flash = Flash::new(vec![4096; 128], align as usize);
 
             let mut areadesc = AreaDesc::new(&flash);
             areadesc.add_simple_image(0x020000, 0x020000, FlashId::Image0);
@@ -124,7 +127,7 @@
     let upgrade = install_image(&mut flash, 0x040000, 41922);
 
     // Set an alignment, and position the magic value.
-    c::set_sim_flash_align(args.flag_align.map(|x| x.0).unwrap_or(1));
+    c::set_sim_flash_align(align);
     let trailer_size = c::boot_trailer_sz();
 
     // Mark the upgrade as ready to install.  (This looks like it might be a bug in the code,