Skip to content

Commit 777ec94

Browse files
George Cosmaeva-cosma
authored andcommitted
chore: refactor errors
Signed-off-by: George Cosma <george.cosma@wyliodrin.com>
1 parent d3c5ff7 commit 777ec94

13 files changed

Lines changed: 267 additions & 223 deletions

File tree

tockloader-lib/src/attributes/app_attributes.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use tbf_parser::{self};
1010
use tokio_serial::SerialStream;
1111

1212
use crate::bootloader_serial::{issue_command, Command, Response};
13-
use crate::errors::TockloaderError;
13+
use crate::errors::{TockError, TockloaderError};
1414

1515
/// This structure contains all relevant information about a tock application.
1616
///
@@ -74,9 +74,7 @@ impl AppAttributes {
7474
loop {
7575
let mut appdata = vec![0u8; 8];
7676

77-
board_core
78-
.read(appaddr, &mut appdata)
79-
.map_err(TockloaderError::ProbeRsReadError)?;
77+
board_core.read(appaddr, &mut appdata)?;
8078

8179
let tbf_version: u16;
8280
let header_size: u16;
@@ -102,11 +100,9 @@ impl AppAttributes {
102100

103101
let mut header_data = vec![0u8; header_size as usize];
104102

105-
board_core
106-
.read(appaddr, &mut header_data)
107-
.map_err(TockloaderError::ProbeRsReadError)?;
103+
board_core.read(appaddr, &mut header_data)?;
108104
let header = parse_tbf_header(&header_data, tbf_version)
109-
.map_err(TockloaderError::ParsingError)?;
105+
.map_err(TockError::InvalidAppTbfHeader)?;
110106

111107
// The end of the application binary marks the beginning of the
112108
// footer.
@@ -129,12 +125,10 @@ impl AppAttributes {
129125
let mut appfooter =
130126
vec![0u8; (total_footers_size - (footer_offset - binary_end_offset)) as usize];
131127

132-
board_core
133-
.read(appaddr + footer_offset as u64, &mut appfooter)
134-
.map_err(TockloaderError::ProbeRsReadError)?;
128+
board_core.read(appaddr + footer_offset as u64, &mut appfooter)?;
135129

136130
let footer_info =
137-
parse_tbf_footer(&appfooter).map_err(TockloaderError::ParsingError)?;
131+
parse_tbf_footer(&appfooter).map_err(TockError::InvalidAppTbfHeader)?;
138132

139133
footers.insert(footer_number, TbfFooter::new(footer_info.0, footer_info.1));
140134

@@ -231,7 +225,7 @@ impl AppAttributes {
231225
.await?;
232226

233227
let header = parse_tbf_header(&header_data, tbf_version)
234-
.map_err(TockloaderError::ParsingError)?;
228+
.map_err(TockError::InvalidAppTbfHeader)?;
235229
let binary_end_offset = header.get_binary_end();
236230

237231
let mut footers: Vec<TbfFooter> = vec![];
@@ -264,7 +258,7 @@ impl AppAttributes {
264258
.await?;
265259

266260
let footer_info =
267-
parse_tbf_footer(&appfooter).map_err(TockloaderError::ParsingError)?;
261+
parse_tbf_footer(&appfooter).map_err(TockError::InvalidAppTbfHeader)?;
268262

269263
footers.insert(footer_number, TbfFooter::new(footer_info.0, footer_info.1));
270264

tockloader-lib/src/attributes/system_attributes.rs

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use probe_rs::{Core, MemoryInterface};
77
use tokio_serial::SerialStream;
88

99
use crate::bootloader_serial::{issue_command, Command, Response};
10-
use crate::errors::TockloaderError;
10+
use crate::errors::{AttributeParseError, TockError, TockloaderError};
1111

1212
use super::decode::{bytes_to_string, decode_attribute};
1313

@@ -72,7 +72,7 @@ impl SystemAttributes {
7272
// Each attribute is 64 bytes exactly, and there are 16 slots
7373
let mut buf = [0u8; 64 * 16];
7474

75-
let _ = board_core.read(address, &mut buf);
75+
board_core.read(address, &mut buf)?;
7676

7777
let mut data = buf.chunks(64);
7878

@@ -107,10 +107,8 @@ impl SystemAttributes {
107107
.trim_start_matches("0x"),
108108
16,
109109
)
110-
.map_err(|_| {
111-
TockloaderError::MisconfiguredBoard(
112-
"Invalid start address.".to_owned(),
113-
)
110+
.map_err(|e| {
111+
TockError::AttributeParsing(AttributeParseError::InvalidNumber(e))
114112
})?,
115113
);
116114
}
@@ -129,28 +127,22 @@ impl SystemAttributes {
129127
let address = 0x40E;
130128
let mut buf = [0u8; 8];
131129

132-
let _ = board_core.read_8(address, &mut buf);
130+
board_core.read_8(address, &mut buf)?;
133131

134-
let string = String::from_utf8(buf.to_vec()).map_err(|_| {
135-
TockloaderError::MisconfiguredBoard(
136-
"Data may be corrupted. System attribure is not UTF-8.".to_owned(),
137-
)
138-
})?;
132+
let string = String::from_utf8(buf.to_vec())
133+
.map_err(|e| TockError::AttributeParsing(AttributeParseError::InvalidString(e)))?;
139134

140135
let string = string.trim_matches(char::from(0));
141136

142137
result.bootloader_version = Some(string.to_owned());
143138

144139
// The 100 bytes prior to the application start address are reserved for the kernel attributes and flags
145140
let mut kernel_attr_binary = [0u8; 100];
146-
board_core
147-
.read(
148-
result.appaddr.ok_or(TockloaderError::MisconfiguredBoard(
149-
"No start address found.".to_owned(),
150-
))? - 100,
151-
&mut kernel_attr_binary,
152-
)
153-
.map_err(TockloaderError::ProbeRsReadError)?;
141+
let kernel_attr_addr = result
142+
.appaddr
143+
.ok_or(TockError::MissingAttribute("appaddr".to_owned()))?
144+
- 100;
145+
board_core.read(kernel_attr_addr, &mut kernel_attr_binary)?;
154146

155147
let sentinel = bytes_to_string(&kernel_attr_binary[96..100]);
156148
let kernel_version = LittleEndian::read_uint(&kernel_attr_binary[95..96], 1);
@@ -234,10 +226,8 @@ impl SystemAttributes {
234226
.trim_start_matches("0x"),
235227
16,
236228
)
237-
.map_err(|_| {
238-
TockloaderError::MisconfiguredBoard(
239-
"Invalid start address.".to_owned(),
240-
)
229+
.map_err(|e| {
230+
TockError::AttributeParsing(AttributeParseError::InvalidNumber(e))
241231
})?,
242232
);
243233
}
@@ -263,24 +253,20 @@ impl SystemAttributes {
263253
let (_, buf) =
264254
issue_command(port, Command::ReadRange, pkt, true, 8, Response::ReadRange).await?;
265255

266-
let string = String::from_utf8(buf).map_err(|_| {
267-
TockloaderError::MisconfiguredBoard(
268-
"Data may be corrupted. System attribure is not UTF-8.".to_owned(),
269-
)
270-
})?;
256+
let string = String::from_utf8(buf)
257+
.map_err(|e| TockError::AttributeParsing(AttributeParseError::InvalidString(e)))?;
271258

272259
// Strip null bytes
273260
let string = string.trim_matches(char::from(0));
274261
result.bootloader_version = Some(string.to_owned());
275262

276263
// The 100 bytes prior to the application start address are reserved
277264
// for the kernel attributes and flags
278-
let mut pkt = ((result.appaddr.ok_or(TockloaderError::MisconfiguredBoard(
279-
"No start address found.".to_owned(),
280-
))? - 100) as u32)
281-
.to_le_bytes()
282-
.to_vec();
283-
265+
let kernel_attr_addr = (result
266+
.appaddr
267+
.ok_or(TockError::MissingAttribute("appaddr".to_owned()))?
268+
- 100) as u32;
269+
let mut pkt = kernel_attr_addr.to_le_bytes().to_vec();
284270
let length = (100_u16).to_le_bytes().to_vec();
285271
for i in length {
286272
pkt.push(i);

tockloader-lib/src/bootloader_serial.rs

Lines changed: 76 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
// The "X" commands are for external flash
66

7-
use crate::errors;
7+
use crate::errors::{self, InternalError, TockError};
88
use bytes::BytesMut;
99
use errors::TockloaderError;
1010
use std::time::Duration;
@@ -17,6 +17,8 @@ pub const SYNC_MESSAGE: [u8; 3] = [0x00, 0xFC, 0x05];
1717
// "This was chosen as it is infrequent in .bin files" - immesys
1818
pub const ESCAPE_CHAR: u8 = 0xFC;
1919

20+
pub const DEFAULT_TIMEOUT: Duration = Duration::from_millis(500);
21+
2022
#[allow(dead_code)]
2123
pub enum Command {
2224
// Commands from this tool to the bootloader
@@ -99,46 +101,77 @@ impl From<u8> for Response {
99101
pub async fn toggle_bootloader_entry_dtr_rts(
100102
port: &mut SerialStream,
101103
) -> Result<(), TockloaderError> {
102-
port.write_data_terminal_ready(true)
103-
.map_err(TockloaderError::SerialInitializationError)?;
104-
port.write_request_to_send(true)
105-
.map_err(TockloaderError::SerialInitializationError)?;
104+
port.write_data_terminal_ready(true)?;
105+
port.write_request_to_send(true)?;
106106

107107
tokio::time::sleep(Duration::from_millis(100)).await;
108108

109-
port.write_data_terminal_ready(false)
110-
.map_err(TockloaderError::SerialInitializationError)?;
109+
port.write_data_terminal_ready(false)?;
111110

112111
tokio::time::sleep(Duration::from_millis(500)).await;
113112

114-
port.write_request_to_send(false)
115-
.map_err(TockloaderError::SerialInitializationError)?;
113+
port.write_request_to_send(false)?;
116114

117115
Ok(())
118116
}
119117

118+
async fn read_bytes(
119+
port: &mut SerialStream,
120+
bytes_to_read: usize,
121+
timeout: Duration,
122+
) -> Result<BytesMut, TockloaderError> {
123+
let mut ret = BytesMut::with_capacity(bytes_to_read);
124+
let mut read_bytes = 0;
125+
126+
tokio::time::timeout(timeout, async {
127+
while read_bytes < bytes_to_read {
128+
read_bytes += port
129+
.read_buf(&mut ret)
130+
.await
131+
.map_err(|e| TockloaderError::Serial(e.into()))?;
132+
}
133+
Ok(ret)
134+
})
135+
.await
136+
.map_err(|_| TockError::BootloaderTimeout)?
137+
}
138+
139+
async fn write_bytes(
140+
port: &mut SerialStream,
141+
bytes: &[u8],
142+
timeout: Duration,
143+
) -> Result<(), TockloaderError> {
144+
let mut bytes_written = 0;
145+
146+
tokio::time::timeout(timeout, async {
147+
while bytes_written != bytes.len() {
148+
bytes_written += port
149+
.write_buf(&mut &bytes[bytes_written..])
150+
.await
151+
.map_err(|e| TockloaderError::Serial(e.into()))?;
152+
}
153+
Ok(())
154+
})
155+
.await
156+
.map_err(|_| TockError::BootloaderTimeout)?
157+
}
158+
120159
#[allow(dead_code)]
121160
pub async fn ping_bootloader_and_wait_for_response(
122161
port: &mut SerialStream,
123-
) -> Result<Response, TockloaderError> {
162+
) -> Result<(), TockloaderError> {
124163
let ping_pkt = [ESCAPE_CHAR, Command::Ping as u8];
125164

126-
let mut ret = BytesMut::with_capacity(200);
127-
128165
for _ in 0..30 {
129-
let mut bytes_written = 0;
130-
while bytes_written != ping_pkt.len() {
131-
bytes_written += port.write_buf(&mut &ping_pkt[bytes_written..]).await?;
132-
}
133-
let mut read_bytes = 0;
134-
while read_bytes < 2 {
135-
read_bytes += port.read_buf(&mut ret).await?;
136-
}
166+
write_bytes(port, &ping_pkt, DEFAULT_TIMEOUT).await?;
167+
let ret = read_bytes(port, 2, DEFAULT_TIMEOUT).await?;
168+
137169
if ret[1] == Response::Pong as u8 {
138-
return Ok(Response::from(ret[1]));
170+
return Ok(());
139171
}
140172
}
141-
Ok(Response::from(ret[1]))
173+
174+
Err(InternalError::BootloaderNotPresent.into())
142175
}
143176

144177
#[allow(dead_code)]
@@ -174,46 +207,37 @@ pub async fn issue_command(
174207
}
175208

176209
// Write the command message
177-
let mut bytes_written = 0;
178-
while bytes_written != message.len() {
179-
bytes_written += port.write_buf(&mut &message[bytes_written..]).await?;
180-
}
210+
write_bytes(port, &message, DEFAULT_TIMEOUT).await?;
181211

182212
// Response has a two byte header, then response_len bytes
183-
let bytes_to_read = 2 + response_len;
184-
let mut ret = BytesMut::with_capacity(2);
213+
let header = read_bytes(port, 2, DEFAULT_TIMEOUT).await?;
185214

186-
// We are waiting for 2 bytes to be read
187-
let mut read_bytes = 0;
188-
while read_bytes < 2 {
189-
read_bytes += port.read_buf(&mut ret).await?;
215+
if header[0..2] != [ESCAPE_CHAR, response_code as u8] {
216+
return Err(TockError::BootloaderBadHeader(header[0], header[1]).into());
190217
}
191218

192-
if ret[0] != ESCAPE_CHAR {
193-
return Err(TockloaderError::BootloaderError(ret[0]));
194-
}
195-
196-
if ret[1] != response_code.clone() as u8 {
197-
return Err(TockloaderError::BootloaderError(ret[1]));
198-
}
199-
200-
let mut new_data: Vec<u8> = Vec::new();
201-
let mut value = 2;
202-
203219
if response_len != 0 {
204-
while bytes_to_read > value {
205-
value += port.read_buf(&mut new_data).await?;
206-
}
220+
let input = read_bytes(port, response_len, DEFAULT_TIMEOUT).await?;
221+
let mut result = Vec::with_capacity(input.len());
207222

208223
// De-escape and add array of read in the bytes
209-
for i in 0..(new_data.len() - 1) {
210-
if new_data[i] == ESCAPE_CHAR && new_data[i + 1] == ESCAPE_CHAR {
211-
new_data.remove(i + 1);
224+
225+
// TODO(george-cosma): Extract this into a function and unit test this.
226+
let mut i = 0;
227+
while i < input.len() {
228+
if i + 1 < input.len() && input[i] == ESCAPE_CHAR && input[i + 1] == ESCAPE_CHAR {
229+
// Found consecutive ESCAPE_CHAR bytes, add only one
230+
result.push(ESCAPE_CHAR);
231+
i += 2; // Skip both bytes
232+
} else {
233+
// Not consecutive ESCAPE_CHAR, add the current byte
234+
result.push(input[i]);
235+
i += 1;
212236
}
213237
}
214238

215-
ret.extend_from_slice(&new_data);
239+
Ok((Response::from(header[1]), result))
240+
} else {
241+
Ok((Response::from(header[1]), vec![]))
216242
}
217-
218-
Ok((Response::from(ret[1]), ret[2..].to_vec()))
219243
}

tockloader-lib/src/command_impl/probers/info.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::attributes::general_attributes::GeneralAttributes;
55
use crate::attributes::system_attributes::SystemAttributes;
66
use crate::board_settings::BoardSettings;
77
use crate::connection::{Connection, ProbeRSConnection};
8-
use crate::errors::TockloaderError;
8+
use crate::errors::{InternalError, TockloaderError};
99
use crate::CommandInfo;
1010

1111
#[async_trait]
@@ -15,13 +15,11 @@ impl CommandInfo for ProbeRSConnection {
1515
settings: &BoardSettings,
1616
) -> Result<GeneralAttributes, TockloaderError> {
1717
if !self.is_open() {
18-
return Err(TockloaderError::ConnectionNotOpen);
18+
return Err(InternalError::ConnectionNotOpen.into());
1919
}
2020
let session = self.session.as_mut().expect("Board must be open");
2121

22-
let mut core = session
23-
.core(self.target_info.core)
24-
.map_err(|e| TockloaderError::CoreAccessError(self.target_info.core, e))?;
22+
let mut core = session.core(self.target_info.core)?;
2523

2624
// TODO(george-cosma): extract these informations without bootloader
2725
let system_attributes = SystemAttributes::read_system_attributes_probe(&mut core)?;

0 commit comments

Comments
 (0)