blob: 4b85912e2af383481ed8a662d4064d244fd61a80 [file] [log] [blame]
David Brownde7729e2017-01-09 10:41:35 -07001//! Describe flash areas.
2
3use flash::{Flash, Sector};
David Brownde7729e2017-01-09 10:41:35 -07004use std::ptr;
5
6/// Structure to build up the boot area table.
7#[derive(Debug)]
8pub struct AreaDesc {
9 areas: Vec<Vec<FlashArea>>,
10 whole: Vec<FlashArea>,
11 sectors: Vec<Sector>,
12}
13
14impl AreaDesc {
15 pub fn new(flash: &Flash) -> AreaDesc {
16 AreaDesc {
17 areas: vec![],
18 whole: vec![],
19 sectors: flash.sector_iter().collect(),
20 }
21 }
22
23 /// Add a slot to the image. The slot must align with erasable units in the flash device.
24 /// Panics if the description is not valid. There are also bootloader assumptions that the
25 /// slots are SLOT0, SLOT1, and SCRATCH in that order.
26 pub fn add_image(&mut self, base: usize, len: usize, id: FlashId) {
27 let nid = id as usize;
28 let orig_base = base;
29 let orig_len = len;
30 let mut base = base;
31 let mut len = len;
32
33 while nid > self.areas.len() {
34 self.areas.push(vec![]);
35 self.whole.push(Default::default());
36 }
37
38 if nid != self.areas.len() {
39 panic!("Flash areas not added in order");
40 }
41
42 let mut area = vec![];
43
44 for sector in &self.sectors {
45 if len == 0 {
46 break;
47 };
48 if base > sector.base + sector.size - 1 {
49 continue;
50 }
51 if sector.base != base {
52 panic!("Image does not start on a sector boundary");
53 }
54
55 area.push(FlashArea {
56 flash_id: id,
57 device_id: 42,
58 pad16: 0,
59 off: sector.base as u32,
60 size: sector.size as u32,
61 });
62
63 base += sector.size;
64 len -= sector.size;
65 }
66
67 if len != 0 {
68 panic!("Image goes past end of device");
69 }
70
71 self.areas.push(area);
72 self.whole.push(FlashArea {
73 flash_id: id,
74 device_id: 42,
75 pad16: 0,
76 off: orig_base as u32,
77 size: orig_len as u32,
78 });
79 }
80
David Brown90c19132017-01-23 10:21:28 -070081 // Add a simple slot to the image. This ignores the device layout, and just adds the area as a
82 // single unit. It assumes that the image lines up with image boundaries. This tests
83 // configurations where the partition table uses larger sectors than the underlying flash
84 // device.
85 pub fn add_simple_image(&mut self, base: usize, len: usize, id: FlashId) {
86 let area = vec![FlashArea {
87 flash_id: id,
88 device_id: 42,
89 pad16: 0,
90 off: base as u32,
91 size: len as u32,
92 }];
93
94 self.areas.push(area);
95 self.whole.push(FlashArea {
96 flash_id: id,
97 device_id: 42,
98 pad16: 0,
99 off: base as u32,
100 size: len as u32,
101 });
102 }
103
David Brown5c6b6792017-03-20 12:51:28 -0600104 // Look for the image with the given ID, and return its base and size. Panics if the area is
105 // not present.
106 pub fn find(&self, id: FlashId) -> (usize, usize) {
107 for area in &self.whole {
108 if area.flash_id == id {
109 return (area.off as usize, area.size as usize);
110 }
111 }
112 panic!("Requesting area that is not present in flash");
113 }
114
David Brownde7729e2017-01-09 10:41:35 -0700115 pub fn get_c(&self) -> CAreaDesc {
116 let mut areas: CAreaDesc = Default::default();
117
118 assert_eq!(self.areas.len(), self.whole.len());
119
120 for (i, area) in self.areas.iter().enumerate() {
121 if area.len() > 0 {
122 areas.slots[i].areas = &area[0];
123 areas.slots[i].whole = self.whole[i].clone();
124 areas.slots[i].num_areas = area.len() as u32;
125 areas.slots[i].id = area[0].flash_id;
126 }
127 }
128
129 areas.num_slots = self.areas.len() as u32;
130
131 areas
132 }
133}
134
135/// The area descriptor, C format.
136#[repr(C)]
137#[derive(Debug, Default)]
David Brown0daa36c2017-03-07 12:08:27 +0100138pub struct CAreaDesc {
139 slots: [CArea; 16],
David Brownde7729e2017-01-09 10:41:35 -0700140 num_slots: u32,
141}
142
143#[repr(C)]
144#[derive(Debug)]
David Brown0daa36c2017-03-07 12:08:27 +0100145pub struct CArea {
David Brownde7729e2017-01-09 10:41:35 -0700146 whole: FlashArea,
147 areas: *const FlashArea,
148 num_areas: u32,
149 id: FlashId,
David Brownde7729e2017-01-09 10:41:35 -0700150}
151
David Brown0daa36c2017-03-07 12:08:27 +0100152impl Default for CArea {
153 fn default() -> CArea {
David Brownde7729e2017-01-09 10:41:35 -0700154 CArea {
155 areas: ptr::null(),
156 whole: Default::default(),
157 id: FlashId::BootLoader,
158 num_areas: 0,
David Brownde7729e2017-01-09 10:41:35 -0700159 }
160 }
161}
162
163/// Flash area map.
164#[repr(u8)]
165#[derive(Copy, Clone, Debug, Eq, PartialEq)]
166#[allow(dead_code)]
167pub enum FlashId {
168 BootLoader = 0,
169 Image0 = 1,
170 Image1 = 2,
171 ImageScratch = 3,
172 Nffs = 4,
173 Core = 5,
174 RebootLog = 6
175}
176
177impl Default for FlashId {
178 fn default() -> FlashId {
179 FlashId::BootLoader
180 }
181}
182
183#[repr(C)]
184#[derive(Debug, Clone, Default)]
185pub struct FlashArea {
186 flash_id: FlashId,
187 device_id: u8,
188 pad16: u16,
189 off: u32,
190 size: u32,
191}
192