Skip to content
Open
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
51 changes: 37 additions & 14 deletions src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,22 +187,11 @@ pub fn elf_to_tbf(
TotalSizePowerOfTwo,
/// Make sure the entire TBF is a multiple of a specific value.
TotalSizeMultiple(usize),
/// To prevent wasted space, only pad to:
/// (X - 1) * (TotalSizePowerOfTwo / 8) < size < X * (TotalSizePowerOfTwo / 8)
MaskedPowerOfTwo,
Comment on lines +190 to +192

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supported for an unmodified, old kernel that doesn't know about these elf2tab changes yet?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be. The only issue I forsee would be if the kernel can't assign an MPU config for this app size (in which case the kernel wouldn't load the app).

With that being said, the MaskedPowerOfTwo should always be able to be assigned an MPU config since it is just using subregions to mask out some of the wasted power of two region size.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only issue I forsee would be if the kernel can't assign an MPU config for this app size (in which case the kernel wouldn't load the app).

That's exactly what I'm concerned about.

With that being said, the MaskedPowerOfTwo should always be able to be assigned an MPU config since it is just using subregions to mask out some of the wasted power of two region size.

Got it. I'm not familiar with the Cortex-M MPU implementation, and so I wasn't sure whether that needs adjustment to support this new MaskedPowerOfTwo mode. If that works with the one that's upstream already (and hence won't break backwards-compatibility of elf2tab), then I'm conceptually on board with this change.

}

// Add trailing padding for certain architectures.
//
// - ARM: make sure the entire TBF is a power of 2 to make configuring the
// MPU easy.
// - RISC_V: make sure the entire TBF is a multiple of 4 to meet TBF
// alignment requirements.
// - x86: use 4k padding to match page size.
let trailing_padding = match elf_file.ehdr.e_machine {
elf::abi::EM_ARM => Some(TrailingPadding::TotalSizePowerOfTwo),
elf::abi::EM_RISCV => Some(TrailingPadding::TotalSizeMultiple(4)),
elf::abi::EM_386 => Some(TrailingPadding::TotalSizeMultiple(4096)),
_ => None,
};

////////////////////////////////////////////////////////////////////////////
// Determine the amount of RAM this app needs.
////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -897,6 +886,30 @@ pub fn elf_to_tbf(
ensured_footer_reserved_space = true;
}

// Add trailing padding for certain architectures.
// - ARM: make sure the entire TBF is a power of 2 to make configuring the
// MPU easy and to make using the generated TBFs directly easy (for apps <64kB).
// However, for larger apps (i.e., apps >64kB) round up to the
// nearest power of 2 and then use subregions to limit wasted flash.
Comment thread
bradjc marked this conversation as resolved.
// This is still compatible with the MPU but may make using multiple TBFs
// more difficult due to alignment restrictions.
// - RISC_V: make sure the entire TBF is a multiple of 4 to meet TBF
// alignment requirements.
// - x86: use 4k padding to match page size.
let trailing_padding = match elf_file.ehdr.e_machine {
elf::abi::EM_ARM => {
// Do power of two padding if less than 64KB, otherwise do masked.
if binary_index < 65536 {
Some(TrailingPadding::TotalSizePowerOfTwo)
} else {
Some(TrailingPadding::MaskedPowerOfTwo)
}
}
elf::abi::EM_RISCV => Some(TrailingPadding::TotalSizeMultiple(4)),
elf::abi::EM_386 => Some(TrailingPadding::TotalSizeMultiple(4096)),
_ => None,
};

// Optionally calculate the additional padding needed to ensure the app size
// meets the padding requirements.
//
Expand All @@ -921,6 +934,16 @@ pub fn elf_to_tbf(
TrailingPadding::TotalSizeMultiple(multiple) => {
(multiple - (binary_index % multiple)) % multiple
}
TrailingPadding::MaskedPowerOfTwo => {
// Find the next power of two.
let next_power2 = 1 << (32 - (binary_index as u32).leading_zeros());
let multiple = next_power2 / 8;
let number_of_unmasked_subregions = binary_index.div_ceil(multiple);
let target_size = number_of_unmasked_subregions * multiple;

// Pad to the nearest multiple of (power of two / 8).
target_size - binary_index
}
};

// Increment to include the padding.
Expand Down