1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#![feature(stmt_expr_attributes)]
#![feature(bool_to_option)]
use std::{array::IntoIter, fmt::Display};
use features::{BootMetrics, FeatureConfiguration, Serial};
use memory::{external_flash, MemoryConfiguration};
use port::Port;
use security::{SecurityConfiguration, SecurityMode};
use serde::{Deserialize, Serialize};
pub mod port;
pub mod pins;
pub mod memory;
pub mod features;
pub mod security;
pub mod codegen;
#[derive(Serialize, Deserialize, Default, Debug)]
pub struct Configuration {
pub port: Port,
pub memory_configuration: MemoryConfiguration,
pub feature_configuration: FeatureConfiguration,
pub security_configuration: SecurityConfiguration,
}
impl Configuration {
pub fn complete(&self) -> bool { self.required_configuration_steps().count() == 0 }
pub fn required_feature_flags(&self) -> impl Iterator<Item = &'static str> {
let mut flags = vec![];
match self.port {
Port::Stm32F412 => flags.push("stm32f412"),
Port::Wgm160P => flags.push("wgm160p"),
};
if self.security_configuration.security_mode == SecurityMode::P256ECDSA {
flags.push("ecdsa-verify");
};
flags.into_iter()
}
pub fn required_configuration_steps(&self) -> impl Iterator<Item = RequiredConfigurationStep> {
#[rustfmt::skip]
IntoIter::new([
self.memory_configuration.internal_memory_map.bootable_index.is_none()
.then_some(RequiredConfigurationStep::BootableBank),
(self.security_configuration.security_mode == SecurityMode::P256ECDSA
&& self.security_configuration.verifying_key_raw.is_empty())
.then_some(RequiredConfigurationStep::PublicKey),
])
.flatten()
}
pub fn cleanup(&mut self) {
if !features::Serial::supported(&self.port) {
self.feature_configuration.serial = Serial::Disabled;
}
if !features::BootMetrics::timing_supported(&self.port) {
if let BootMetrics::Enabled{timing} = &mut self.feature_configuration.boot_metrics {
*timing = false
}
}
if !external_flash(&self.port).any(|f| Some(f) == self.memory_configuration.external_flash)
{
self.memory_configuration.external_flash = None;
}
if self.memory_configuration.external_flash.is_none() {
self.memory_configuration.external_memory_map.banks.clear();
}
}
}
pub enum RequiredConfigurationStep {
PublicKey,
SerialTxPin,
SerialRxPin,
BootableBank,
}
impl Display for RequiredConfigurationStep {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
RequiredConfigurationStep::PublicKey => {
"[Security] Provide P256 ECDSA public key or enable CRC32 mode"
}
RequiredConfigurationStep::SerialTxPin => "[Features] Define Serial Tx pin",
RequiredConfigurationStep::SerialRxPin => "[Features] Define Serial Rx pin",
RequiredConfigurationStep::BootableBank => "[Memory Map] Define a bootable bank",
})
}
}