Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add partition-table subcommand #172

Merged
merged 3 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: 1.56
toolchain: 1.58
override: true
- uses: Swatinem/rust-cache@v1
- uses: actions-rs/cargo@v1
Expand Down
55 changes: 51 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This repository contains two applications:
| [cargo-espflash] | Cargo subcommand for espflash |
| [espflash] | Library and `espflash` binary (_without_ Cargo integration) |

> **NOTE:** requires `rustc >= 1.56.0` in order to build either application
> **NOTE:** requires `rustc >= 1.58.0` in order to build either application

## Installation

Expand Down
71 changes: 70 additions & 1 deletion cargo-espflash/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{
fs,
io::Write,
path::PathBuf,
process::{exit, Command, ExitStatus, Stdio},
str::FromStr,
Expand All @@ -12,7 +13,7 @@ use espflash::{
board_info, connect, flash_elf_image, monitor::monitor, save_elf_as_image, ConnectOpts,
FlashConfigOpts, FlashOpts,
},
Chip, Config, ImageFormatId,
Chip, Config, ImageFormatId, InvalidPartitionTable, PartitionTable,
};
use miette::{IntoDiagnostic, Result, WrapErr};

Expand Down Expand Up @@ -56,6 +57,8 @@ pub enum SubCommand {
BoardInfo(ConnectOpts),
/// Save the image to disk instead of flashing to device
SaveImage(SaveImageOpts),
/// Operations for partitions tables
PartitionTable(PartitionTableOpts),
}

#[derive(Parser)]
Expand Down Expand Up @@ -102,6 +105,24 @@ pub struct SaveImageOpts {
pub partition_table: Option<PathBuf>,
}

#[derive(Parser)]
pub struct PartitionTableOpts {
/// Convert CSV parition table to binary representation
#[clap(long, required_unless_present_any = ["info", "to-csv"])]
to_binary: bool,
/// Convert binary partition table to CSV representation
#[clap(long, required_unless_present_any = ["info", "to-binary"])]
to_csv: bool,
/// Show information on partition table
#[clap(short, long, required_unless_present_any = ["to-binary", "to-csv"])]
info: bool,
/// Input partition table
partition_table: PathBuf,
/// Optional output file name, if unset will output to stdout
#[clap(short, long)]
output: Option<PathBuf>,
}

fn main() -> Result<()> {
miette::set_panic_hook();

Expand All @@ -117,6 +138,7 @@ fn main() -> Result<()> {
match subcommand {
BoardInfo(opts) => board_info(opts, config),
SaveImage(opts) => save_image(opts, metadata, cargo_config),
PartitionTable(opts) => partition_table(opts),
}
} else {
flash(opts, config, metadata, cargo_config)
Expand Down Expand Up @@ -344,6 +366,53 @@ fn save_image(
Ok(())
}

fn partition_table(opts: PartitionTableOpts) -> Result<()> {
if opts.to_binary {
let input = fs::read(&opts.partition_table).into_diagnostic()?;
let part_table = PartitionTable::try_from_str(String::from_utf8(input).into_diagnostic()?)
.into_diagnostic()?;

// Use either stdout or a file if provided for the output.
let mut writer: Box<dyn Write> = if let Some(output) = opts.output {
Box::new(fs::File::create(output).into_diagnostic()?)
} else {
Box::new(std::io::stdout())
};
part_table.save_bin(&mut writer).into_diagnostic()?;
} else if opts.to_csv {
let input = fs::read(&opts.partition_table).into_diagnostic()?;
let part_table = PartitionTable::try_from_bytes(input).into_diagnostic()?;

// Use either stdout or a file if provided for the output.
let mut writer: Box<dyn Write> = if let Some(output) = opts.output {
Box::new(fs::File::create(output).into_diagnostic()?)
} else {
Box::new(std::io::stdout())
};
part_table.save_csv(&mut writer).into_diagnostic()?;
} else if opts.info {
let input = fs::read(&opts.partition_table).into_diagnostic()?;

// Try getting the partition table from either the csv or the binary representation and
// fail otherwise.
let part_table = if let Ok(part_table) =
PartitionTable::try_from_bytes(input.clone()).into_diagnostic()
{
part_table
} else if let Ok(part_table) =
PartitionTable::try_from_str(String::from_utf8(input).into_diagnostic()?)
{
part_table
} else {
return Err((InvalidPartitionTable {}).into());
};

part_table.pretty_print();
}

Ok(())
}

#[cfg(unix)]
fn exit_with_process_status(status: ExitStatus) -> ! {
use std::os::unix::process::ExitStatusExt;
Expand Down
3 changes: 2 additions & 1 deletion espflash/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = [
"Jesse Braham <[email protected]>",
]
edition = "2021"
rust-version = "1.56"
rust-version = "1.58"
description = "A command-line tool for flashing Espressif devices over serial"
repository = "https://github.com/esp-rs/espflash"
license = "GPL-2.0"
Expand Down Expand Up @@ -35,6 +35,7 @@ path = "src/main.rs"
binread = "2.2"
bytemuck = { version = "1.9", features = ["derive"] }
clap = { version = "3.1", features = ["derive"] }
comfy-table = "5"
crossterm = "0.23"
csv = "1.1"
dialoguer = "0.10"
Expand Down
32 changes: 32 additions & 0 deletions espflash/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,18 @@ pub enum PartitionTableError {
#[error(transparent)]
#[diagnostic(transparent)]
UnalignedPartitionError(#[from] UnalignedPartitionError),
#[error(transparent)]
#[diagnostic(transparent)]
LengthNotMultipleOf32(#[from] LengthNotMultipleOf32),
#[error(transparent)]
#[diagnostic(transparent)]
InvalidChecksum(#[from] InvalidChecksum),
#[error(transparent)]
#[diagnostic(transparent)]
NoEndMarker(#[from] NoEndMarker),
#[error(transparent)]
#[diagnostic(transparent)]
InvalidPartitionTable(#[from] InvalidPartitionTable),
}

#[derive(Debug, Error, Diagnostic)]
Expand Down Expand Up @@ -535,6 +547,26 @@ impl UnalignedPartitionError {
}
}

#[derive(Debug, Error, Diagnostic)]
#[error("Partition table length not a multiple of 32")]
#[diagnostic(code(espflash::partition_table::invalid_length))]
pub struct LengthNotMultipleOf32;

#[derive(Debug, Error, Diagnostic)]
#[error("Checksum invalid")]
#[diagnostic(code(espflash::partition_table::invalid_checksum))]
pub struct InvalidChecksum;

#[derive(Debug, Error, Diagnostic)]
#[error("No end marker found")]
#[diagnostic(code(espflash::partition_table::no_end_marker))]
pub struct NoEndMarker;

#[derive(Debug, Error, Diagnostic)]
#[error("Invalid partition table")]
#[diagnostic(code(espflash::partition_table::invalid_partition_table))]
pub struct InvalidPartitionTable;

#[derive(Debug, Error)]
#[error("{0}")]
pub struct ElfError(&'static str);
Expand Down
2 changes: 1 addition & 1 deletion espflash/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub use chip::Chip;
pub use cli::config::Config;
pub use elf::{FlashFrequency, FlashMode};
pub use error::Error;
pub use error::{Error, InvalidPartitionTable};
pub use flasher::{FlashSize, Flasher};
pub use image_format::ImageFormatId;
pub use partition_table::PartitionTable;
Expand Down
Loading