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"
dependencies = [
"byteorder",
"crc",
"deku",
"directories-next",
"env_logger",
"hex",
"indicatif",
"log",
"main_error",
@ -112,6 +114,12 @@ dependencies = [
"generic-array",
]
[[package]]
name = "build_const"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
[[package]]
name = "byteorder"
version = "1.3.4"
@ -193,6 +201,15 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "darling"
version = "0.10.2"
@ -384,6 +401,12 @@ dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
[[package]]
name = "humantime"
version = "2.0.1"

View File

@ -26,3 +26,5 @@ byteorder = "1.3.4"
sha2 = "0.9.2"
structopt = { version = "0.3.21", features = ["paw"] }
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 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;
// 16MB
const ROM_END: u32 = 0x23000000 + 0x1000000;
#[derive(Copy, Clone)]
pub struct Bl602;
impl Bl602 {
fn addr_is_flash(&self, addr: u32) -> bool {
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 {

View File

@ -1,4 +1,4 @@
mod bl602;
pub mod bl602;
pub use bl602::Bl602;
pub use crate::elf::{FirmwareImage, CodeSegment};
pub use crate::flasher::FlashSegment;

View File

@ -25,6 +25,8 @@ pub enum Error {
RomError(RomError),
#[error("Parse error")]
ParseError(#[from] deku::error::DekuError),
#[error("Parse toml error")]
TomlError(#[from] toml::de::Error),
}
impl From<std::io::Error> for Error {

View File

@ -37,13 +37,14 @@ pub struct Flasher {
impl Flasher {
pub fn connect(
chip: impl Chip + 'static,
serial: impl SerialPort + 'static,
speed: Option<BaudRate>,
) -> Result<Self, Error> {
let mut flasher = Flasher {
connection: Connection::new(serial),
boot_info: protocol::BootInfo::default(),
chip: Box::new(Bl602),
chip: Box::new(chip),
};
flasher.connection.set_baud(speed.unwrap_or(DEFAULT_BAUDRATE))?;
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 flasher;
mod connection;
mod chip;
pub mod chip;
mod error;
mod image;
pub mod elf;

View File

@ -1,6 +1,6 @@
use std::fs::read;
use blflash::{Config, Flasher, Error};
use blflash::{Config, Flasher, Error, chip::bl602::{self, Bl602}};
use main_error::MainError;
use serial::BaudRate;
use env_logger::Env;
@ -15,6 +15,11 @@ struct FlashOpt {
/// Bin file
#[structopt(parse(from_os_str))]
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)]
@ -37,34 +42,59 @@ enum Opt {
fn flash(opt: FlashOpt) -> Result<(), Error> {
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);
log::trace!("Boot info: {:x?}", flasher.boot_info());
// use blflash::elf::CodeSegment;
// let a = read("image/boot2image.bin")?;
// let b = read("image/partition.bin")?;
// let c = read("image/fwimage.bin")?;
// let d = read("image/ro_params.dtb")?;
// let segments = vec![
// CodeSegment::from_slice(0x0, &a),
// CodeSegment::from_slice(0xe000, &b),
// CodeSegment::from_slice(0xf000, &b),
// CodeSegment::from_slice(0x10000, &c),
// CodeSegment::from_slice(0x1f8000, &d),
// ];
// flasher.load_segments(segments.into_iter())?;
let input_bytes = read(&opt.image)?;
flasher.load_elf_to_flash(&input_bytes)?;
if !opt.without_boot2 {
let partition_cfg = opt
.partition_cfg
.map(read)
.unwrap_or_else(|| Ok(bl602::DEFAULT_PARTITION_CFG.to_vec()))?;
let partition_cfg = toml::from_slice(&partition_cfg)?;
let bin = read(&opt.image)?;
let segments = chip.with_boot2(
partition_cfg,
&bin
)?;
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());
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");
Ok(())
}
fn check(opt: CheckOpt) -> Result<(), Error> {
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::trace!("Boot info: {:x?}", flasher.boot_info());