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:
parent
820e9ccef5
commit
6945bb6cb4
102
sim/src/image.rs
102
sim/src/image.rs
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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, {
|
||||
|
|
Loading…
Reference in New Issue