firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
1use std::path::PathBuf;
2use clap::Parser;
3use elf::abi::PT_LOAD;
4use elf::ElfBytes;
5use elf::endian::LittleEndian;
6
7#[derive(Parser, Debug)]
8#[command(version, about, long_about = None)]
9struct Args {
10 #[arg(short)]
11 in_file: PathBuf,
12
13 #[arg(short)]
14 out_file: PathBuf,
15}
16
17fn main() {
18 let args = Args::parse();
19
20 let elf_data = std::fs::read(args.in_file).expect("Failed to open ELF file");
21
22 let elf = ElfBytes::<LittleEndian>::minimal_parse(&elf_data)
23 .expect("Failed to parse ELF file");
24
25 // Copy all the LOAD segments, like objcopy -O binary
26 let mut bin: Vec<u8> = Vec::new();
27
28 let mut data_paddr = 0u32;
29 let mut data_vaddr = 0u32;
30 let mut data_len = 0u32;
31 let mut current_addr: Option<u32> = None;
32
33 for phdr in elf.segments().expect("Failed to parse ELF file") {
34 if phdr.p_type == PT_LOAD {
35 if current_addr.is_none() {
36 current_addr.replace(phdr.p_vaddr as u32);
37 }
38
39 let current_addr = current_addr.as_mut().unwrap();
40
41 if *current_addr < phdr.p_vaddr as u32 {
42 let diff = phdr.p_vaddr as u32 - *current_addr;
43 for _ in 0..diff {
44 bin.push(0);
45 }
46 }
47
48 let segment_data = elf.segment_data(&phdr).expect("Failed to parse ELF file");
49 bin.extend_from_slice(segment_data);
50 *current_addr += segment_data.len() as u32;
51 }
52
53 // Assume that there is at most one segment that needs to be copied from flash to RAM
54 // (i.e. the segment containing .data)
55 if phdr.p_paddr != phdr.p_vaddr {
56 data_paddr = phdr.p_paddr as u32;
57 data_vaddr = phdr.p_vaddr as u32;
58 data_len = phdr.p_memsz as u32;
59 }
60 }
61
62 let mut bss_paddr = 0u32;
63 let mut bss_len = 0u32;
64 if let Some(bss) = elf.section_header_by_name(".bss")
65 .expect("Failed to parse ELF file")
66 {
67 bss_paddr = bss.sh_addr as u32;
68 bss_len = bss.sh_size as u32;
69 }
70
71 let len = bin.len() as u32;
72
73 // Add missing EPB header entries
74 bin[8..12].copy_from_slice(&len.to_le_bytes()); // len
75 bin[12..16].copy_from_slice(&data_len.to_le_bytes()); // data_len
76 bin[16..20].copy_from_slice(&data_paddr.to_le_bytes()); // data_lma
77 bin[20..24].copy_from_slice(&data_vaddr.to_le_bytes()); // data_vma
78 bin[24..28].copy_from_slice(&bss_len.to_le_bytes()); // bss_len
79 bin[28..32].copy_from_slice(&bss_paddr.to_le_bytes()); // bss_vma
80
81 let crc = crc32fast::hash(&bin[8..]);
82 bin[4..8].copy_from_slice(&crc.to_le_bytes()); // crc
83
84 std::fs::write(args.out_file, &bin).expect("Failed to write output");
85}