Skip to content

Commit

Permalink
Refator logging ELFs
Browse files Browse the repository at this point in the history
Compress logging ELF files and name bootloader ELF based on its CRC32
checksum.
  • Loading branch information
surban committed Nov 16, 2023
1 parent 7dd5196 commit 5368d60
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 31 deletions.
30 changes: 29 additions & 1 deletion Cargo.lock

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

3 changes: 2 additions & 1 deletion openemc-log/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "openemc-log"
description = "OpenEMC Logger"
authors = ["Sebastian Urban <surban@surban.net>"]
license = "GPL-3.0"
version = "0.5.0"
version = "0.6.0"
publish = false
edition = "2021"

Expand All @@ -17,3 +17,4 @@ log = "0.4"
libc = "0.2"
env_logger = "0.10"
ctrlc = { version = "3", features = ["termination"] }
flate2 = "1"
36 changes: 30 additions & 6 deletions openemc-log/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use clap::Parser;
use defmt_decoder::{DecodeError, Frame, Location, Table};
use defmt_parser::Level as DefmtLevel;
use env_logger::Target;
use flate2::read::GzDecoder;
use log::{Level, LevelFilter};
use nix::{
errno::Errno,
Expand All @@ -44,6 +45,7 @@ mod syslog;

const READ_BUFFER_SIZE: usize = 128;
const POLL_TIMEOUT: c_int = 60_000;
const FIRMWARE_DIR: &'static str = "/lib/firmware";

static STOP: AtomicBool = AtomicBool::new(false);

Expand Down Expand Up @@ -123,27 +125,45 @@ fn get_paths(opts: &Opts, bootloader: bool) -> Result<(PathBuf, PathBuf)> {

let firmware_elf = match &opts.firmware_elf {
Some(firmware_elf) => firmware_elf.clone(),

None if bootloader => {
let firmware_bin = PathBuf::from(OsString::from_vec(
fs::read(openemc_log.with_file_name("openemc_firmware"))
.context("OpenEMC firmware location not available")?,
));
let firmware_dir = match firmware_bin.parent() {
Some(dir) if firmware_bin.has_root() => dir,
_ => Path::new(FIRMWARE_DIR),
};

let bootloader_crc32 = fs::read_to_string(openemc_log.with_file_name("openemc_bootloader_crc32"))
.context("OpenEMC bootloader CRC32 not available")?;

let bootloader_elf = firmware_dir.join(format!("openemc_bootloader_{bootloader_crc32}.elf.gz"));
if !bootloader_elf.is_file() {
bail!("OpenEMC bootloader ELF not found");
}
bootloader_elf
}

None => {
let mut firmware_bin = PathBuf::from(OsString::from_vec(
fs::read(openemc_log.with_file_name("openemc_firmware"))
.context("OpenEMC firmware location not available")?,
));
if !firmware_bin.has_root() {
firmware_bin = Path::new("/lib/firmware").join(firmware_bin);
firmware_bin = Path::new(FIRMWARE_DIR).join(firmware_bin);
}

let firmware_dir = firmware_bin.parent().context("no firmware directory")?;
let mut firmware = firmware_bin.file_stem().context("unrecognized firmware name")?.to_os_string();
if bootloader {
firmware = firmware.to_string_lossy().replace("openemc_", "openemc_bootloader_").into();
}

loop {
if firmware.is_empty() {
bail!("OpenEMC firmware ELF not found");
}

let firmware_elf = firmware_dir.join(&firmware).with_extension("elf");
let firmware_elf = firmware_dir.join(&firmware).with_extension("elf.gz");
if firmware_elf.is_file() {
break firmware_elf;
}
Expand All @@ -169,7 +189,11 @@ fn perform(opts: &Opts) -> Result<bool> {
firmware_elf.display()
);

let bytes = fs::read(&firmware_elf).context("cannot read firmware")?;
let mut bytes = Vec::new();
{
let mut file = GzDecoder::new(File::open(&firmware_elf).context("cannot open firmware")?);
file.read_to_end(&mut bytes).context("cannot read firmware")?;
}
let table = Table::parse(&bytes)?.context(".defmt data not found")?;
let locs = table.get_locations(&bytes)?;
drop(bytes);
Expand Down
2 changes: 2 additions & 0 deletions xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ edition = "2021"
devx-cmd = "0.5"
anyhow = "1"
clap = { version = "4", features = ["derive"] }
flate2 = "1"
crc32fast = "1.3"
68 changes: 45 additions & 23 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@

use clap::Parser;
use devx_cmd::cmd;
use flate2::{write::GzEncoder, Compression};
use std::{
env, fs,
fs::File,
io::{copy, Write},
path::{Path, PathBuf},
};

const ARCH: &str = "thumbv7m-none-eabi";
const GZ_LEVEL: Compression = Compression::best();

/// Build OpenEMC images.
#[derive(Parser, Debug)]
Expand Down Expand Up @@ -44,6 +48,15 @@ fn project_root() -> PathBuf {
Path::new(&env!("CARGO_MANIFEST_DIR")).ancestors().nth(1).unwrap().to_path_buf()
}

fn gzip(src: impl AsRef<Path>, dest: impl AsRef<Path>) -> std::io::Result<()> {
let mut in_file = File::open(src)?;
let out_file = File::create(dest)?;
let mut gz = GzEncoder::new(out_file, GZ_LEVEL);
copy(&mut in_file, &mut gz)?;
gz.finish()?.flush()?;
Ok(())
}

fn main() -> anyhow::Result<()> {
let args = Args::parse();
let board = &args.board;
Expand All @@ -60,22 +73,14 @@ fn main() -> anyhow::Result<()> {

let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());

if !args.no_bootloader {
let bootloader_elf_gz = if !args.no_bootloader {
cmd!(&cargo, "build", "--release", "--no-default-features", "--features", "defmt-ringbuf")
.current_dir(project_root().join("openemc-bootloader"))
.env("OPENEMC_BOARD", board)
.env("OPENEMC_BOOTLOADER", bootloader_variant)
.env("DEFMT_LOG", &args.bootloader_log)
.run()?;
fs::copy(
project_root()
.join("openemc-bootloader")
.join("target")
.join(ARCH)
.join("release")
.join("openemc-bootloader"),
project_root().join("image").join(format!("{bootloader}.elf")),
)?;

cmd!(
&cargo,
"objcopy",
Expand All @@ -93,7 +98,25 @@ fn main() -> anyhow::Result<()> {
.env("OPENEMC_BOOTLOADER", bootloader_variant)
.env("DEFMT_LOG", &args.bootloader_log)
.run()?;
}

let bootloader_bin_data = fs::read(project_root().join("image").join(format!("{bootloader}.bin")))?;
let bootloader_bin_crc32 = crc32fast::hash(&bootloader_bin_data);
let bootloader_elf_gz = format!("openemc_bootloader_{bootloader_bin_crc32:08x}.elf.gz");

gzip(
project_root()
.join("openemc-bootloader")
.join("target")
.join(ARCH)
.join("release")
.join("openemc-bootloader"),
project_root().join("image").join(&bootloader_elf_gz),
)?;

Some(bootloader_elf_gz)
} else {
None
};

cmd!(&cargo, "build", "--release", "--no-default-features", "--features", "defmt-ringbuf")
.args(args.features.iter().flat_map(|feature| ["--features", feature]))
Expand All @@ -102,15 +125,16 @@ fn main() -> anyhow::Result<()> {
.env("OPENEMC_BOOTLOADER", bootloader_variant)
.env("DEFMT_LOG", &args.log)
.run()?;
fs::copy(
gzip(
project_root()
.join("openemc-firmware")
.join("target")
.join(ARCH)
.join("release")
.join("openemc-firmware"),
project_root().join("image").join(format!("{firmware}.elf")),
project_root().join("image").join(format!("{firmware}.elf.gz")),
)?;

cmd!(&cargo, "objcopy", "--release", "--no-default-features", "--features", "defmt-ringbuf",)
.args(args.features.iter().flat_map(|feature| ["--features", feature]))
.args(["--", "-O", "binary", &format!("../image/{firmware}.bin")])
Expand Down Expand Up @@ -140,12 +164,12 @@ fn main() -> anyhow::Result<()> {
use std::os::unix::fs::PermissionsExt;
let mut files = vec![
project_root().join("image").join(format!("{firmware}.emc")),
project_root().join("image").join(format!("{firmware}.elf")),
project_root().join("image").join(format!("{firmware}.elf.gz")),
];
if !args.no_bootloader {
if let Some(bootloader_elf_gz) = &bootloader_elf_gz {
files.extend([
project_root().join("image").join(format!("{bootloader}.bin")),
project_root().join("image").join(format!("{bootloader}.elf")),
project_root().join("image").join(bootloader_elf_gz),
]);
}
for file in files {
Expand All @@ -157,14 +181,12 @@ fn main() -> anyhow::Result<()> {

println!();
println!("Board {board}:");
if !args.no_bootloader {
println!(
"Built {}bootloader image/{bootloader}.{{bin,elf}} with log level {}",
if emc_model == 0xd1 { "debug " } else { "" },
&args.bootloader_log
);
if let Some(bootloader_elf_gz) = &bootloader_elf_gz {
let debug = if emc_model == 0xd1 { "debug " } else { "" };
println!("Built {debug}bootloader image/{bootloader}.bin with log level {}", &args.bootloader_log);
println!("Built {debug}bootloader image/{bootloader_elf_gz}");
}
println!("Built OpenEMC firmware image/{firmware}.{{emc,elf}} with log level {}", &args.log);
println!("Built OpenEMC firmware image/{firmware}.{{emc,elf.gz}} with log level {}", &args.log);
println!();

Ok(())
Expand Down

0 comments on commit 5368d60

Please sign in to comment.