Add ability to flash backup rom
This commit is contained in:
@ -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
|
||||||
|
if (flags & CMD_SPI_FLAG_BACKUP) {
|
||||||
|
ECINDAR3 = 0xFF;
|
||||||
|
} else {
|
||||||
ECINDAR3 = 0x7F;
|
ECINDAR3 = 0x7F;
|
||||||
|
}
|
||||||
ECINDAR2 = 0xFF;
|
ECINDAR2 = 0xFF;
|
||||||
ECINDAR1 = 0xFD;
|
ECINDAR1 = 0xFD;
|
||||||
ECINDAR0 = 0x00;
|
ECINDAR0 = 0x00;
|
||||||
|
@ -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
|
||||||
|
if (flags & CMD_SPI_FLAG_BACKUP) {
|
||||||
|
ECINDAR3 = 0xFF;
|
||||||
|
} else {
|
||||||
ECINDAR3 = 0x7F;
|
ECINDAR3 = 0x7F;
|
||||||
|
}
|
||||||
ECINDAR2 = 0xFF;
|
ECINDAR2 = 0xFF;
|
||||||
ECINDAR1 = 0xFD;
|
ECINDAR1 = 0xFD;
|
||||||
ECINDAR0 = 0x00;
|
ECINDAR0 = 0x00;
|
||||||
|
@ -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
|
||||||
|
if (flags & CMD_SPI_FLAG_BACKUP) {
|
||||||
|
ECINDAR3 = 0xFF;
|
||||||
|
} else {
|
||||||
ECINDAR3 = 0x7F;
|
ECINDAR3 = 0x7F;
|
||||||
|
}
|
||||||
ECINDAR2 = 0xFF;
|
ECINDAR2 = 0xFF;
|
||||||
ECINDAR1 = 0xFD;
|
ECINDAR1 = 0xFD;
|
||||||
ECINDAR0 = 0x00;
|
ECINDAR0 = 0x00;
|
||||||
|
@ -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
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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))
|
||||||
|
@ -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,
|
||||||
|
Reference in New Issue
Block a user