Better output when flashing EC

This commit is contained in:
Jeremy Soller
2020-02-27 14:46:32 -07:00
parent 6ac21ace9c
commit 33cc2a2a76
2 changed files with 74 additions and 46 deletions

View File

@ -2,6 +2,7 @@ use ectool::{
Ec, Ec,
Error, Error,
Firmware, Firmware,
Spi,
SpiRom, SpiRom,
SpiTarget, SpiTarget,
Timeout, Timeout,
@ -74,9 +75,30 @@ unsafe fn console() -> Result<(), Error> {
} }
} }
unsafe fn flash_read<S: Spi>(spi: &mut SpiRom<S, StdTimeout>, rom: &mut [u8], sector_size: usize) -> Result<(), Error> {
let mut address = 0;
while address < rom.len() {
eprint!("\rSPI Read {}K", address / 1024);
let next_address = address + sector_size;
let count = spi.read_at(address as u32, &mut rom[address..next_address])?;
if count != sector_size {
eprintln!("\ncount {} did not match sector size {}", count, sector_size);
return Err(Error::Verify);
}
address = next_address;
}
eprintln!("\rSPI Read {}K", address / 1024);
Ok(())
}
unsafe fn flash_inner(ec: &mut Ec<StdTimeout>, firmware: &Firmware, target: SpiTarget, scratch: bool) -> Result<(), Error> { unsafe fn flash_inner(ec: &mut Ec<StdTimeout>, firmware: &Firmware, target: SpiTarget, scratch: bool) -> Result<(), Error> {
let rom_size = 128 * 1024; let rom_size = 128 * 1024;
let sector_size = 1024; let sector_size = 4096;
let mut new_rom = firmware.data.to_vec();
while new_rom.len() < rom_size {
new_rom.push(0xFF);
}
let mut spi_bus = ec.spi(target, scratch)?; let mut spi_bus = ec.spi(target, scratch)?;
let mut spi = SpiRom::new( let mut spi = SpiRom::new(
@ -84,10 +106,8 @@ unsafe fn flash_inner(ec: &mut Ec<StdTimeout>, firmware: &Firmware, target: SpiT
StdTimeout::new(Duration::new(1, 0)) StdTimeout::new(Duration::new(1, 0))
); );
// Read entire ROM let mut rom = vec![0xFF; rom_size];
let mut rom = vec![0; rom_size]; flash_read(&mut spi, &mut rom, sector_size)?;
eprintln!("SPI read");
spi.read_at(0, &mut rom)?;
eprintln!("Saving ROM to backup.rom"); eprintln!("Saving ROM to backup.rom");
fs::write("backup.rom", &rom).map_err(|_| Error::Verify)?; fs::write("backup.rom", &rom).map_err(|_| Error::Verify)?;
@ -105,59 +125,68 @@ unsafe fn flash_inner(ec: &mut Ec<StdTimeout>, firmware: &Firmware, target: SpiT
return Ok(()); return Ok(());
} }
// Erase entire chip, sector by sector
{ {
// Chip erase
// eprintln!("SPI chip erase");
// spi.erase_chip()?;
// Sector erase
let mut address = 0; let mut address = 0;
while address < rom_size { while address < rom_size {
eprint!("\rSPI Erase {}K", address / 1024);
let next_address = address + sector_size;
let mut erased = true; let mut erased = true;
for &b in &rom[address..address + sector_size] { for &b in &rom[address..next_address] {
if b != 0xFF { if b != 0xFF {
erased =false; erased =false;
break; break;
} }
} }
if ! erased {
spi.erase_sector(address as u32)?;
}
address = next_address;
}
eprintln!("\rSPI Erase {}K", address / 1024);
if erased { // Verify chip erase
eprintln!("SPI sector already erased {:06X}", address); flash_read(&mut spi, &mut rom, sector_size)?;
address += sector_size; for i in 0..rom.len() {
} else { if rom[i] != 0xFF {
eprintln!("SPI sector erase {:06X}", address); eprintln!("Failed to erase: {:X} is {:X} instead of {:X}", i, rom[i], 0xFF);
address += spi.erase_sector(address as u32)?; return Err(Error::Verify);
} }
} }
// Read entire ROM
eprintln!("SPI read");
spi.read_at(0, &mut rom)?;
} }
// Verify chip erase // Write entire chip, sector by sector
for i in 0..rom.len() { //TODO: write signature last
if rom[i] != 0xFF {
eprintln!("Failed to erase: {:X} is {:X} instead of {:X}", i, rom[i], 0xFF);
return Err(Error::Verify);
}
}
// Program
{ {
eprintln!("SPI AAI word program"); let mut address = 0;
spi.write_at(0, &firmware.data)?; while address < rom_size {
eprint!("\rSPI Write {}K", address / 1024);
let next_address = address + sector_size;
let mut erased = true;
for &b in &new_rom[address..next_address] {
if b != 0xFF {
erased =false;
break;
}
}
if ! erased {
let count = spi.write_at(address as u32, &new_rom[address..next_address])?;
if count != sector_size {
eprintln!("\nWrite count {} did not match sector size {}", count, sector_size);
return Err(Error::Verify);
}
}
address = next_address;
}
eprintln!("\rSPI Write {}K", address / 1024);
// Read entire ROM // Verify chip write
eprintln!("SPI read"); flash_read(&mut spi, &mut rom, sector_size)?;
spi.read_at(0, &mut rom)?; for i in 0..rom.len() {
} if rom[i] != new_rom[i] {
eprintln!("Failed to program: {:X} is {:X} instead of {:X}", i, rom[i], new_rom[i]);
// Verify program return Err(Error::Verify);
for i in 0..rom.len() { }
if &rom[i] != firmware.data.get(i).unwrap_or(&0xFF) {
eprintln!("Failed to program: {:X} is {:X} instead of {:X}", i, rom[i], firmware.data[i]);
return Err(Error::Verify);
} }
} }

View File

@ -81,7 +81,7 @@ impl<'a, S: Spi, T: Timeout> SpiRom<'a, S, T> {
Ok(()) Ok(())
} }
pub unsafe fn erase_sector(&mut self, address: u32) -> Result<usize, Error> { pub unsafe fn erase_sector(&mut self, address: u32) -> Result<(), Error> {
if (address & 0xFF00_0000) > 0 { if (address & 0xFF00_0000) > 0 {
return Err(Error::Parameter); return Err(Error::Parameter);
} }
@ -90,7 +90,7 @@ impl<'a, S: Spi, T: Timeout> SpiRom<'a, S, T> {
self.spi.reset()?; self.spi.reset()?;
self.spi.write(&[ self.spi.write(&[
0xD7, 0x20,
(address >> 16) as u8, (address >> 16) as u8,
(address >> 8) as u8, (address >> 8) as u8,
address as u8, address as u8,
@ -101,8 +101,7 @@ impl<'a, S: Spi, T: Timeout> SpiRom<'a, S, T> {
self.write_disable()?; self.write_disable()?;
//TODO: dynamically figure out this value Ok(())
Ok(1024)
} }
pub unsafe fn read_at(&mut self, address: u32, data: &mut [u8]) -> Result<usize, Error> { pub unsafe fn read_at(&mut self, address: u32, data: &mut [u8]) -> Result<usize, Error> {