feat: add partition bin

This commit is contained in:
spacemeowx2 2020-12-04 19:23:54 +08:00 committed by spacelin
parent fa1865987e
commit 004fdf12bc
13 changed files with 277 additions and 25 deletions

23
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View 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

Binary file not shown.

View File

@ -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 {

View File

@ -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;

View File

@ -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 {

View File

@ -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()?;

View File

3
blflash/src/image/mod.rs Normal file
View File

@ -0,0 +1,3 @@
mod partition;
pub use partition::PartitionCfg;

View 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(())
}
}

View File

@ -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;

View File

@ -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());