Skip to content

Commit 68d86ef

Browse files
committed
add check that the subtype is valid for the partition type
1 parent fcd113c commit 68d86ef

File tree

3 files changed

+110
-9
lines changed

3 files changed

+110
-9
lines changed

espflash/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ slip-codec = "0.2.4"
2626
thiserror = "1.0.20"
2727
xmas-elf = "0.8.0"
2828
serde = { version = "1.0", features = ["derive"] }
29+
serde_plain = "1"
2930
toml = "0.5"
3031
directories-next = "2.0.0"
3132
color-eyre = "0.5"

espflash/src/error.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::flasher::Command;
22
use crate::image_format::ImageFormatId;
3+
use crate::partition_table::{SubType, Type};
34
use crate::Chip;
45
use miette::{Diagnostic, SourceOffset, SourceSpan};
56
use slip_codec::Error as SlipError;
@@ -276,6 +277,9 @@ pub enum PartitionTableError {
276277
#[error(transparent)]
277278
#[diagnostic(transparent)]
278279
Duplicate(#[from] DuplicatePartitionsError),
280+
#[error(transparent)]
281+
#[diagnostic(transparent)]
282+
InvalidSubType(#[from] InvalidSubTypeError),
279283
}
280284

281285
#[derive(Debug, Error, Diagnostic)]
@@ -384,6 +388,32 @@ impl DuplicatePartitionsError {
384388
}
385389
}
386390

391+
#[derive(Debug, Error, Diagnostic)]
392+
#[error("Invalid subtype for type")]
393+
#[diagnostic(
394+
code(espflash::partition_table::invalid_type),
395+
help("'{}' supports the following subtypes: {}", self.ty, self.ty.subtype_hint())
396+
)]
397+
pub struct InvalidSubTypeError {
398+
#[source_code]
399+
source_code: String,
400+
#[label("'{}' is not a valid subtype for '{}'", self.sub_type, self.ty)]
401+
span: SourceSpan,
402+
ty: Type,
403+
sub_type: SubType,
404+
}
405+
406+
impl InvalidSubTypeError {
407+
pub fn new(source: &str, line: usize, ty: Type, sub_type: SubType) -> Self {
408+
InvalidSubTypeError {
409+
source_code: source.into(),
410+
span: line_to_span(&source, line),
411+
ty,
412+
sub_type,
413+
}
414+
}
415+
}
416+
387417
#[derive(Debug, Error)]
388418
#[error("{0}")]
389419
pub struct ElfError(&'static str);

espflash/src/partition_table.rs

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
use md5::{Context, Digest};
2-
use regex::Regex;
3-
use serde::{Deserialize, Deserializer};
4-
51
use crate::error::{
6-
CSVError, DuplicatePartitionsError, OverlappingPartitionsError, PartitionTableError,
2+
CSVError, DuplicatePartitionsError, InvalidSubTypeError, OverlappingPartitionsError,
3+
PartitionTableError,
74
};
5+
use md5::{Context, Digest};
6+
use regex::Regex;
7+
use serde::{Deserialize, Deserializer, Serialize};
88
use std::cmp::{max, min};
9+
use std::fmt::Write as _;
10+
use std::fmt::{Display, Formatter};
911
use std::io::Write;
1012

1113
const MAX_PARTITION_LENGTH: usize = 0xC00;
1214
const PARTITION_TABLE_SIZE: usize = 0x1000;
1315

14-
#[derive(Copy, Clone, Debug, Deserialize)]
16+
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq)]
1517
#[repr(u8)]
1618
#[allow(dead_code)]
1719
#[serde(rename_all = "lowercase")]
@@ -20,7 +22,46 @@ pub enum Type {
2022
Data = 0x01,
2123
}
2224

23-
#[derive(Copy, Clone, Debug, Deserialize, PartialEq)]
25+
impl Type {
26+
pub fn subtype_hint(&self) -> String {
27+
match self {
28+
Type::App => "'factory', 'ota_0' trough 'ota_15' and 'test'".into(),
29+
Type::Data => {
30+
let types = [
31+
DataType::Ota,
32+
DataType::Phy,
33+
DataType::Nvs,
34+
DataType::CoreDump,
35+
DataType::NvsKeys,
36+
DataType::EFuse,
37+
DataType::EspHttpd,
38+
DataType::Fat,
39+
DataType::Spiffs,
40+
];
41+
42+
let mut out = format!("'{}'", serde_plain::to_string(&types[0]).unwrap());
43+
for ty in &types[1..types.len() - 2] {
44+
let ser = serde_plain::to_string(&ty).unwrap();
45+
write!(&mut out, ", '{}'", ser).unwrap();
46+
}
47+
48+
let ser = serde_plain::to_string(&types[types.len() - 1]).unwrap();
49+
write!(&mut out, " and '{}'", ser).unwrap();
50+
51+
out
52+
}
53+
}
54+
}
55+
}
56+
57+
impl Display for Type {
58+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
59+
let ser = serde_plain::to_string(self).unwrap();
60+
write!(f, "{}", ser)
61+
}
62+
}
63+
64+
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq)]
2465
#[repr(u8)]
2566
#[allow(dead_code)]
2667
#[serde(rename_all = "lowercase")]
@@ -61,7 +102,7 @@ pub enum AppType {
61102
Test = 0x20,
62103
}
63104

64-
#[derive(Copy, Clone, Debug, Deserialize, PartialEq)]
105+
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq)]
65106
#[repr(u8)]
66107
#[allow(dead_code)]
67108
#[serde(rename_all = "lowercase")]
@@ -78,14 +119,25 @@ pub enum DataType {
78119
Spiffs = 0x82,
79120
}
80121

81-
#[derive(Debug, Deserialize, PartialEq)]
122+
#[derive(Debug, Deserialize, PartialEq, Copy, Clone)]
82123
#[allow(dead_code)]
83124
#[serde(untagged)]
84125
pub enum SubType {
85126
App(AppType),
86127
Data(DataType),
87128
}
88129

130+
impl Display for SubType {
131+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
132+
let ser = match self {
133+
SubType::App(sub) => serde_plain::to_string(sub),
134+
SubType::Data(sub) => serde_plain::to_string(sub),
135+
}
136+
.unwrap();
137+
write!(f, "{}", ser)
138+
}
139+
}
140+
89141
impl SubType {
90142
fn as_u8(&self) -> u8 {
91143
match self {
@@ -194,6 +246,24 @@ impl PartitionTable {
194246
}
195247

196248
fn validate(&self, source: &str) -> Result<(), PartitionTableError> {
249+
for partition in &self.partitions {
250+
if let Some(line) = &partition.line {
251+
let expected_type = match partition.sub_type {
252+
SubType::App(_) => Type::App,
253+
SubType::Data(_) => Type::Data,
254+
};
255+
if expected_type != partition.ty {
256+
return Err(InvalidSubTypeError::new(
257+
source,
258+
*line,
259+
partition.ty,
260+
partition.sub_type,
261+
)
262+
.into());
263+
}
264+
}
265+
}
266+
197267
for partition1 in &self.partitions {
198268
for partition2 in &self.partitions {
199269
if let (Some(line1), Some(line2)) = (&partition1.line, &partition2.line) {

0 commit comments

Comments
 (0)