mirror of
https://github.com/spacemeowx2/blflash.git
synced 2024-10-04 05:39:47 +00:00
feat: add partition bin
This commit is contained in:
parent
fa1865987e
commit
004fdf12bc
23
Cargo.lock
generated
23
Cargo.lock
generated
@ -87,9 +87,11 @@ name = "blflash"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"crc",
|
||||||
"deku",
|
"deku",
|
||||||
"directories-next",
|
"directories-next",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"hex",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
"log",
|
"log",
|
||||||
"main_error",
|
"main_error",
|
||||||
@ -112,6 +114,12 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "build_const"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.3.4"
|
version = "1.3.4"
|
||||||
@ -193,6 +201,15 @@ version = "0.1.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
|
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||||
|
dependencies = [
|
||||||
|
"build_const",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
@ -384,6 +401,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
|
@ -26,3 +26,5 @@ byteorder = "1.3.4"
|
|||||||
sha2 = "0.9.2"
|
sha2 = "0.9.2"
|
||||||
structopt = { version = "0.3.21", features = ["paw"] }
|
structopt = { version = "0.3.21", features = ["paw"] }
|
||||||
paw = "1.0.0"
|
paw = "1.0.0"
|
||||||
|
crc = "1.8.1"
|
||||||
|
hex = "0.4.2"
|
||||||
|
94
blflash/src/chip/bl602/cfg/partition_cfg_2M.toml
Normal file
94
blflash/src/chip/bl602/cfg/partition_cfg_2M.toml
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
[pt_table]
|
||||||
|
#partition table is 4K in size
|
||||||
|
address0 = 0xE000
|
||||||
|
address1 = 0xF000
|
||||||
|
|
||||||
|
[[pt_entry]]
|
||||||
|
type = 0
|
||||||
|
name = "FW"
|
||||||
|
device = 0
|
||||||
|
address0 = 0x10000
|
||||||
|
size0 = 0xC8000
|
||||||
|
address1 = 0xD8000
|
||||||
|
size1 = 0x88000
|
||||||
|
# compressed image must set len,normal image can left it to 0
|
||||||
|
len = 0
|
||||||
|
|
||||||
|
[[pt_entry]]
|
||||||
|
type = 2
|
||||||
|
name = "mfg"
|
||||||
|
device = 0
|
||||||
|
address0 = 0x160000
|
||||||
|
size0 = 0x32000
|
||||||
|
address1 = 0
|
||||||
|
size1 = 0
|
||||||
|
# compressed image must set len,normal image can left it to 0
|
||||||
|
len = 0
|
||||||
|
|
||||||
|
[[pt_entry]]
|
||||||
|
type = 3
|
||||||
|
name = "media"
|
||||||
|
device = 0
|
||||||
|
address0 = 0x192000
|
||||||
|
size0 = 0x57000
|
||||||
|
address1 = 0
|
||||||
|
size1 = 0
|
||||||
|
# compressed image must set len,normal image can left it to 0
|
||||||
|
len = 0
|
||||||
|
|
||||||
|
[[pt_entry]]
|
||||||
|
type = 4
|
||||||
|
name = "PSM"
|
||||||
|
device = 0
|
||||||
|
address0 = 0x1E9000
|
||||||
|
size0 = 0x8000
|
||||||
|
address1 = 0
|
||||||
|
size1 = 0
|
||||||
|
# compressed image must set len,normal image can left it to 0
|
||||||
|
len = 0
|
||||||
|
|
||||||
|
[[pt_entry]]
|
||||||
|
type = 5
|
||||||
|
name = "KEY"
|
||||||
|
device = 0
|
||||||
|
address0 = 0x1F1000
|
||||||
|
size0 = 0x2000
|
||||||
|
address1 = 0
|
||||||
|
size1 = 0
|
||||||
|
# compressed image must set len,normal image can left it to 0
|
||||||
|
len = 0
|
||||||
|
|
||||||
|
[[pt_entry]]
|
||||||
|
type = 6
|
||||||
|
name = "DATA"
|
||||||
|
device = 0
|
||||||
|
address0 = 0x1F3000
|
||||||
|
size0 = 0x5000
|
||||||
|
address1 = 0
|
||||||
|
size1 = 0
|
||||||
|
# compressed image must set len,normal image can left it to 0
|
||||||
|
len = 0
|
||||||
|
|
||||||
|
|
||||||
|
[[pt_entry]]
|
||||||
|
type = 7
|
||||||
|
name = "factory"
|
||||||
|
device = 0
|
||||||
|
address0 = 0x1F8000
|
||||||
|
size0 = 0x7000
|
||||||
|
address1 = 0
|
||||||
|
size1 = 0
|
||||||
|
# compressed image must set len,normal image can left it to 0
|
||||||
|
len = 0
|
||||||
|
|
||||||
|
#if user want to put RF calibration data on flash, uncomment following pt entry
|
||||||
|
#[[pt_entry]]
|
||||||
|
#type = 8
|
||||||
|
#name = "rf_para"
|
||||||
|
#device = 0
|
||||||
|
#address0 = 0x1FF000
|
||||||
|
#size0 = 0x1000
|
||||||
|
#address1 = 0
|
||||||
|
#size1 = 0
|
||||||
|
## compressed image must set len,normal image can left it to 0
|
||||||
|
#len = 0
|
BIN
blflash/src/chip/bl602/image/boot2image.bin
Normal file
BIN
blflash/src/chip/bl602/image/boot2image.bin
Normal file
Binary file not shown.
@ -1,16 +1,38 @@
|
|||||||
use super::{Chip, CodeSegment, FlashSegment};
|
use super::{Chip, CodeSegment, FlashSegment};
|
||||||
|
use crate::{Error, image::PartitionCfg};
|
||||||
|
use deku::prelude::*;
|
||||||
|
|
||||||
const EFLASH_LOADER: &'static [u8] = include_bytes!("image/eflash_loader_40m.bin");
|
pub const DEFAULT_PARTITION_CFG: &'static [u8] = include_bytes!("cfg/partition_cfg_2M.toml");
|
||||||
|
pub const BOOT2IMAGE: &'static [u8] = include_bytes!("image/boot2image.bin");
|
||||||
|
pub const EFLASH_LOADER: &'static [u8] = include_bytes!("image/eflash_loader_40m.bin");
|
||||||
const ROM_START: u32 = 0x23000000;
|
const ROM_START: u32 = 0x23000000;
|
||||||
// 16MB
|
// 16MB
|
||||||
const ROM_END: u32 = 0x23000000 + 0x1000000;
|
const ROM_END: u32 = 0x23000000 + 0x1000000;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
pub struct Bl602;
|
pub struct Bl602;
|
||||||
|
|
||||||
impl Bl602 {
|
impl Bl602 {
|
||||||
fn addr_is_flash(&self, addr: u32) -> bool {
|
fn addr_is_flash(&self, addr: u32) -> bool {
|
||||||
addr >= ROM_START && addr < ROM_END
|
addr >= ROM_START && addr < ROM_END
|
||||||
}
|
}
|
||||||
|
pub fn with_boot2(
|
||||||
|
&self,
|
||||||
|
mut partition_cfg: PartitionCfg,
|
||||||
|
bin: &[u8],
|
||||||
|
) -> Result<Vec<FlashSegment>, Error> {
|
||||||
|
partition_cfg.update()?;
|
||||||
|
let partition_cfg = partition_cfg.to_bytes()?;
|
||||||
|
|
||||||
|
let segments = vec![
|
||||||
|
CodeSegment::from_slice(0x0, &BOOT2IMAGE),
|
||||||
|
CodeSegment::from_slice(0xe000, &partition_cfg),
|
||||||
|
CodeSegment::from_slice(0xf000, &partition_cfg),
|
||||||
|
// CodeSegment::from_slice(0x10000, &c),
|
||||||
|
// CodeSegment::from_slice(0x1f8000, &d),
|
||||||
|
];
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chip for Bl602 {
|
impl Chip for Bl602 {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
mod bl602;
|
pub mod bl602;
|
||||||
pub use bl602::Bl602;
|
pub use bl602::Bl602;
|
||||||
pub use crate::elf::{FirmwareImage, CodeSegment};
|
pub use crate::elf::{FirmwareImage, CodeSegment};
|
||||||
pub use crate::flasher::FlashSegment;
|
pub use crate::flasher::FlashSegment;
|
||||||
|
@ -25,6 +25,8 @@ pub enum Error {
|
|||||||
RomError(RomError),
|
RomError(RomError),
|
||||||
#[error("Parse error")]
|
#[error("Parse error")]
|
||||||
ParseError(#[from] deku::error::DekuError),
|
ParseError(#[from] deku::error::DekuError),
|
||||||
|
#[error("Parse toml error")]
|
||||||
|
TomlError(#[from] toml::de::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::io::Error> for Error {
|
impl From<std::io::Error> for Error {
|
||||||
|
@ -37,13 +37,14 @@ pub struct Flasher {
|
|||||||
|
|
||||||
impl Flasher {
|
impl Flasher {
|
||||||
pub fn connect(
|
pub fn connect(
|
||||||
|
chip: impl Chip + 'static,
|
||||||
serial: impl SerialPort + 'static,
|
serial: impl SerialPort + 'static,
|
||||||
speed: Option<BaudRate>,
|
speed: Option<BaudRate>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let mut flasher = Flasher {
|
let mut flasher = Flasher {
|
||||||
connection: Connection::new(serial),
|
connection: Connection::new(serial),
|
||||||
boot_info: protocol::BootInfo::default(),
|
boot_info: protocol::BootInfo::default(),
|
||||||
chip: Box::new(Bl602),
|
chip: Box::new(chip),
|
||||||
};
|
};
|
||||||
flasher.connection.set_baud(speed.unwrap_or(DEFAULT_BAUDRATE))?;
|
flasher.connection.set_baud(speed.unwrap_or(DEFAULT_BAUDRATE))?;
|
||||||
flasher.start_connection()?;
|
flasher.start_connection()?;
|
||||||
|
3
blflash/src/image/mod.rs
Normal file
3
blflash/src/image/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod partition;
|
||||||
|
|
||||||
|
pub use partition::PartitionCfg;
|
75
blflash/src/image/partition.rs
Normal file
75
blflash/src/image/partition.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
use deku::prelude::*;
|
||||||
|
use std::iter;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, DekuWrite, Default)]
|
||||||
|
#[deku(magic = b"\x42\x46\x50\x54\x00\x00")]
|
||||||
|
pub struct PartitionCfg {
|
||||||
|
#[serde(skip)]
|
||||||
|
#[deku(update = "self.pt_entry.len()")]
|
||||||
|
pub entry_len: u32,
|
||||||
|
#[serde(skip)]
|
||||||
|
#[deku(update = "0")]
|
||||||
|
_unused1: u16,
|
||||||
|
#[serde(skip)]
|
||||||
|
#[deku(update = "self.header_checksum()")]
|
||||||
|
pub checksum: u32,
|
||||||
|
#[deku(skip)]
|
||||||
|
pub pt_table: Table,
|
||||||
|
pub pt_entry: Vec<Entry>,
|
||||||
|
#[serde(skip)]
|
||||||
|
#[deku(update = "self.checksum()")]
|
||||||
|
pub file_checksum: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, DekuWrite, Default)]
|
||||||
|
pub struct Table {
|
||||||
|
pub address0: u32,
|
||||||
|
pub address1: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, DekuWrite, Default)]
|
||||||
|
pub struct Entry {
|
||||||
|
#[deku(bytes = "3")]
|
||||||
|
pub r#type: u32,
|
||||||
|
#[deku(writer = "Entry::write_name(name, output)")]
|
||||||
|
pub name: String,
|
||||||
|
pub address0: u32,
|
||||||
|
pub address1: u32,
|
||||||
|
pub size0: u32,
|
||||||
|
pub size1: u32,
|
||||||
|
pub len: u32,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub _unused1: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartitionCfg {
|
||||||
|
fn header_checksum(&self) -> u32 {
|
||||||
|
let data = self.to_bytes().unwrap();
|
||||||
|
crc::crc32::checksum_ieee(&data[0..12])
|
||||||
|
}
|
||||||
|
fn checksum(&self) -> u32 {
|
||||||
|
let data = self.to_bytes().unwrap();
|
||||||
|
crc::crc32::checksum_ieee(&data[16..16+36*self.pt_entry.len()])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entry {
|
||||||
|
fn write_name(
|
||||||
|
name: &str,
|
||||||
|
output: &mut BitVec<Msb0, u8>,
|
||||||
|
) -> Result<(), DekuError> {
|
||||||
|
if name.len() > 8 {
|
||||||
|
return Err(DekuError::Unexpected("name too long".to_string()))
|
||||||
|
}
|
||||||
|
let bytes = name
|
||||||
|
.bytes()
|
||||||
|
.chain(iter::repeat(0))
|
||||||
|
.take(8 + 1) // last is null?
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
output.write_all(&bytes).unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
mod config;
|
mod config;
|
||||||
mod flasher;
|
mod flasher;
|
||||||
mod connection;
|
mod connection;
|
||||||
mod chip;
|
pub mod chip;
|
||||||
mod error;
|
mod error;
|
||||||
mod image;
|
mod image;
|
||||||
pub mod elf;
|
pub mod elf;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::fs::read;
|
use std::fs::read;
|
||||||
|
|
||||||
use blflash::{Config, Flasher, Error};
|
use blflash::{Config, Flasher, Error, chip::bl602::{self, Bl602}};
|
||||||
use main_error::MainError;
|
use main_error::MainError;
|
||||||
use serial::BaudRate;
|
use serial::BaudRate;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
@ -15,6 +15,11 @@ struct FlashOpt {
|
|||||||
/// Bin file
|
/// Bin file
|
||||||
#[structopt(parse(from_os_str))]
|
#[structopt(parse(from_os_str))]
|
||||||
image: PathBuf,
|
image: PathBuf,
|
||||||
|
/// Path to partition_cfg.toml, default to be partition/partition_cfg_2M.toml
|
||||||
|
partition_cfg: Option<PathBuf>,
|
||||||
|
/// With boot2
|
||||||
|
#[structopt(short, long)]
|
||||||
|
without_boot2: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
@ -37,34 +42,59 @@ enum Opt {
|
|||||||
|
|
||||||
fn flash(opt: FlashOpt) -> Result<(), Error> {
|
fn flash(opt: FlashOpt) -> Result<(), Error> {
|
||||||
let serial = serial::open(&opt.port)?;
|
let serial = serial::open(&opt.port)?;
|
||||||
let mut flasher = Flasher::connect(serial, Some(BaudRate::Baud115200))?;
|
let chip = Bl602;
|
||||||
|
|
||||||
log::info!("Bootrom version: {}", flasher.boot_info().bootrom_version);
|
if !opt.without_boot2 {
|
||||||
log::trace!("Boot info: {:x?}", flasher.boot_info());
|
let partition_cfg = opt
|
||||||
// use blflash::elf::CodeSegment;
|
.partition_cfg
|
||||||
// let a = read("image/boot2image.bin")?;
|
.map(read)
|
||||||
// let b = read("image/partition.bin")?;
|
.unwrap_or_else(|| Ok(bl602::DEFAULT_PARTITION_CFG.to_vec()))?;
|
||||||
// let c = read("image/fwimage.bin")?;
|
let partition_cfg = toml::from_slice(&partition_cfg)?;
|
||||||
// let d = read("image/ro_params.dtb")?;
|
|
||||||
// let segments = vec![
|
let bin = read(&opt.image)?;
|
||||||
// CodeSegment::from_slice(0x0, &a),
|
let segments = chip.with_boot2(
|
||||||
// CodeSegment::from_slice(0xe000, &b),
|
partition_cfg,
|
||||||
// CodeSegment::from_slice(0xf000, &b),
|
&bin
|
||||||
// CodeSegment::from_slice(0x10000, &c),
|
)?;
|
||||||
// CodeSegment::from_slice(0x1f8000, &d),
|
let mut flasher = Flasher::connect(
|
||||||
// ];
|
chip,
|
||||||
// flasher.load_segments(segments.into_iter())?;
|
serial,
|
||||||
let input_bytes = read(&opt.image)?;
|
Some(BaudRate::Baud115200)
|
||||||
flasher.load_elf_to_flash(&input_bytes)?;
|
)?;
|
||||||
|
|
||||||
|
log::info!("Bootrom version: {}", flasher.boot_info().bootrom_version);
|
||||||
|
log::trace!("Boot info: {:x?}", flasher.boot_info());
|
||||||
|
|
||||||
|
flasher.load_segments(segments.into_iter())?;
|
||||||
|
|
||||||
|
flasher.reset()?;
|
||||||
|
} else {
|
||||||
|
let mut flasher = Flasher::connect(
|
||||||
|
chip,
|
||||||
|
serial,
|
||||||
|
Some(BaudRate::Baud115200)
|
||||||
|
)?;
|
||||||
|
|
||||||
|
log::info!("Bootrom version: {}", flasher.boot_info().bootrom_version);
|
||||||
|
log::trace!("Boot info: {:x?}", flasher.boot_info());
|
||||||
|
|
||||||
|
let input_bytes = read(&opt.image)?;
|
||||||
|
flasher.load_elf_to_flash(&input_bytes)?;
|
||||||
|
|
||||||
|
flasher.reset()?;
|
||||||
|
}
|
||||||
|
|
||||||
flasher.reset()?;
|
|
||||||
log::info!("Success");
|
log::info!("Success");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(opt: CheckOpt) -> Result<(), Error> {
|
fn check(opt: CheckOpt) -> Result<(), Error> {
|
||||||
let serial = serial::open(&opt.port)?;
|
let serial = serial::open(&opt.port)?;
|
||||||
let mut flasher = Flasher::connect(serial, Some(BaudRate::Baud115200))?;
|
let mut flasher = Flasher::connect(
|
||||||
|
Bl602,
|
||||||
|
serial,
|
||||||
|
Some(BaudRate::Baud115200),
|
||||||
|
)?;
|
||||||
|
|
||||||
log::info!("Bootrom version: {}", flasher.boot_info().bootrom_version);
|
log::info!("Bootrom version: {}", flasher.boot_info().bootrom_version);
|
||||||
log::trace!("Boot info: {:x?}", flasher.boot_info());
|
log::trace!("Boot info: {:x?}", flasher.boot_info());
|
||||||
|
Loading…
Reference in New Issue
Block a user