Add ability to flash backup rom

This commit is contained in:
Jeremy Soller
2020-02-26 13:43:31 -07:00
parent 1e1c626d71
commit 68b9acd249
8 changed files with 71 additions and 26 deletions

View File

@ -82,8 +82,12 @@ static enum Result cmd_spi(void) {
#ifdef __SCRATCH__ #ifdef __SCRATCH__
uint8_t len = smfi_cmd[3]; uint8_t len = smfi_cmd[3];
// Enable chip (internal) // Enable chip
ECINDAR3 = 0x7F; if (flags & CMD_SPI_FLAG_BACKUP) {
ECINDAR3 = 0xFF;
} else {
ECINDAR3 = 0x7F;
}
ECINDAR2 = 0xFF; ECINDAR2 = 0xFF;
ECINDAR1 = 0xFD; ECINDAR1 = 0xFD;
ECINDAR0 = 0x00; ECINDAR0 = 0x00;

View File

@ -82,8 +82,12 @@ static enum Result cmd_spi(void) {
#ifdef __SCRATCH__ #ifdef __SCRATCH__
uint8_t len = smfi_cmd[3]; uint8_t len = smfi_cmd[3];
// Enable chip (internal) // Enable chip
ECINDAR3 = 0x7F; if (flags & CMD_SPI_FLAG_BACKUP) {
ECINDAR3 = 0xFF;
} else {
ECINDAR3 = 0x7F;
}
ECINDAR2 = 0xFF; ECINDAR2 = 0xFF;
ECINDAR1 = 0xFD; ECINDAR1 = 0xFD;
ECINDAR0 = 0x00; ECINDAR0 = 0x00;

View File

@ -82,8 +82,12 @@ static enum Result cmd_spi(void) {
#ifdef __SCRATCH__ #ifdef __SCRATCH__
uint8_t len = smfi_cmd[3]; uint8_t len = smfi_cmd[3];
// Enable chip (internal) // Enable chip
ECINDAR3 = 0x7F; if (flags & CMD_SPI_FLAG_BACKUP) {
ECINDAR3 = 0xFF;
} else {
ECINDAR3 = 0x7F;
}
ECINDAR2 = 0xFF; ECINDAR2 = 0xFF;
ECINDAR1 = 0xFD; ECINDAR1 = 0xFD;
ECINDAR0 = 0x00; ECINDAR0 = 0x00;

View File

@ -34,6 +34,8 @@ enum CommandSpiFlag {
CMD_SPI_FLAG_DISABLE = (1 << 1), CMD_SPI_FLAG_DISABLE = (1 << 1),
// Run firmware from scratch RAM if necessary // Run firmware from scratch RAM if necessary
CMD_SPI_FLAG_SCRATCH = (1 << 2), CMD_SPI_FLAG_SCRATCH = (1 << 2),
// Write to backup ROM instead
CMD_SPI_FLAG_BACKUP = (1 << 3),
}; };
#endif // _COMMON_COMMAND_H #endif // _COMMON_COMMAND_H

View File

@ -3,6 +3,7 @@ use hwio::{Io, Pio};
use crate::{ use crate::{
Error, Error,
Spi, Spi,
SpiTarget,
SuperIo, SuperIo,
Timeout, Timeout,
timeout timeout
@ -23,6 +24,7 @@ pub enum Cmd {
pub const CMD_SPI_FLAG_READ: u8 = (1 << 0); pub const CMD_SPI_FLAG_READ: u8 = (1 << 0);
pub const CMD_SPI_FLAG_DISABLE: u8 = (1 << 1); pub const CMD_SPI_FLAG_DISABLE: u8 = (1 << 1);
pub const CMD_SPI_FLAG_SCRATCH: u8 = (1 << 2); pub const CMD_SPI_FLAG_SCRATCH: u8 = (1 << 2);
pub const CMD_SPI_FLAG_BACKUP: u8 = (1 << 3);
pub struct Ec<T: Timeout> { pub struct Ec<T: Timeout> {
cmd: u16, cmd: u16,
@ -149,9 +151,10 @@ impl<T: Timeout> Ec<T> {
Ok(i) 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 { let mut spi = EcSpi {
ec: self, ec: self,
target,
scratch, scratch,
}; };
spi.reset()?; spi.reset()?;
@ -165,49 +168,71 @@ impl<T: Timeout> Ec<T> {
pub struct EcSpi<'a, T: Timeout> { pub struct EcSpi<'a, T: Timeout> {
ec: &'a mut Ec<T>, ec: &'a mut Ec<T>,
target: SpiTarget,
scratch: bool, 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> { impl<'a, T: Timeout> Spi for EcSpi<'a, T> {
/// Disable SPI chip, must be done before and after a transaction /// Disable SPI chip, must be done before and after a transaction
unsafe fn reset(&mut self) -> Result<(), Error> { unsafe fn reset(&mut self) -> Result<(), Error> {
let flags = let flags = self.flags(false, true);
CMD_SPI_FLAG_DISABLE |
if self.scratch { CMD_SPI_FLAG_SCRATCH } else { 0 };
self.ec.write(2, flags); self.ec.write(2, flags);
self.ec.write(3, 0); self.ec.write(3, 0);
self.ec.command(Cmd::Spi)?; self.ec.command(Cmd::Spi)?;
assert_eq!(self.ec.read(3), 0); if self.ec.read(3) != 0 {
return Err(Error::Verify);
}
Ok(()) Ok(())
} }
/// SPI read /// SPI read
unsafe fn read(&mut self, data: &mut [u8]) -> Result<usize, Error> { unsafe fn read(&mut self, data: &mut [u8]) -> Result<usize, Error> {
let flags = let flags = self.flags(true, false);
CMD_SPI_FLAG_READ |
if self.scratch { CMD_SPI_FLAG_SCRATCH } else { 0 };
for chunk in data.chunks_mut(256 - 4) { for chunk in data.chunks_mut(256 - 4) {
self.ec.write(2, flags); self.ec.write(2, flags);
self.ec.write(3, chunk.len() as u8); self.ec.write(3, chunk.len() as u8);
self.ec.command(Cmd::Spi)?; 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() { for i in 0..chunk.len() {
chunk[i] = self.ec.read(i as u8 + 4); chunk[i] = self.ec.read(i as u8 + 4);
} }
} }
Ok(data.len()) Ok(data.len())
} }
/// SPI write /// SPI write
unsafe fn write(&mut self, data: &[u8]) -> Result<usize, Error> { unsafe fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
let flags = let flags = self.flags(false, false);
if self.scratch { CMD_SPI_FLAG_SCRATCH } else { 0 };
for chunk in data.chunks(256 - 4) { for chunk in data.chunks(256 - 4) {
for i in 0..chunk.len() { for i in 0..chunk.len() {
self.ec.write(i as u8 + 4, chunk[i]); 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(2, flags);
self.ec.write(3, chunk.len() as u8); self.ec.write(3, chunk.len() as u8);
self.ec.command(Cmd::Spi)?; 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()) Ok(data.len())
} }
} }

View File

@ -15,7 +15,7 @@ mod legacy;
pub use self::pmc::Pmc; pub use self::pmc::Pmc;
mod pmc; mod pmc;
pub use self::spi::{Spi, SpiRom}; pub use self::spi::{Spi, SpiRom, SpiTarget};
mod spi; mod spi;
pub use self::super_io::SuperIo; pub use self::super_io::SuperIo;

View File

@ -3,6 +3,7 @@ use ectool::{
Error, Error,
Firmware, Firmware,
SpiRom, SpiRom,
SpiTarget,
Timeout, Timeout,
}; };
use std::{ use std::{
@ -77,7 +78,7 @@ unsafe fn flash_inner(ec: &mut Ec<StdTimeout>, firmware: &Firmware) -> Result<()
let rom_size = 128 * 1024; let rom_size = 128 * 1024;
let sector_size = 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( let mut spi = SpiRom::new(
&mut spi_bus, &mut spi_bus,
StdTimeout::new(Duration::new(1, 0)) StdTimeout::new(Duration::new(1, 0))

View File

@ -9,6 +9,10 @@ pub trait Spi {
unsafe fn write(&mut self, data: &[u8]) -> Result<usize, Error>; unsafe fn write(&mut self, data: &[u8]) -> Result<usize, Error>;
} }
pub enum SpiTarget {
Main,
Backup,
}
pub struct SpiRom<'a, S: Spi, T: Timeout> { pub struct SpiRom<'a, S: Spi, T: Timeout> {
spi: &'a mut S, spi: &'a mut S,