blob: 57b4bad0437ee4a404af1a1c46b42f4671dbf683 [file] [log] [blame]
David Browne2acfae2020-01-21 16:45:01 -07001// Copyright (c) 2019 Linaro LTD
2//
3// SPDX-License-Identifier: Apache-2.0
4
David Brownc3898d62019-08-05 14:20:02 -06005//! Support and tests related to the dependency management for multi-image
6//! support.
7
8use crate::image::ImageVersion;
9
10pub trait Depender {
11 /// Generate a version for this particular image. The slot indicates
12 /// which slot this is being put in.
13 fn my_version(&self, offset: usize, slot: usize) -> ImageVersion;
14
15 /// Return dependencies for this image/slot combination.
16 fn my_deps(&self, offset: usize, slot: usize) -> Vec<ImageVersion>;
17
18 /// Return the image ID of the other version.
19 fn other_id(&self) -> u8;
20}
21
22/// A boring image is used when we aren't testing dependencies. There will
23/// be meaningful version numbers. The size field is the image number we
24/// are.
25pub struct BoringDep(pub usize);
26
27impl Depender for BoringDep {
28 fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
29 ImageVersion::new_synthetic(self.0 as u8, slot as u8, 0)
30 }
31
32 fn my_deps(&self, _offset: usize, _slot: usize) -> Vec<ImageVersion> {
33 vec![]
34 }
35
36 fn other_id(&self) -> u8 {
37 0
38 }
39}
40
41/// An individual test of the dependency mechanism describes one of the
42/// possibilities for the dependency information for each image, and what
43/// the expected outcome is.
44#[derive(Clone, Debug)]
45pub struct DepTest {
46 /// What kinds of dependency should be installed in the image.
47 pub depends: [DepType; 2],
48
49 /// What is the expected outcome of the upgrade.
50 pub upgrades: [UpgradeInfo; 2],
51}
52
53/// Describes the various types of dependency information that can be
54/// provided.
55#[derive(Clone, Debug)]
56pub enum DepType {
57 /// Do not include dependency information
58 Nothing,
59 /// Provide dependency information that matches the other image.
60 Correct,
David Brown873be312019-09-03 12:22:32 -060061 /// Provide a dependency that matches the old version of the other
62 /// image.
63 OldCorrect,
David Brownc3898d62019-08-05 14:20:02 -060064 /// Provide dependency information describing something newer than the
65 /// other image.
66 Newer,
David Brown873be312019-09-03 12:22:32 -060067 /// Don't provide an upgrade image at all for this image
68 NoUpgrade,
David Brownc3898d62019-08-05 14:20:02 -060069}
70
71/// Describes what our expectation is for an upgrade.
David Brown207c4572019-09-03 12:21:05 -060072#[derive(Clone, Debug, PartialEq, Eq)]
David Brownc3898d62019-08-05 14:20:02 -060073pub enum UpgradeInfo {
74 /// The current version should be held.
75 Held,
76 /// The image should be upgraded
77 Upgraded,
78}
79
80/// A "test" that gives no dependency information.
81pub static NO_DEPS: DepTest = DepTest {
82 depends: [DepType::Nothing, DepType::Nothing],
83 upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
84};
85
86/// A PairDep describes the dependencies between two pairs.
87pub struct PairDep {
88 /// The image number of this image.
89 number: usize,
90
91 test: DepTest,
92}
93
94impl PairDep {
95 pub fn new(total_image: usize, my_image: usize, deps: &DepTest) -> PairDep {
96 if total_image != 2 {
97 panic!("PairDep only works when there are two images");
98 }
99
100 PairDep {
101 number: my_image,
102 test: deps.clone(),
103 }
104 }
105}
106
107impl Depender for PairDep {
108 fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
109 ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
110 }
111
112 fn my_deps(&self, _offset: usize, slot: usize) -> Vec<ImageVersion> {
David Brown873be312019-09-03 12:22:32 -0600113 // For now, don't put any dependencies in slot zero. They could be
114 // added here if we someday implement checking these.
115 if slot == 0 {
116 vec![]
117 } else {
118 match self.test.depends[self.number] {
119 DepType::Nothing => vec![],
120 DepType::NoUpgrade => panic!("Shouldn't get to this point"),
121 DepType::Correct => vec![
122 ImageVersion::new_synthetic(self.other_id(), slot as u8, 0)
123 ],
124 DepType::OldCorrect => vec![
125 ImageVersion::new_synthetic(self.other_id(), 0, 0)
126 ],
127 DepType::Newer => vec![
128 ImageVersion::new_synthetic(self.other_id(), slot as u8, 1)
129 ],
130 }
David Brownc3898d62019-08-05 14:20:02 -0600131 }
132 }
133
134 fn other_id(&self) -> u8 {
135 (1 - self.number) as u8
136 }
137}
138
139impl ImageVersion {
140 /// Generate an image version based on some key information. The image
141 /// number influences the major version number (by an arbitrary factor),
142 /// and the slot affects the major number on the build_number. The minor
143 /// number can also be given to force numbers to be different.
144 fn new_synthetic(image_id: u8, slot: u8, minor: u8) -> ImageVersion {
145 ImageVersion {
146 major: image_id * 20 + slot,
147 minor: minor,
148 revision: 1,
149 build_num: slot as u32,
150 }
151 }
152}