blob: 9bb7d5765dab5a78ae1ef358a0cdc1d5afb6460b [file] [log] [blame]
David Brownde7729e2017-01-09 10:41:35 -07001//! Describe flash areas.
2
3use flash::{Flash, Sector};
4use std::marker::PhantomData;
5use std::ptr;
6
7/// Structure to build up the boot area table.
8#[derive(Debug)]
9pub struct AreaDesc {
10 areas: Vec<Vec<FlashArea>>,
11 whole: Vec<FlashArea>,
12 sectors: Vec<Sector>,
13}
14
15impl AreaDesc {
16 pub fn new(flash: &Flash) -> AreaDesc {
17 AreaDesc {
18 areas: vec![],
19 whole: vec![],
20 sectors: flash.sector_iter().collect(),
21 }
22 }
23
24 /// Add a slot to the image. The slot must align with erasable units in the flash device.
25 /// Panics if the description is not valid. There are also bootloader assumptions that the
26 /// slots are SLOT0, SLOT1, and SCRATCH in that order.
27 pub fn add_image(&mut self, base: usize, len: usize, id: FlashId) {
28 let nid = id as usize;
29 let orig_base = base;
30 let orig_len = len;
31 let mut base = base;
32 let mut len = len;
33
34 while nid > self.areas.len() {
35 self.areas.push(vec![]);
36 self.whole.push(Default::default());
37 }
38
39 if nid != self.areas.len() {
40 panic!("Flash areas not added in order");
41 }
42
43 let mut area = vec![];
44
45 for sector in &self.sectors {
46 if len == 0 {
47 break;
48 };
49 if base > sector.base + sector.size - 1 {
50 continue;
51 }
52 if sector.base != base {
53 panic!("Image does not start on a sector boundary");
54 }
55
56 area.push(FlashArea {
57 flash_id: id,
58 device_id: 42,
59 pad16: 0,
60 off: sector.base as u32,
61 size: sector.size as u32,
62 });
63
64 base += sector.size;
65 len -= sector.size;
66 }
67
68 if len != 0 {
69 panic!("Image goes past end of device");
70 }
71
72 self.areas.push(area);
73 self.whole.push(FlashArea {
74 flash_id: id,
75 device_id: 42,
76 pad16: 0,
77 off: orig_base as u32,
78 size: orig_len as u32,
79 });
80 }
81
82 pub fn get_c(&self) -> CAreaDesc {
83 let mut areas: CAreaDesc = Default::default();
84
85 assert_eq!(self.areas.len(), self.whole.len());
86
87 for (i, area) in self.areas.iter().enumerate() {
88 if area.len() > 0 {
89 areas.slots[i].areas = &area[0];
90 areas.slots[i].whole = self.whole[i].clone();
91 areas.slots[i].num_areas = area.len() as u32;
92 areas.slots[i].id = area[0].flash_id;
93 }
94 }
95
96 areas.num_slots = self.areas.len() as u32;
97
98 areas
99 }
100}
101
102/// The area descriptor, C format.
103#[repr(C)]
104#[derive(Debug, Default)]
105pub struct CAreaDesc<'a> {
106 slots: [CArea<'a>; 16],
107 num_slots: u32,
108}
109
110#[repr(C)]
111#[derive(Debug)]
112pub struct CArea<'a> {
113 whole: FlashArea,
114 areas: *const FlashArea,
115 num_areas: u32,
116 id: FlashId,
117 phantom: PhantomData<&'a AreaDesc>,
118}
119
120impl<'a> Default for CArea<'a> {
121 fn default() -> CArea<'a> {
122 CArea {
123 areas: ptr::null(),
124 whole: Default::default(),
125 id: FlashId::BootLoader,
126 num_areas: 0,
127 phantom: PhantomData,
128 }
129 }
130}
131
132/// Flash area map.
133#[repr(u8)]
134#[derive(Copy, Clone, Debug, Eq, PartialEq)]
135#[allow(dead_code)]
136pub enum FlashId {
137 BootLoader = 0,
138 Image0 = 1,
139 Image1 = 2,
140 ImageScratch = 3,
141 Nffs = 4,
142 Core = 5,
143 RebootLog = 6
144}
145
146impl Default for FlashId {
147 fn default() -> FlashId {
148 FlashId::BootLoader
149 }
150}
151
152#[repr(C)]
153#[derive(Debug, Clone, Default)]
154pub struct FlashArea {
155 flash_id: FlashId,
156 device_id: u8,
157 pad16: u16,
158 off: u32,
159 size: u32,
160}
161