Add ability to flash backup rom
This commit is contained in:
		@@ -82,8 +82,12 @@ static enum Result cmd_spi(void) {
 | 
			
		||||
#ifdef __SCRATCH__
 | 
			
		||||
    uint8_t len = smfi_cmd[3];
 | 
			
		||||
 | 
			
		||||
    // Enable chip (internal)
 | 
			
		||||
    ECINDAR3 = 0x7F;
 | 
			
		||||
    // Enable chip
 | 
			
		||||
    if (flags & CMD_SPI_FLAG_BACKUP) {
 | 
			
		||||
        ECINDAR3 = 0xFF;
 | 
			
		||||
    } else {
 | 
			
		||||
        ECINDAR3 = 0x7F;
 | 
			
		||||
    }
 | 
			
		||||
    ECINDAR2 = 0xFF;
 | 
			
		||||
    ECINDAR1 = 0xFD;
 | 
			
		||||
    ECINDAR0 = 0x00;
 | 
			
		||||
 
 | 
			
		||||
@@ -82,8 +82,12 @@ static enum Result cmd_spi(void) {
 | 
			
		||||
#ifdef __SCRATCH__
 | 
			
		||||
    uint8_t len = smfi_cmd[3];
 | 
			
		||||
 | 
			
		||||
    // Enable chip (internal)
 | 
			
		||||
    ECINDAR3 = 0x7F;
 | 
			
		||||
    // Enable chip
 | 
			
		||||
    if (flags & CMD_SPI_FLAG_BACKUP) {
 | 
			
		||||
        ECINDAR3 = 0xFF;
 | 
			
		||||
    } else {
 | 
			
		||||
        ECINDAR3 = 0x7F;
 | 
			
		||||
    }
 | 
			
		||||
    ECINDAR2 = 0xFF;
 | 
			
		||||
    ECINDAR1 = 0xFD;
 | 
			
		||||
    ECINDAR0 = 0x00;
 | 
			
		||||
 
 | 
			
		||||
@@ -82,8 +82,12 @@ static enum Result cmd_spi(void) {
 | 
			
		||||
#ifdef __SCRATCH__
 | 
			
		||||
    uint8_t len = smfi_cmd[3];
 | 
			
		||||
 | 
			
		||||
    // Enable chip (internal)
 | 
			
		||||
    ECINDAR3 = 0x7F;
 | 
			
		||||
    // Enable chip
 | 
			
		||||
    if (flags & CMD_SPI_FLAG_BACKUP) {
 | 
			
		||||
        ECINDAR3 = 0xFF;
 | 
			
		||||
    } else {
 | 
			
		||||
        ECINDAR3 = 0x7F;
 | 
			
		||||
    }
 | 
			
		||||
    ECINDAR2 = 0xFF;
 | 
			
		||||
    ECINDAR1 = 0xFD;
 | 
			
		||||
    ECINDAR0 = 0x00;
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,8 @@ enum CommandSpiFlag {
 | 
			
		||||
    CMD_SPI_FLAG_DISABLE = (1 << 1),
 | 
			
		||||
    // Run firmware from scratch RAM if necessary
 | 
			
		||||
    CMD_SPI_FLAG_SCRATCH = (1 << 2),
 | 
			
		||||
    // Write to backup ROM instead
 | 
			
		||||
    CMD_SPI_FLAG_BACKUP = (1 << 3),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // _COMMON_COMMAND_H
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ use hwio::{Io, Pio};
 | 
			
		||||
use crate::{
 | 
			
		||||
    Error,
 | 
			
		||||
    Spi,
 | 
			
		||||
    SpiTarget,
 | 
			
		||||
    SuperIo,
 | 
			
		||||
    Timeout,
 | 
			
		||||
    timeout
 | 
			
		||||
@@ -23,6 +24,7 @@ pub enum Cmd {
 | 
			
		||||
pub const CMD_SPI_FLAG_READ: u8 = (1 << 0);
 | 
			
		||||
pub const CMD_SPI_FLAG_DISABLE: u8 = (1 << 1);
 | 
			
		||||
pub const CMD_SPI_FLAG_SCRATCH: u8 = (1 << 2);
 | 
			
		||||
pub const CMD_SPI_FLAG_BACKUP: u8 = (1 << 3);
 | 
			
		||||
 | 
			
		||||
pub struct Ec<T: Timeout> {
 | 
			
		||||
    cmd: u16,
 | 
			
		||||
@@ -149,9 +151,10 @@ impl<T: Timeout> Ec<T> {
 | 
			
		||||
        Ok(i)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub unsafe fn spi(&mut self, scratch: bool) -> Result<EcSpi<T>, Error> {
 | 
			
		||||
    pub unsafe fn spi(&mut self, target: SpiTarget, scratch: bool) -> Result<EcSpi<T>, Error> {
 | 
			
		||||
        let mut spi = EcSpi {
 | 
			
		||||
            ec: self,
 | 
			
		||||
            target,
 | 
			
		||||
            scratch,
 | 
			
		||||
        };
 | 
			
		||||
        spi.reset()?;
 | 
			
		||||
@@ -165,49 +168,71 @@ impl<T: Timeout> Ec<T> {
 | 
			
		||||
 | 
			
		||||
pub struct EcSpi<'a, T: Timeout> {
 | 
			
		||||
    ec: &'a mut Ec<T>,
 | 
			
		||||
    target: SpiTarget,
 | 
			
		||||
    scratch: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a, T: Timeout> EcSpi<'a, T> {
 | 
			
		||||
    fn flags(&self, read: bool, disable: bool) -> u8 {
 | 
			
		||||
        let mut flags = 0;
 | 
			
		||||
 | 
			
		||||
        if read {
 | 
			
		||||
            flags |= CMD_SPI_FLAG_READ;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if disable {
 | 
			
		||||
            flags |= CMD_SPI_FLAG_DISABLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if self.scratch {
 | 
			
		||||
            flags |= CMD_SPI_FLAG_SCRATCH;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        match self.target {
 | 
			
		||||
            SpiTarget::Main => (),
 | 
			
		||||
            SpiTarget::Backup => {
 | 
			
		||||
                flags |= CMD_SPI_FLAG_BACKUP;
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        flags
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a, T: Timeout> Spi for EcSpi<'a, T> {
 | 
			
		||||
    /// Disable SPI chip, must be done before and after a transaction
 | 
			
		||||
    unsafe fn reset(&mut self) -> Result<(), Error> {
 | 
			
		||||
        let flags =
 | 
			
		||||
            CMD_SPI_FLAG_DISABLE |
 | 
			
		||||
            if self.scratch { CMD_SPI_FLAG_SCRATCH } else { 0 };
 | 
			
		||||
 | 
			
		||||
        let flags = self.flags(false, true);
 | 
			
		||||
        self.ec.write(2, flags);
 | 
			
		||||
        self.ec.write(3, 0);
 | 
			
		||||
        self.ec.command(Cmd::Spi)?;
 | 
			
		||||
        assert_eq!(self.ec.read(3), 0);
 | 
			
		||||
 | 
			
		||||
        if self.ec.read(3) != 0 {
 | 
			
		||||
            return Err(Error::Verify);
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// SPI read
 | 
			
		||||
    unsafe fn read(&mut self, data: &mut [u8]) -> Result<usize, Error> {
 | 
			
		||||
        let flags =
 | 
			
		||||
            CMD_SPI_FLAG_READ |
 | 
			
		||||
            if self.scratch { CMD_SPI_FLAG_SCRATCH } else { 0 };
 | 
			
		||||
 | 
			
		||||
        let flags = self.flags(true, false);
 | 
			
		||||
        for chunk in data.chunks_mut(256 - 4) {
 | 
			
		||||
            self.ec.write(2, flags);
 | 
			
		||||
            self.ec.write(3, chunk.len() as u8);
 | 
			
		||||
            self.ec.command(Cmd::Spi)?;
 | 
			
		||||
            assert_eq!(self.ec.read(3), chunk.len() as u8);
 | 
			
		||||
            if self.ec.read(3) != chunk.len() as u8 {
 | 
			
		||||
                return Err(Error::Verify);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for i in 0..chunk.len() {
 | 
			
		||||
                chunk[i] = self.ec.read(i as u8 + 4);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(data.len())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// SPI write
 | 
			
		||||
    unsafe fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
 | 
			
		||||
        let flags =
 | 
			
		||||
            if self.scratch { CMD_SPI_FLAG_SCRATCH } else { 0 };
 | 
			
		||||
 | 
			
		||||
        let flags = self.flags(false, false);
 | 
			
		||||
        for chunk in data.chunks(256 - 4) {
 | 
			
		||||
            for i in 0..chunk.len() {
 | 
			
		||||
                self.ec.write(i as u8 + 4, chunk[i]);
 | 
			
		||||
@@ -216,9 +241,10 @@ impl<'a, T: Timeout> Spi for EcSpi<'a, T> {
 | 
			
		||||
            self.ec.write(2, flags);
 | 
			
		||||
            self.ec.write(3, chunk.len() as u8);
 | 
			
		||||
            self.ec.command(Cmd::Spi)?;
 | 
			
		||||
            assert_eq!(self.ec.read(3), chunk.len() as u8);
 | 
			
		||||
            if self.ec.read(3) != chunk.len() as u8 {
 | 
			
		||||
                return Err(Error::Verify);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(data.len())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ mod legacy;
 | 
			
		||||
pub use self::pmc::Pmc;
 | 
			
		||||
mod pmc;
 | 
			
		||||
 | 
			
		||||
pub use self::spi::{Spi, SpiRom};
 | 
			
		||||
pub use self::spi::{Spi, SpiRom, SpiTarget};
 | 
			
		||||
mod spi;
 | 
			
		||||
 | 
			
		||||
pub use self::super_io::SuperIo;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ use ectool::{
 | 
			
		||||
    Error,
 | 
			
		||||
    Firmware,
 | 
			
		||||
    SpiRom,
 | 
			
		||||
    SpiTarget,
 | 
			
		||||
    Timeout,
 | 
			
		||||
};
 | 
			
		||||
use std::{
 | 
			
		||||
@@ -77,7 +78,7 @@ unsafe fn flash_inner(ec: &mut Ec<StdTimeout>, firmware: &Firmware) -> Result<()
 | 
			
		||||
    let rom_size = 128 * 1024;
 | 
			
		||||
    let sector_size = 1024;
 | 
			
		||||
 | 
			
		||||
    let mut spi_bus = ec.spi(true)?;
 | 
			
		||||
    let mut spi_bus = ec.spi(SpiTarget::Main, true)?;
 | 
			
		||||
    let mut spi = SpiRom::new(
 | 
			
		||||
        &mut spi_bus,
 | 
			
		||||
        StdTimeout::new(Duration::new(1, 0))
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,10 @@ pub trait Spi {
 | 
			
		||||
    unsafe fn write(&mut self, data: &[u8]) -> Result<usize, Error>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum SpiTarget {
 | 
			
		||||
    Main,
 | 
			
		||||
    Backup,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct SpiRom<'a, S: Spi, T: Timeout> {
 | 
			
		||||
    spi: &'a mut S,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user