sim: Add new ram-load test cases

Adds new test cases to various ram-load related logic.

Signed-off-by: Roland Mikhel <roland.mikhel@arm.com>
Change-Id: I3a0ca951b2c720be4e6fe2ed0e5d1830fcfb240c
This commit is contained in:
Roland Mikhel 2023-04-11 15:57:49 +02:00 committed by Dávid Vincze
parent 820e9ccef5
commit 6945bb6cb4
4 changed files with 109 additions and 30 deletions

View File

@ -123,6 +123,19 @@ struct SlotPlace {
size: u32,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ImageManipulation {
None,
BadSignature,
WrongOffset,
IgnoreRamLoadFlag,
/// True to use same address,
/// false to overlap by 1 byte
OverlapImages(bool),
CorruptHigherVersionImage,
}
impl ImagesBuilder {
/// Construct a new image builder for the given device. Returns
/// Some(builder) if is possible to test this configuration, or None if
@ -210,22 +223,37 @@ impl ImagesBuilder {
}
/// Construct an `Images` that doesn't expect an upgrade to happen.
pub fn make_no_upgrade_image(self, deps: &DepTest) -> Images {
pub fn make_no_upgrade_image(self, deps: &DepTest, img_manipulation: ImageManipulation) -> Images {
let num_images = self.num_images();
let mut flash = self.flash;
let ram = self.ram.clone(); // TODO: This is wasteful.
let ram = self.ram.clone(); // TODO: Avoid this clone.
let mut higher_version_corrupted = false;
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep: Box<dyn Depender> = if num_images > 1 {
Box::new(PairDep::new(num_images, image_num, deps))
} else {
Box::new(BoringDep::new(image_num, deps))
};
let primaries = install_image(&mut flash, &slots[0],
maximal(42784), &ram, &*dep, false, Some(0));
let upgrades = match deps.depends[image_num] {
DepType::NoUpgrade => install_no_image(),
_ => install_image(&mut flash, &slots[1],
maximal(46928), &ram, &*dep, false, Some(0))
let (primaries,upgrades) = if img_manipulation == ImageManipulation::CorruptHigherVersionImage && !higher_version_corrupted {
higher_version_corrupted = true;
let prim = install_image(&mut flash, &slots[0],
maximal(42784), &ram, &*dep, ImageManipulation::None, Some(0));
let upgr = match deps.depends[image_num] {
DepType::NoUpgrade => install_no_image(),
_ => install_image(&mut flash, &slots[1],
maximal(46928), &ram, &*dep, ImageManipulation::BadSignature, Some(0))
};
(prim, upgr)
} else {
let prim = install_image(&mut flash, &slots[0],
maximal(42784), &ram, &*dep, img_manipulation, Some(0));
let upgr = match deps.depends[image_num] {
DepType::NoUpgrade => install_no_image(),
_ => install_image(&mut flash, &slots[1],
maximal(46928), &ram, &*dep, img_manipulation, Some(0))
};
(prim, upgr)
};
OneImage {
slots,
@ -243,7 +271,7 @@ impl ImagesBuilder {
}
pub fn make_image(self, deps: &DepTest, permanent: bool) -> Images {
let mut images = self.make_no_upgrade_image(deps);
let mut images = self.make_no_upgrade_image(deps, ImageManipulation::None);
for image in &images.images {
mark_upgrade(&mut images.flash, &image.slots[1]);
}
@ -274,9 +302,9 @@ impl ImagesBuilder {
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_image(&mut bad_flash, &slots[0],
maximal(32784), &ram, &dep, false, Some(0));
maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
let upgrades = install_image(&mut bad_flash, &slots[1],
maximal(41928), &ram, &dep, true, Some(0));
maximal(41928), &ram, &dep, ImageManipulation::BadSignature, Some(0));
OneImage {
slots,
primaries,
@ -297,9 +325,9 @@ impl ImagesBuilder {
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_image(&mut bad_flash, &slots[0],
maximal(32784), &ram, &dep, false, Some(0));
maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
let upgrades = install_image(&mut bad_flash, &slots[1],
ImageSize::Oversized, &ram, &dep, false, Some(0));
ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0));
OneImage {
slots,
primaries,
@ -320,7 +348,7 @@ impl ImagesBuilder {
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_image(&mut flash, &slots[0],
maximal(32784), &ram, &dep, false, Some(0));
maximal(32784), &ram, &dep,ImageManipulation::None, Some(0));
let upgrades = install_no_image();
OneImage {
slots,
@ -343,7 +371,7 @@ impl ImagesBuilder {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_no_image();
let upgrades = install_image(&mut flash, &slots[1],
maximal(32784), &ram, &dep, false, Some(0));
maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
OneImage {
slots,
primaries,
@ -365,7 +393,7 @@ impl ImagesBuilder {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_no_image();
let upgrades = install_image(&mut flash, &slots[1],
ImageSize::Oversized, &ram, &dep, false, Some(0));
ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0));
OneImage {
slots,
primaries,
@ -387,9 +415,9 @@ impl ImagesBuilder {
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_image(&mut flash, &slots[0],
maximal(32784), &ram, &dep, false, security_cnt);
maximal(32784), &ram, &dep, ImageManipulation::None, security_cnt);
let upgrades = install_image(&mut flash, &slots[1],
maximal(41928), &ram, &dep, false, security_cnt.map(|v| v + 1));
maximal(41928), &ram, &dep, ImageManipulation::None, security_cnt.map(|v| v + 1));
OneImage {
slots,
primaries,
@ -1318,6 +1346,28 @@ impl Images {
false
}
pub fn run_ram_load_boot_with_result(&self, expected_result: bool) -> bool {
if !Caps::RamLoad.present() {
return false;
}
// Clone the flash so we can tell if unchanged.
let mut flash = self.flash.clone();
// Create RAM config.
let ram = RamBlock::new(self.ram.total - RAM_LOAD_ADDR, RAM_LOAD_ADDR);
// Run the bootloader, and verify that it couldn't run to completion.
let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc, None,
None, true));
if result.success() != expected_result {
error!("RAM load boot result was not of the expected value! (was: {}, expected: {})", result.success(), expected_result);
return true;
}
false
}
/// Adds a new flash area that fails statistically
fn mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize,
rate: f32) {
@ -1699,26 +1749,34 @@ fn image_largest_trailer(dev: &dyn Flash) -> usize {
/// fields used by the given code. Returns a copy of the image that was written.
fn install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: ImageSize,
ram: &RamData,
deps: &dyn Depender, bad_sig: bool, security_counter:Option<u32>) -> ImageData {
deps: &dyn Depender, img_manipulation: ImageManipulation, security_counter:Option<u32>) -> ImageData {
let offset = slot.base_off;
let slot_len = slot.len;
let dev_id = slot.dev_id;
let dev = flash.get_mut(&dev_id).unwrap();
let mut tlv: Box<dyn ManifestGen> = Box::new(make_tlv());
if img_manipulation == ImageManipulation::IgnoreRamLoadFlag {
tlv.set_ignore_ram_load_flag();
}
tlv.set_security_counter(security_counter);
// Add the dependencies early to the tlv.
for dep in deps.my_deps(offset, slot.index) {
tlv.add_dependency(deps.other_id(), &dep);
}
const HDR_SIZE: usize = 32;
let place = ram.lookup(&slot);
let load_addr = if Caps::RamLoad.present() {
place.offset
match img_manipulation {
ImageManipulation::WrongOffset => u32::MAX,
ImageManipulation::OverlapImages(true) => RAM_LOAD_ADDR,
ImageManipulation::OverlapImages(false) => place.offset - 1,
_ => place.offset
}
} else {
0
};
@ -1803,7 +1861,7 @@ fn install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: ImageSize,
}
// Build the TLV itself.
if bad_sig {
if img_manipulation == ImageManipulation::BadSignature {
tlv.corrupt_sig();
}
let mut b_tlv = tlv.make_tlv();

View File

@ -1,6 +1,6 @@
// Copyright (c) 2017-2019 Linaro LTD
// Copyright (c) 2017-2019 JUUL Labs
// Copyright (c) 2019 Arm Limited
// Copyright (c) 2019-2023 Arm Limited
//
// SPDX-License-Identifier: Apache-2.0
@ -30,6 +30,7 @@ pub use crate::{
image::{
ImagesBuilder,
Images,
ImageManipulation,
show_sizes,
},
};
@ -201,7 +202,7 @@ impl RunStatus {
failed |= bad_secondary_slot_image.run_signfail_upgrade();
let images = run.clone().make_no_upgrade_image(&NO_DEPS);
let images = run.clone().make_no_upgrade_image(&NO_DEPS, ImageManipulation::None);
failed |= images.run_norevert_newimage();
let images = run.make_image(&NO_DEPS, true);

View File

@ -112,6 +112,10 @@ pub trait ManifestGen {
/// Set the security counter to the specified value.
fn set_security_counter(&mut self, security_cnt: Option<u32>);
/// Sets the ignore_ram_load_flag so that can be validated when it is missing,
/// it will not load successfully.
fn set_ignore_ram_load_flag(&mut self);
}
#[derive(Debug, Default)]
@ -124,6 +128,8 @@ pub struct TlvGen {
/// Should this signature be corrupted.
gen_corrupted: bool,
security_cnt: Option<u32>,
/// Ignore RAM_LOAD flag
ignore_ram_load_flag: bool,
}
#[derive(Debug)]
@ -318,7 +324,7 @@ impl ManifestGen for TlvGen {
/// Retrieve the header flags for this configuration. This can be called at any time.
fn get_flags(&self) -> u32 {
// For the RamLoad case, add in the flag for this feature.
if Caps::RamLoad.present() {
if Caps::RamLoad.present() && !self.ignore_ram_load_flag {
self.flags | (TlvFlags::RAM_LOAD as u32)
} else {
self.flags
@ -793,6 +799,10 @@ impl ManifestGen for TlvGen {
fn set_security_counter(&mut self, security_cnt: Option<u32>) {
self.security_cnt = security_cnt;
}
fn set_ignore_ram_load_flag(&mut self) {
self.ignore_ram_load_flag = true;
}
}
include!("rsa_pub_key-rs.txt");

View File

@ -1,6 +1,6 @@
// Copyright (c) 2017-2021 Linaro LTD
// Copyright (c) 2017-2019 JUUL Labs
// Copyright (c) 2023 Arm Limited
// Copyright (c) 2021-2023 Arm Limited
//
// SPDX-License-Identifier: Apache-2.0
@ -15,6 +15,7 @@ use bootsim::{
NO_DEPS,
REV_DEPS,
testlog,
ImageManipulation
};
use std::{
env,
@ -51,7 +52,7 @@ sim_test!(bad_secondary_slot, make_bad_secondary_slot_image(), run_signfail_upgr
sim_test!(secondary_trailer_leftover, make_erased_secondary_image(), run_secondary_leftover_trailer());
sim_test!(bootstrap, make_bootstrap_image(), run_bootstrap());
sim_test!(oversized_bootstrap, make_oversized_bootstrap_image(), run_oversized_bootstrap());
sim_test!(norevert_newimage, make_no_upgrade_image(&NO_DEPS), run_norevert_newimage());
sim_test!(norevert_newimage, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_norevert_newimage());
sim_test!(basic_revert, make_image(&NO_DEPS, true), run_basic_revert());
sim_test!(revert_with_fails, make_image(&NO_DEPS, false), run_revert_with_fails());
sim_test!(perm_with_fails, make_image(&NO_DEPS, true), run_perm_with_fails());
@ -65,11 +66,20 @@ sim_test!(status_write_fails_complete, make_image(&NO_DEPS, true), run_with_stat
sim_test!(status_write_fails_with_reset, make_image(&NO_DEPS, true), run_with_status_fails_with_reset());
sim_test!(downgrade_prevention, make_image(&REV_DEPS, true), run_nodowngrade());
sim_test!(direct_xip_first, make_no_upgrade_image(&NO_DEPS), run_direct_xip());
sim_test!(ram_load_first, make_no_upgrade_image(&NO_DEPS), run_ram_load());
sim_test!(ram_load_split, make_no_upgrade_image(&NO_DEPS), run_split_ram_load());
sim_test!(direct_xip_first, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_direct_xip());
sim_test!(ram_load_first, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_ram_load());
sim_test!(ram_load_split, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_split_ram_load());
sim_test!(hw_prot_failed_security_cnt_check, make_image_with_security_counter(Some(0)), run_hw_rollback_prot());
sim_test!(hw_prot_missing_security_cnt, make_image_with_security_counter(None), run_hw_rollback_prot());
sim_test!(ram_load_out_of_bounds, make_no_upgrade_image(&NO_DEPS, ImageManipulation::WrongOffset), run_ram_load_boot_with_result(false));
sim_test!(ram_load_missing_header_flag, make_no_upgrade_image(&NO_DEPS, ImageManipulation::IgnoreRamLoadFlag), run_ram_load_boot_with_result(false));
sim_test!(ram_load_failed_validation, make_no_upgrade_image(&NO_DEPS, ImageManipulation::BadSignature), run_ram_load_boot_with_result(false));
sim_test!(ram_load_corrupt_higher_version_image, make_no_upgrade_image(&NO_DEPS, ImageManipulation::CorruptHigherVersionImage), run_ram_load_boot_with_result(true));
#[cfg(feature = "multiimage")]
sim_test!(ram_load_overlapping_images_same_base, make_no_upgrade_image(&NO_DEPS, ImageManipulation::OverlapImages(true)), run_ram_load_boot_with_result(false));
#[cfg(feature = "multiimage")]
sim_test!(ram_load_overlapping_images_offset, make_no_upgrade_image(&NO_DEPS, ImageManipulation::OverlapImages(false)), run_ram_load_boot_with_result(false));
// Test various combinations of incorrect dependencies.
test_shell!(dependency_combos, r, {