Skip to content

Commit

Permalink
Merge pull request #24 from tock/fixed-address-start-estimate
Browse files Browse the repository at this point in the history
Estimate a protected region size for fixed address apps
  • Loading branch information
ppannuto committed Jul 20, 2020
2 parents 267e499 + 16a9f84 commit 1265180
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 1 deletion.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,19 @@ not. To detect a fixed RAM address, elf2tab looks for a `_sram_origin` symbol,
and if it exists checks if the address matches the dummy RAM address for PIC
apps or not.

elf2tab has to choose a length for the protected region after the TBF header and
before the start of the actual application binary. Normally, this defaults to 0.
It can be fixed for all TBFs in the TAB using the command line argument
`--protected-region-size` (which takes as an argument entire size before the
application binary, including the TBF header). However, a TAB can include both
PIC apps and non-PIC apps, and setting the size for all TBFs isn't always
desirable. Therefore, if `--protected-region-size` is not used, for apps
compiled for fixed addresses (as determined above) elf2tab will estimate a
protected region size that tries to ensure the start of the TBF headers _and_
the application binary are placed at useful addresses in flash. elf2tab will try
to increase the size of the protected region to make the start of the TBF header
at an address aligned to 256 bytes when the application binary is at its correct
fixed address.

### Creating the TAB file

Expand Down
2 changes: 2 additions & 0 deletions src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ impl fmt::Display for TbfHeader {
for wfr in &self.hdr_wfr {
write!(f, "{}", wfr)?;
}
self.hdr_fixed_addresses
.map_or(Ok(()), |hdr| write!(f, "{}", hdr))?;
Ok(())
}
}
60 changes: 59 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ fn main() {
.unwrap();

// Do the conversion to a tock binary.
if opt.verbose {
println!("Creating {:?}", tbf_path);
}
elf_to_tbf(
&elffile,
&mut outfile,
Expand All @@ -79,6 +82,9 @@ fn main() {
opt.protected_region_size,
)
.unwrap();
if opt.verbose {
println!("");
}

// Add the file to the TAB tar file.
outfile.seek(io::SeekFrom::Start(0)).unwrap();
Expand Down Expand Up @@ -335,7 +341,59 @@ fn elf_to_tbf<W: Write>(

fixed_protected_region_size
} else {
header_length as u32
// The protected region was not specified on the command line.
// Normally, we default to an additional size of 0 for the protected
// region beyond the header. However, if we are _not_ doing PIC, we
// might want to choose a nonzero sized protected region. Without
// PIC, the application binary must be at specific address. In
// addition, boards have a fixed address where they start looking
// for applications. To make both of those addresses match, we can
// expand the protected region.
//
// |----------------------|-------------------|---------------------
// | TBF Header | Protected Region | Application Binary
// |----------------------|-------------------|---------------------
// ^ ^ ^
// | | |-- Fixed binary address
// |-- Start of apps address |-- Flexible size
//
// However, we don't actually know the start of apps address.
// Additionally, an app may be positioned after another app in
// flash, and so the start address is actually the start of apps
// address plus the size of the first app. Tockloader when it goes
// to actually load the app can check for these addresses and expand
// the protected region as needed. But, in some cases it is easier
// to just be able to flash the TBF directly onto the board without
// needing Tockloader. So, we at least try to pick a reasonable
// protected size in the non-PIC case to give the TBF a chance of
// working as created.
//
// So, we put the start address of the TBF header at an alignment of
// 256 if the application binary is at the expected address.
if !fixed_address_flash_pic {
// Non-PIC case. As a reasonable guess we try to get our TBF
// start address to be at a 256 byte alignment.
let app_binary_address = fixed_address_flash.unwrap_or(0); // Already checked for `None`.
let tbf_start_address = util::align_down(app_binary_address, 256);
let protected_region_size = app_binary_address - tbf_start_address;
if protected_region_size > header_length as u32 {
// We do want to set the protected size past the header to
// something nonzero.
if verbose {
println!(
"Inserting nonzero protected region of length: {} bytes",
protected_region_size - header_length as u32
);
}
tbfheader.set_protected_size(protected_region_size - header_length as u32);
protected_region_size
} else {
header_length as u32
}
} else {
// Normal PIC case, no need to insert extra protected region.
header_length as u32
}
};
binary_index += protected_region_size as usize;

Expand Down
5 changes: 5 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ pub fn align_to(value: u32, box_size: u32) -> u32 {
value + ((box_size - (value % box_size)) % box_size)
}

/// Takes a value and rounds it down to be aligned % box_size
pub fn align_down(value: u32, box_size: u32) -> u32 {
value - (value % box_size)
}

/// How much needs to be added to get a value aligned % 4
pub fn amount_alignment_needed(value: u32, box_size: u32) -> u32 {
align_to(value, box_size) - value
Expand Down

0 comments on commit 1265180

Please sign in to comment.