blob: a67bcd82def4ecaef89c1191ce853eb59ce473a9 [file] [log] [blame]
// Copyright (c) 2019 Linaro LTD
//
// SPDX-License-Identifier: Apache-2.0
//! Support and tests related to the dependency management for multi-image
//! support.
use crate::image::ImageVersion;
pub trait Depender {
/// Generate a version for this particular image. The slot indicates
/// which slot this is being put in.
fn my_version(&self, offset: usize, slot: usize) -> ImageVersion;
/// Return dependencies for this image/slot combination.
fn my_deps(&self, offset: usize, slot: usize) -> Vec<ImageVersion>;
/// Return the image ID of the other version.
fn other_id(&self) -> u8;
}
/// A boring image is used when we aren't testing dependencies. There will
/// be meaningful version numbers. The size field is the image number we
/// are.
pub struct BoringDep {
number: usize,
test: DepTest,
}
impl BoringDep {
pub fn new(number: usize, test: &DepTest) -> BoringDep {
BoringDep {
number,
test: test.clone(),
}
}
}
impl Depender for BoringDep {
fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
let slot = if self.test.downgrade {
1 - slot
} else {
slot
};
ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
}
fn my_deps(&self, _offset: usize, _slot: usize) -> Vec<ImageVersion> {
vec![]
}
fn other_id(&self) -> u8 {
0
}
}
/// An individual test of the dependency mechanism describes one of the
/// possibilities for the dependency information for each image, and what
/// the expected outcome is.
#[derive(Clone, Debug)]
pub struct DepTest {
/// What kinds of dependency should be installed in the image.
pub depends: [DepType; 2],
/// What is the expected outcome of the upgrade.
pub upgrades: [UpgradeInfo; 2],
/// Should this be considered a downgrade (cause the version number to
/// decrease).
pub downgrade: bool,
}
/// Describes the various types of dependency information that can be
/// provided.
#[derive(Clone, Debug)]
pub enum DepType {
/// Do not include dependency information
Nothing,
/// Provide dependency information that matches the other image.
Correct,
/// Provide a dependency that matches the old version of the other
/// image.
OldCorrect,
/// Provide dependency information describing something newer than the
/// other image.
Newer,
/// Don't provide an upgrade image at all for this image
NoUpgrade,
}
/// Describes what our expectation is for an upgrade.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum UpgradeInfo {
/// The current version should be held.
Held,
/// The image should be upgraded
Upgraded,
}
/// A "test" that gives no dependency information.
pub static NO_DEPS: DepTest = DepTest {
depends: [DepType::Nothing, DepType::Nothing],
upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
downgrade: false,
};
/// A "test" with no dependency information, and the images marked as a
/// downgrade.
pub static REV_DEPS: DepTest = DepTest {
depends: [DepType::Nothing, DepType::Nothing],
upgrades: [UpgradeInfo::Held, UpgradeInfo::Held],
downgrade: true,
};
/// A PairDep describes the dependencies between two pairs.
pub struct PairDep {
/// The image number of this image.
number: usize,
test: DepTest,
}
impl PairDep {
pub fn new(total_image: usize, my_image: usize, deps: &DepTest) -> PairDep {
if total_image != 2 {
panic!("PairDep only works when there are two images");
}
PairDep {
number: my_image,
test: deps.clone(),
}
}
}
impl Depender for PairDep {
fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
let slot = if self.test.downgrade {
1 - slot
} else {
slot
};
ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
}
fn my_deps(&self, _offset: usize, slot: usize) -> Vec<ImageVersion> {
// For now, don't put any dependencies in slot zero. They could be
// added here if we someday implement checking these.
if slot == 0 {
vec![]
} else {
match self.test.depends[self.number] {
DepType::Nothing => vec![],
DepType::NoUpgrade => panic!("Shouldn't get to this point"),
DepType::Correct => vec![
ImageVersion::new_synthetic(self.other_id(), slot as u8, 0)
],
DepType::OldCorrect => vec![
ImageVersion::new_synthetic(self.other_id(), 0, 0)
],
DepType::Newer => vec![
ImageVersion::new_synthetic(self.other_id(), slot as u8, 1)
],
}
}
}
fn other_id(&self) -> u8 {
(1 - self.number) as u8
}
}
impl ImageVersion {
/// Generate an image version based on some key information. The image
/// number influences the major version number (by an arbitrary factor),
/// and the slot affects the major number on the build_number. The minor
/// number can also be given to force numbers to be different.
fn new_synthetic(image_id: u8, slot: u8, minor: u8) -> ImageVersion {
ImageVersion {
major: image_id * 20 + slot,
minor,
revision: 1,
build_num: slot as u32,
}
}
}