sim: Move 'Flash' into a trait

Make 'Flash' a trait, and move the current functionality into a type
called 'SimFlash'.  The code that runs the simulation only uses the
trait.

Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/sim/src/api.rs b/sim/src/api.rs
index 7b81627..2fa6b31 100644
--- a/sim/src/api.rs
+++ b/sim/src/api.rs
@@ -3,6 +3,7 @@
 use flash::{Result, Flash};
 use libc;
 use log::LogLevel;
+use mem;
 use std::slice;
 
 // The current active flash device.  The 'static is a lie, and we manage the lifetime ourselves.
@@ -10,7 +11,8 @@
 
 // Set the flash device to be used by the simulation.  The pointer is unsafely stashed away.
 pub unsafe fn set_flash(dev: &mut Flash) {
-    FLASH = Some(dev);
+    let dev: &'static mut Flash = mem::transmute(dev);
+    FLASH = Some(dev as *mut Flash);
 }
 
 pub unsafe fn clear_flash() {
diff --git a/sim/src/area.rs b/sim/src/area.rs
index 4b85912..eb42292 100644
--- a/sim/src/area.rs
+++ b/sim/src/area.rs
@@ -1,6 +1,6 @@
 //! Describe flash areas.
 
-use flash::{Flash, Sector};
+use flash::{Flash, SimFlash, Sector};
 use std::ptr;
 
 /// Structure to build up the boot area table.
@@ -12,7 +12,7 @@
 }
 
 impl AreaDesc {
-    pub fn new(flash: &Flash) -> AreaDesc {
+    pub fn new(flash: &SimFlash) -> AreaDesc {
         AreaDesc {
             areas: vec![],
             whole: vec![],
diff --git a/sim/src/flash.rs b/sim/src/flash.rs
index 5e08f8d..98b6a27 100644
--- a/sim/src/flash.rs
+++ b/sim/src/flash.rs
@@ -23,6 +23,15 @@
     }
 }
 
+pub trait Flash {
+    fn erase(&mut self, offset: usize, len: usize) -> Result<()>;
+    fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()>;
+    fn read(&self, offset: usize, data: &mut [u8]) -> Result<()>;
+
+    fn sector_iter(&self) -> SectorIter;
+    fn device_size(&self) -> usize;
+}
+
 fn ebounds<T: AsRef<str>>(message: T) -> ErrorKind {
     ErrorKind::OutOfBounds(message.as_ref().to_owned())
 }
@@ -34,7 +43,7 @@
 /// An emulated flash device.  It is represented as a block of bytes, and a list of the sector
 /// mapings.
 #[derive(Clone)]
-pub struct Flash {
+pub struct SimFlash {
     data: Vec<u8>,
     write_safe: Vec<bool>,
     sectors: Vec<usize>,
@@ -42,15 +51,15 @@
     align: usize,
 }
 
-impl Flash {
+impl SimFlash {
     /// Given a sector size map, construct a flash device for that.
-    pub fn new(sectors: Vec<usize>, align: usize) -> Flash {
+    pub fn new(sectors: Vec<usize>, align: usize) -> SimFlash {
         // Verify that the alignment is a positive power of two.
         assert!(align > 0);
         assert!(align & (align - 1) == 0);
 
         let total = sectors.iter().sum();
-        Flash {
+        SimFlash {
             data: vec![0xffu8; total],
             write_safe: vec![true; total],
             sectors: sectors,
@@ -58,10 +67,39 @@
         }
     }
 
+    #[allow(dead_code)]
+    pub fn dump(&self) {
+        self.data.dump();
+    }
+
+    /// Dump this image to the given file.
+    #[allow(dead_code)]
+    pub fn write_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
+        let mut fd = File::create(path).chain_err(|| "Unable to write image file")?;
+        fd.write_all(&self.data).chain_err(|| "Unable to write to image file")?;
+        Ok(())
+    }
+
+    // Scan the sector map, and return the base and offset within a sector for this given byte.
+    // Returns None if the value is outside of the device.
+    fn get_sector(&self, offset: usize) -> Option<(usize, usize)> {
+        let mut offset = offset;
+        for (sector, &size) in self.sectors.iter().enumerate() {
+            if offset < size {
+                return Some((sector, offset));
+            }
+            offset -= size;
+        }
+        return None;
+    }
+
+}
+
+impl Flash for SimFlash {
     /// The flash drivers tend to erase beyond the bounds of the given range.  Instead, we'll be
     /// strict, and make sure that the passed arguments are exactly at a sector boundary, otherwise
     /// return an error.
-    pub fn erase(&mut self, offset: usize, len: usize) -> Result<()> {
+    fn erase(&mut self, offset: usize, len: usize) -> Result<()> {
         let (_start, slen) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
         let (end, elen) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;
 
@@ -91,7 +129,7 @@
     /// This emulates a flash device which starts out erased, with the
     /// added restriction that repeated writes to the same location
     /// are disallowed, even if they would be safe to do.
-    pub fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()> {
+    fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()> {
         if offset + payload.len() > self.data.len() {
             panic!("Write outside of device");
         }
@@ -119,7 +157,7 @@
     }
 
     /// Read is simple.
-    pub fn read(&self, offset: usize, data: &mut [u8]) -> Result<()> {
+    fn read(&self, offset: usize, data: &mut [u8]) -> Result<()> {
         if offset + data.len() > self.data.len() {
             bail!(ebounds("Read outside of device"));
         }
@@ -129,41 +167,17 @@
         Ok(())
     }
 
-    // Scan the sector map, and return the base and offset within a sector for this given byte.
-    // Returns None if the value is outside of the device.
-    fn get_sector(&self, offset: usize) -> Option<(usize, usize)> {
-        let mut offset = offset;
-        for (sector, &size) in self.sectors.iter().enumerate() {
-            if offset < size {
-                return Some((sector, offset));
-            }
-            offset -= size;
-        }
-        return None;
-    }
-
     /// An iterator over each sector in the device.
-    pub fn sector_iter(&self) -> SectorIter {
+    fn sector_iter(&self) -> SectorIter {
         SectorIter {
             iter: self.sectors.iter().enumerate(),
             base: 0,
         }
     }
 
-    pub fn device_size(&self) -> usize {
+    fn device_size(&self) -> usize {
         self.data.len()
     }
-
-    pub fn dump(&self) {
-        self.data.dump();
-    }
-
-    /// Dump this image to the given file.
-    pub fn write_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
-        let mut fd = File::create(path).chain_err(|| "Unable to write image file")?;
-        fd.write_all(&self.data).chain_err(|| "Unable to write to image file")?;
-        Ok(())
-    }
 }
 
 /// It is possible to iterate over the sectors in the device, each element returning this.
@@ -203,17 +217,17 @@
 
 #[cfg(test)]
 mod test {
-    use super::{Flash, Error, ErrorKind, Result, Sector};
+    use super::{Flash, SimFlash, Error, ErrorKind, Result, Sector};
 
     #[test]
     fn test_flash() {
         // NXP-style, uniform sectors.
-        let mut f1 = Flash::new(vec![4096usize; 256]);
+        let mut f1 = SimFlash::new(vec![4096usize; 256], 1);
         test_device(&mut f1);
 
         // STM style, non-uniform sectors
-        let mut f2 = Flash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
-                                128 * 1024, 128 * 1024, 128 * 1024]);
+        let mut f2 = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
+                                128 * 1024, 128 * 1024, 128 * 1024], 1);
         test_device(&mut f2);
     }
 
diff --git a/sim/src/main.rs b/sim/src/main.rs
index 16400a3..af3a2d6 100644
--- a/sim/src/main.rs
+++ b/sim/src/main.rs
@@ -24,7 +24,7 @@
 mod pdump;
 mod caps;
 
-use flash::Flash;
+use flash::{Flash, SimFlash};
 use area::{AreaDesc, FlashId};
 use caps::Caps;
 
@@ -155,10 +155,10 @@
         let (mut flash, areadesc) = match device {
             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],
-                                       align as usize);
+                let flash = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024,
+                                          64 * 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);
@@ -167,7 +167,7 @@
             }
             DeviceName::K64f => {
                 // NXP style flash.  Small sectors, one small sector for scratch.
-                let flash = Flash::new(vec![4096; 128], align as usize);
+                let flash = SimFlash::new(vec![4096; 128], align as usize);
 
                 let mut areadesc = AreaDesc::new(&flash);
                 areadesc.add_image(0x020000, 0x020000, FlashId::Image0);
@@ -178,7 +178,7 @@
             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], align as usize);
+                let flash = SimFlash::new(vec![4096; 128], align as usize);
 
                 let mut areadesc = AreaDesc::new(&flash);
                 areadesc.add_simple_image(0x020000, 0x020000, FlashId::Image0);
@@ -189,7 +189,7 @@
             DeviceName::Nrf52840 => {
                 // Simulating the flash on the nrf52840 with partitions set up so that the scratch size
                 // does not divide into the image size.
-                let flash = Flash::new(vec![4096; 128], align as usize);
+                let flash = SimFlash::new(vec![4096; 128], align as usize);
 
                 let mut areadesc = AreaDesc::new(&flash);
                 areadesc.add_image(0x008000, 0x034000, FlashId::Image0);
@@ -270,7 +270,7 @@
 ///
 /// Returns the number of flash operations which can later be used to
 /// inject failures at chosen steps.
-fn run_basic_upgrade(flash: &Flash, areadesc: &AreaDesc, images: &Images)
+fn run_basic_upgrade(flash: &SimFlash, areadesc: &AreaDesc, images: &Images)
                      -> Result<i32, ()> {
     let (fl, total_count) = try_upgrade(&flash, &areadesc, &images, None);
     info!("Total flash operation count={}", total_count);
@@ -283,7 +283,7 @@
     }
 }
 
-fn run_basic_revert(flash: &Flash, areadesc: &AreaDesc, images: &Images) -> bool {
+fn run_basic_revert(flash: &SimFlash, areadesc: &AreaDesc, images: &Images) -> bool {
     let mut fails = 0;
 
     if Caps::SwapUpgrade.present() {
@@ -300,7 +300,7 @@
     fails > 0
 }
 
-fn run_perm_with_fails(flash: &Flash, areadesc: &AreaDesc, images: &Images,
+fn run_perm_with_fails(flash: &SimFlash, areadesc: &AreaDesc, images: &Images,
                        total_flash_ops: i32) -> bool {
     let mut fails = 0;
 
@@ -340,7 +340,7 @@
     fails > 0
 }
 
-fn run_perm_with_random_fails(flash: &Flash, areadesc: &AreaDesc,
+fn run_perm_with_random_fails(flash: &SimFlash, areadesc: &AreaDesc,
                               images: &Images, total_flash_ops: i32,
                               total_fails: usize) -> bool {
     let mut fails = 0;
@@ -374,7 +374,7 @@
     fails > 0
 }
 
-fn run_revert_with_fails(flash: &Flash, areadesc: &AreaDesc, images: &Images,
+fn run_revert_with_fails(flash: &SimFlash, areadesc: &AreaDesc, images: &Images,
                          total_count: i32) -> bool {
     let mut fails = 0;
 
@@ -390,7 +390,7 @@
     fails > 0
 }
 
-fn run_norevert(flash: &Flash, areadesc: &AreaDesc, images: &Images) -> bool {
+fn run_norevert(flash: &SimFlash, areadesc: &AreaDesc, images: &Images) -> bool {
     let mut fl = flash.clone();
     let mut fails = 0;
 
@@ -441,8 +441,8 @@
 
 /// Test a boot, optionally stopping after 'n' flash options.  Returns a count
 /// of the number of flash operations done total.
-fn try_upgrade(flash: &Flash, areadesc: &AreaDesc, images: &Images,
-               stop: Option<i32>) -> (Flash, i32) {
+fn try_upgrade(flash: &SimFlash, areadesc: &AreaDesc, images: &Images,
+               stop: Option<i32>) -> (SimFlash, i32) {
     // Clone the flash to have a new copy.
     let mut fl = flash.clone();
 
@@ -468,7 +468,7 @@
     (fl, count - c::get_flash_counter())
 }
 
-fn try_revert(flash: &Flash, areadesc: &AreaDesc, count: usize) -> Flash {
+fn try_revert(flash: &SimFlash, areadesc: &AreaDesc, count: usize) -> SimFlash {
     let mut fl = flash.clone();
     c::set_flash_counter(0);
 
@@ -480,7 +480,7 @@
     fl
 }
 
-fn try_revert_with_fail_at(flash: &Flash, areadesc: &AreaDesc, images: &Images,
+fn try_revert_with_fail_at(flash: &SimFlash, areadesc: &AreaDesc, images: &Images,
                            stop: i32) -> bool {
     let mut fl = flash.clone();
     let mut x: i32;
@@ -554,8 +554,8 @@
     fails > 0
 }
 
-fn try_random_fails(flash: &Flash, areadesc: &AreaDesc, images: &Images,
-                    total_ops: i32,  count: usize) -> (Flash, Vec<i32>) {
+fn try_random_fails(flash: &SimFlash, areadesc: &AreaDesc, images: &Images,
+                    total_ops: i32,  count: usize) -> (SimFlash, Vec<i32>) {
     let mut fl = flash.clone();
 
     mark_permanent_upgrade(&mut fl, &images.slot1);