Skip to content

Commit

Permalink
rfel: write address function; Version, Hexdump, Read32 and Write32 co…
Browse files Browse the repository at this point in the history
…mmands

Signed-off-by: Zhouqi Jiang <[email protected]>
  • Loading branch information
luojia65 committed Nov 7, 2024
1 parent ed0226c commit 75c03a3
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 29 deletions.
1 change: 1 addition & 0 deletions rfel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ clap-verbosity-flag = "2.2.2"
env_logger = "0.11.5"
futures = "0.3.31"
log = "0.4.22"
num-traits = "0.2.19"
nusb = "0.1.10"
69 changes: 46 additions & 23 deletions rfel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,35 +55,35 @@ impl<'a> Fel<'a> {
}

pub fn read_address(&self, address: u32, buf: &mut [u8]) -> usize {
trace!("read_address");
for chunk in buf.chunks_mut(CHUNK_SIZE) {
self.send_fel_request(FelRequest::write_raw(address, chunk.len() as u32));
self.send_fel_request(FelRequest::read_raw(address, chunk.len() as u32));
self.usb_read(chunk);
self.read_fel_status();
}
buf.len()
}

pub fn write_address(&self, address: u32, buf: &[u8]) -> usize {
trace!("write_address");
for chunk in buf.chunks(CHUNK_SIZE) {
self.send_fel_request(FelRequest::write_raw(address, chunk.len() as u32));
self.usb_write(chunk);
self.read_fel_status();
}
buf.len()
}

fn send_fel_request(&self, request: FelRequest) {
trace!("send_fel_request");
let buf: [u8; 36] = unsafe {
core::mem::transmute(UsbRequest::usb_write(
core::mem::size_of::<FelRequest>() as u32
))
};
block_on(self.iface.bulk_out(self.endpoint_out, buf.to_vec()))
.status
.expect("send_usb_request on send_fel_request transfer");
let buf: [u8; 16] = unsafe { core::mem::transmute(request) };
block_on(self.iface.bulk_out(self.endpoint_out, buf.to_vec()))
.status
.expect("usb bulk out on send_fel_request transfer");
let buf = nusb::transfer::RequestBuffer::new(13);
let ans = block_on(self.iface.bulk_in(self.endpoint_in, buf));
ans.status
.expect("read_usb_response on send_fel_request transfer");
if ans.data != *b"AWUS\0\0\0\0\0\0\0\0\0" {
panic!("invalid data received from read_usb_response")
}
self.usb_write(&buf);
}

fn read_fel_status(&self) {
trace!("read_fel_status");
let mut buf = [0u8; 8];
self.usb_read(&mut buf);
}

fn usb_read(&self, buf: &mut [u8]) {
Expand All @@ -107,10 +107,24 @@ impl<'a> Fel<'a> {
buf.copy_from_slice(&ans.data);
}

fn read_fel_status(&self) {
trace!("read_fel_status");
let mut buf = [0u8; 8];
self.usb_read(&mut buf);
fn usb_write(&self, buf: &[u8]) {
trace!("usb_write");
let buf_1: [u8; 36] =
unsafe { core::mem::transmute(UsbRequest::usb_write(buf.len() as u32)) };
block_on(self.iface.bulk_out(self.endpoint_out, buf_1.to_vec()))
.status
.expect("send_usb_request on usb_write transfer");
block_on(self.iface.bulk_out(self.endpoint_out, buf.to_vec()))
.status
.expect("usb bulk out on usb_write transfer");
let buf_3 = nusb::transfer::RequestBuffer::new(13);
let ans_1 = block_on(self.iface.bulk_in(self.endpoint_in, buf_3));
ans_1
.status
.expect("read_usb_response on usb_write transfer");
if ans_1.data != *b"AWUS\0\0\0\0\0\0\0\0\0" {
panic!("invalid data received from read_usb_response")
}
}
}

Expand Down Expand Up @@ -170,6 +184,15 @@ impl FelRequest {
}
}
#[inline]
pub const fn read_raw(address: u32, length: u32) -> Self {
FelRequest {
request: 0x103,
address,
length,
pad: 0,
}
}
#[inline]
pub const fn write_raw(address: u32, length: u32) -> Self {
FelRequest {
request: 0x101,
Expand Down
124 changes: 118 additions & 6 deletions rfel/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clap::Parser;
use clap::{Parser, Subcommand};
use clap_verbosity_flag::Verbosity;
use log::{debug, error};
use rfel::Fel;
Expand All @@ -9,6 +9,33 @@ use rfel::Fel;
struct Cli {
#[clap(flatten)]
verbose: Verbosity,
#[clap(subcommand)]
command: Commands,
}

#[derive(Debug, Subcommand)]
enum Commands {
/// Show chip version
Version,
/// Dumps memory region in hexadecimal format
Hexdump {
/// The address to be dumped
address: String,
/// Length of memory to be dumped
length: String,
},
/// Read a 32-bit value from chip memory
Read32 {
/// The address to be read
address: String,
},
/// Write a 32-bit value into chip memory
Write32 {
/// The address to be written
address: String,
/// The 32-bit value to be written
value: String,
},
}

/// USB vendor ID 0x1f3a: Allwinner Technology Co., Ltd.
Expand Down Expand Up @@ -37,9 +64,94 @@ fn main() {
let device = devices[0].open().expect("open USB device");
let mut interface = device.claim_interface(0).expect("open USB interface 0");
let fel = Fel::open_interface(&mut interface).expect("open usb interface as an FEL device");
let version = fel.get_version();
println!("{:x?}", version);
let mut buf = [0; 16];
fel.read_address(0x20000, &mut buf);
println!("{:x?}", buf);
match cli.command {
Commands::Version => {

Check warning on line 68 in rfel/src/main.rs

View workflow job for this annotation

GitHub Actions / Rustfmt all packages

Diff in /home/runner/work/allwinner-hal/allwinner-hal/rfel/src/main.rs
let version = fel.get_version();
println!("{:x?}", version);
},
Commands::Hexdump { address, length } => {
let address: usize = match parse_value(address.trim()) {
Some(address) => address,
None => {
println!("error: invalid address, shoule be hexadecimal like 0x40000000, or decimal like 1073741824");
return;
}
};
let length: usize = match parse_value(length.trim()) {
Some(address) => address,
None => {
println!("error: invalid data, shoule be hexadecimal like 0x40000000, or decimal like 1073741824");
return;
}
};
const CHUNK_SIZE: usize = 65536;
let mut buf = Vec::new();
buf.resize(CHUNK_SIZE, 0);
for offset in (0..length).step_by(CHUNK_SIZE) {
let chunk_len = (length - offset).min(CHUNK_SIZE);
fel.read_address((address + offset) as u32, &mut buf[..chunk_len]);
hexdump(&buf[..chunk_len], (address + offset) as u32);
}
}
Commands::Read32 { address } => {
let address: u32 = match parse_value(address.trim()) {
Some(address) => address,
None => {
println!("error: invalid address, shoule be hexadecimal like 0x40000000, or decimal like 1073741824");
return;
}
};
let mut buf = [0u8; 4];
fel.read_address(address, &mut buf);
let ans = u32::from_le_bytes(buf);
println!("0x{:08x}", ans);
}
Commands::Write32 { address, value } => {
let address: u32 = match parse_value(address.trim()) {
Some(address) => address,
None => {
println!("error: invalid address, shoule be hexadecimal like 0x40000000, or decimal like 1073741824");
return;
}
};
let value: u32 = match parse_value(value.trim()) {
Some(value) => value,
None => {
println!("error: invalid address, shoule be hexadecimal like 0x40000000, or decimal like 1073741824");
return;
}

Check warning on line 122 in rfel/src/main.rs

View workflow job for this annotation

GitHub Actions / Rustfmt all packages

Diff in /home/runner/work/allwinner-hal/allwinner-hal/rfel/src/main.rs
};
fel.write_address(address, &value.to_le_bytes());
},
}
}

fn hexdump(buf: &[u8], base_address: u32) {
for i in (0..buf.len()).step_by(16) {
print!("{:08x}: ", base_address as usize + i);
let chunk_len = 16.min(buf.len() - i);
for j in 0..chunk_len {
print!("{:02x} ", buf[i + j]);
}
print!(" ");
for _ in chunk_len..16 {
print!(" ");
}
for byte in &buf[i..(i + chunk_len)] {
if byte.is_ascii_graphic() || *byte == b' ' {
print!("{}", *byte as char);
} else {
print!(".");
}
}
println!()
}
}

fn parse_value<T: core::str::FromStr + num_traits::Num>(value: &str) -> Option<T> {
if value.starts_with("0x") {
T::from_str_radix(value.strip_prefix("0x").unwrap(), 16).ok()
} else {
value.parse::<T>().ok()
}
}

0 comments on commit 75c03a3

Please sign in to comment.