Add more subcommands to tool

This commit is contained in:
Jeremy Soller 2020-02-24 13:42:00 -07:00
parent d511a57bff
commit 8d0bab01f7
No known key found for this signature in database
GPG Key ID: E988B49EE78A7FB1
3 changed files with 203 additions and 18 deletions

68
tool/src/legacy.rs Normal file
View File

@ -0,0 +1,68 @@
use crate::{
Error,
Pmc,
SuperIo,
Timeout,
};
pub struct EcLegacy<T: Timeout> {
pub pmc: Pmc<T>,
}
impl<T: Timeout> EcLegacy<T> {
/// Probes for a compatible EC
pub unsafe fn new(primary: bool, timeout: T) -> Result<Self, Error> {
let mut sio = SuperIo::new(if primary { 0x2E } else { 0x4E });
let id =
(sio.read(0x20) as u16) << 8 |
(sio.read(0x21) as u16);
match id {
0x5570 | 0x8587 => (),
_ => return Err(Error::SuperIoId(id)),
}
//TODO: is there a good way to probe?
Ok(Self {
pmc: Pmc::new(if primary { 0x62 } else { 0x68 }, timeout),
})
}
pub unsafe fn project(&mut self, data: &mut [u8]) -> Result<usize, Error> {
let mut i = 0;
self.pmc.command(0x92)?;
while i < data.len() {
data[i] = self.pmc.read()?;
if data[i] == b'$' {
break;
}
i += 1;
}
Ok(i)
}
pub unsafe fn version(&mut self, data: &mut [u8]) -> Result<usize, Error> {
// Prepend `1.` to version string
let mut i = 0;
if i < data.len() {
data[i] = b'1';
i += 1;
}
if i < data.len() {
data[i] = b'.';
i += 1;
}
self.pmc.command(0x93)?;
while i < data.len() {
data[i] = self.pmc.read()?;
if data[i] == b'$' {
break;
}
i += 1;
}
Ok(i)
}
}

View File

@ -9,6 +9,9 @@ mod error;
pub use self::firmware::Firmware;
mod firmware;
pub use self::legacy::EcLegacy;
mod legacy;
pub use self::pmc::Pmc;
mod pmc;

View File

@ -1,12 +1,17 @@
use ectool::{
Ec,
Error,
Firmware,
Timeout,
};
use std::{
env,
fs,
io,
process,
str,
time::{Duration, Instant},
thread,
};
pub struct StdTimeout {
@ -33,7 +38,82 @@ impl Timeout for StdTimeout {
}
}
unsafe fn tool() -> Result<(), Error> {
unsafe fn iopl() {
extern {
fn iopl(level: isize) -> isize;
}
if iopl(3) < 0 {
eprintln!("failed to get I/O permission: {}", io::Error::last_os_error());
process::exit(1);
}
}
unsafe fn console() -> Result<(), Error> {
iopl();
let mut ec = Ec::new(
true,
StdTimeout::new(Duration::new(1, 0)),
)?;
let mut head = ec.debug(0) as usize;
loop {
let tail = ec.debug(0) as usize;
if tail == 0 || head == tail {
thread::sleep(Duration::from_millis(1));
} else {
while head != tail {
head += 1;
if head >= 256 { head = 1; }
let c = ec.debug(head as u8);
print!("{}", c as char);
}
}
}
}
unsafe fn flash(path: &str) -> Result<(), Error> {
//TODO: remove unwraps
let firmware_data = fs::read(path).unwrap();
let firmware = Firmware::new(&firmware_data).unwrap();
println!("file board: {:?}", str::from_utf8(firmware.board));
println!("file version: {:?}", str::from_utf8(firmware.version));
iopl();
let mut ec = Ec::new(
true,
StdTimeout::new(Duration::new(1, 0)),
)?;
{
let mut data = [0; 256];
let size = ec.board(&mut data)?;
let ec_board = &data[..size];
println!("ec board: {:?}", str::from_utf8(ec_board));
if ec_board != firmware.board {
panic!("file board does not match ec board");
}
}
{
print!("ec version: ");
let mut data = [0; 256];
let size = ec.version(&mut data)?;
let ec_version = &data[..size];
println!("ec version: {:?}", str::from_utf8(ec_version));
}
Ok(())
}
unsafe fn info() -> Result<(), Error> {
iopl();
let mut ec = Ec::new(
true,
StdTimeout::new(Duration::new(1, 0)),
@ -62,21 +142,55 @@ unsafe fn tool() -> Result<(), Error> {
Ok(())
}
fn main() {
extern {
fn iopl(level: isize) -> isize;
}
if unsafe { iopl(3) < 0 } {
eprintln!("failed to get I/O permission: {}", io::Error::last_os_error());
process::exit(1);
}
match unsafe { tool() } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to run tool: {:X?}", err);
process::exit(1);
}
}
fn usage() {
eprintln!(" console");
eprintln!(" flash [file]");
eprintln!(" info");
}
fn main() {
let mut args = env::args().skip(1);
match args.next() {
Some(arg) => match arg.as_str() {
"console" => match unsafe { console() } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to read console: {:X?}", err);
process::exit(1);
},
},
"flash" => match args.next() {
Some(path) => match unsafe { flash(&path) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to flash '{}': {:X?}", path, err);
process::exit(1);
},
},
None => {
eprintln!("no file provided");
process::exit(1);
}
},
"info" => match unsafe { info() } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to read info: {:X?}", err);
process::exit(1);
},
},
_ => {
eprintln!("unknown subcommand '{}'", arg);
usage();
process::exit(1);
},
},
None => {
eprintln!("no subcommand provided");
usage();
process::exit(1);
},
}
}