1use esp_idf_part::{Flags, Partition, PartitionTable, SubType, Type};
3
4use crate::{
5 Memory,
6 layout::{Layout, ResolvedLayout},
7 section::{ResolvedSection, Section},
8};
9
10pub type EspSection = Section<EspMetaData>;
12pub type EspLayout = Layout<EspMetaData>;
14pub type EspMemory = Memory<EspMetaData>;
16
17#[derive(Clone, Debug)]
19pub struct EspMetaData {
20 pub partition_type: esp_idf_part::Type,
22 pub partition_subtype: esp_idf_part::SubType,
24 pub flags: esp_idf_part::Flags,
26}
27
28impl EspMetaData {
29 #[must_use]
31 pub fn new(partition_type: Type, partition_subtype: SubType, flags: Flags) -> Self {
32 Self {
33 partition_type,
34 partition_subtype,
35 flags,
36 }
37 }
38
39 #[must_use]
41 pub fn set_flags(mut self, flags: Flags) -> Self {
42 self.flags = flags;
43 self
44 }
45}
46
47impl Section<()> {
48 #[must_use]
50 pub fn add_esp_metadata(self, partition_type: Type, subtype: impl Into<SubType>) -> EspSection {
51 let metadata = EspMetaData::new(partition_type, subtype.into(), Flags::empty());
52 self.replace_metadata(metadata)
53 }
54}
55
56impl Memory<()> {
57 #[must_use]
63 pub fn with_esp_metadata(self) -> EspMemory {
64 Memory {
65 chip: self.chip,
66 layout: self.layout.with_esp_metadata(),
67 }
68 }
69}
70
71impl Layout<()> {
72 #[must_use]
78 pub fn with_esp_metadata(self) -> EspLayout {
79 assert!(self.sections.is_empty());
80
81 Layout::empty()
82 }
83}
84
85impl Section<EspMetaData> {
86 #[must_use]
88 pub fn set_esp_flags(mut self, flags: Flags) -> Section<EspMetaData> {
89 self.metadata = self.metadata.set_flags(flags);
90 self
91 }
92}
93
94impl ResolvedSection<EspMetaData> {
95 #[cfg(feature = "esp")]
97 #[must_use]
98 #[allow(clippy::cast_possible_truncation)]
99 pub fn as_esp_partition(&self) -> Partition {
100 Partition::new(
101 &self.linker_name,
102 self.metadata.partition_type,
103 self.metadata.partition_subtype,
104 self.address as u32,
105 self.size as u32,
106 self.metadata.flags,
107 )
108 }
109}
110
111impl ResolvedLayout<EspMetaData> {
112 #[must_use]
114 pub fn into_esp_partition(&self) -> PartitionTable {
115 let partitions = self
116 .sections
117 .iter()
118 .map(ResolvedSection::as_esp_partition)
119 .collect();
120 PartitionTable::new(partitions)
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use esp_idf_part::{AppType, DataType};
127
128 use crate::{Memory, chip::Chip};
129
130 use super::*;
131
132 #[test]
133 fn default_layout() {
134 let esp_single_factory_app = "# ESP-IDF Partition Table\n\
135 # Name,Type,SubType,Offset,Size,Flags\n\
136 nvs,data,nvs,0x9000,0x6000,\n\
137 phy_init,data,phy,0xf000,0x1000,\n\
138 factory,app,factory,0x10000,0x100000,\n\
139 ";
140
141 let nvs = Section::new("nvs")
142 .unwrap()
143 .set_size(0x6000)
144 .set_address(0x9000)
145 .add_esp_metadata(Type::Data, DataType::Nvs);
146 let phy_init = Section::new("phy_init")
147 .unwrap()
148 .set_size(0x1000)
149 .set_address(0xf000)
150 .add_esp_metadata(Type::Data, DataType::Phy);
151 let factory = Section::new("factory")
152 .unwrap()
153 .set_size(1024 * 1024)
154 .set_address_align(64 * 1024)
155 .add_esp_metadata(Type::App, AppType::Factory);
156
157 let chip = Chip::new(512, 0, 2048 * 1048).unwrap();
158 let mut memory = Memory::new(chip);
159 memory.add_section(nvs);
160 memory.add_section(phy_init);
161 memory.add_section(factory);
162
163 let resolved = memory.resolve_layout().unwrap();
164
165 let csv = resolved.into_esp_partition().to_csv().unwrap();
166 assert_eq!(&csv, esp_single_factory_app);
167 }
168}