diff --git a/src/link.rs b/src/link.rs
index 8fc98075732a14f5f4e2382499e17ec52cb02b76..4b433031a31a53d15fac3e360fa6781ac19e345b 100644
--- a/src/link.rs
+++ b/src/link.rs
@@ -12,17 +12,20 @@
//! generates a binary that includes Pip MPU and the user code as root
//! partition
-
-use anyhow::Result;
+use anyhow::{anyhow, Result};
use clap::Parser;
use elf::endian::AnyEndian;
use std::path::PathBuf;
-use pip_mpu_relocate::reloc::RelIter;
-use pip_mpu_relocate::relocate::relocate;
-use pip_mpu_relocate::symbols::SymbolsQuery;
+// use pip_mpu_relocate::reloc::RelIter;
+// use pip_mpu_relocate::relocate::relocate;
+// use pip_mpu_relocate::symbols::SymbolsQuery;
use std::io::Write;
+const PADDING_SIZE: usize = 32;
+const PADDING_BUFFER: [u8; PADDING_SIZE] = [0xff; PADDING_SIZE];
+const PIP_EXPORT_SECTIONS: &'static [&str] = &[".vector_table", ".text", ".data"];
+
/// Options for the link subcommand
#[derive(Parser, Debug)]
pub struct Opts {
@@ -37,29 +40,56 @@ pub struct Opts {
/// Path the Pipcore MPU elf file
#[arg(long, short)]
- pip_elf: Option<PathBuf>
-
+ pip_elf: Option<PathBuf>,
}
-pub fn link(opts: Opts) -> Result<()> {
+/// Dump the binary content of the given sections to the output file.
+///
+/// It returns the number of bytes writen
+fn dump_sections<'s, T: Write>(
+ elf: &elf::ElfBytes<AnyEndian>,
+ section_names: &[&str],
+ output: &mut T,
+) -> Result<usize> {
+ let mut output_size = 0;
+
+ for section_name in section_names {
+ let section = match elf.section_header_by_name(section_name)? {
+ None => return Err(anyhow!("Section {section_name} not found")),
+ Some(s) => s,
+ };
+ let (bytes, compression) = elf.section_data(§ion)?;
+ assert_eq!(compression, None);
+ output.write_all(bytes)?;
+ output_size += bytes.len();
+ }
+ Ok(output_size)
+}
+fn align(value: usize, align: usize) -> usize {
+ let a = value & (align - 1);
+ if a == 0 {
+ 0
+ } else {
+ align - a
+ }
+}
+
+pub fn link(opts: Opts) -> Result<()> {
// First, open and parse both crt0 and user_code elf files
-
+
let crt0_elf_file = std::fs::read(&opts.crt0_elf)?;
let crt0_elf_data = crt0_elf_file.as_slice();
- let crt0_elf = elf::ElfBytes::<AnyEndian>::minimal_parse(crt0_elf_data)?;
+ let _crt0_elf = elf::ElfBytes::<AnyEndian>::minimal_parse(crt0_elf_data)?;
let user_code_elf_file = std::fs::read(&opts.user_code_elf)?;
let user_code_elf_data = user_code_elf_file.as_slice();
- let user_code_elf = elf::ElfBytes::<AnyEndian>::minimal_parse(user_code_elf_data)?;
-
+ let _user_code_elf = elf::ElfBytes::<AnyEndian>::minimal_parse(user_code_elf_data)?;
// Then open Pip elf file if necessary
let pip_elf_data = match opts.pip_elf {
None => None,
- Some(pip_path) => {
- Some(std::fs::read(&pip_path)?)
- }
+ Some(pip_path) => Some(std::fs::read(&pip_path)?),
};
let pip_elf = match pip_elf_data {
@@ -69,7 +99,41 @@ pub fn link(opts: Opts) -> Result<()> {
// When reaching here, all files were opened and parsed
// we can safely open the output file
let mut output = std::fs::File::create(opts.output)?;
- writeln!(output, "Yeah it works")?;
-
+
+ // First, if needed, output pip binary, padded to 32 bytes
+ if let Some(pip_elf) = pip_elf {
+ let output_size = dump_sections(&pip_elf, PIP_EXPORT_SECTIONS, &mut output)?;
+ // If ouput size is not align on configured padding size bytes, add some padding
+ let pad_bytes = align(output_size, PADDING_SIZE);
+ if pad_bytes > 0 {
+ output.write_all(&PADDING_BUFFER[0..pad_bytes])?;
+ }
+ }
Ok(())
}
+
+#[cfg(test)]
+mod tests {
+ use super::align;
+
+ #[test]
+ fn test_align() {
+ assert_eq!(align(0, 8), 0);
+ assert_eq!(align(1, 8), 7);
+ assert_eq!(align(2, 8), 6);
+ assert_eq!(align(3, 8), 5);
+ assert_eq!(align(4, 8), 4);
+ assert_eq!(align(5, 8), 3);
+ assert_eq!(align(6, 8), 2);
+ assert_eq!(align(7, 8), 1);
+
+ assert_eq!(align(8, 8), 0);
+ assert_eq!(align(9, 8), 7);
+ assert_eq!(align(10, 8), 6);
+ assert_eq!(align(11, 8), 5);
+ assert_eq!(align(12, 8), 4);
+ assert_eq!(align(13, 8), 3);
+ assert_eq!(align(14, 8), 2);
+ assert_eq!(align(15, 8), 1);
+ }
+}