Skip to content

Commit a2e2d9f

Browse files
author
George Cosma
committed
wip2
Signed-off-by: George Cosma <george.cosma@wyliodrin.com>
1 parent 0e7196c commit a2e2d9f

12 files changed

Lines changed: 176 additions & 167 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
#[derive(Debug)]
1616
pub struct AppAttributes {
@@ -52,9 +52,7 @@ impl AppAttributes {
5252
loop {
5353
let mut appdata = vec![0u8; 8];
5454

55-
board_core
56-
.read(appaddr, &mut appdata)
57-
.map_err(TockloaderError::ProbeRsReadError)?;
55+
board_core.read(appaddr, &mut appdata)?;
5856

5957
let tbf_version: u16;
6058
let header_size: u16;
@@ -75,11 +73,9 @@ impl AppAttributes {
7573

7674
let mut header_data = vec![0u8; header_size as usize];
7775

78-
board_core
79-
.read(appaddr, &mut header_data)
80-
.map_err(TockloaderError::ProbeRsReadError)?;
76+
board_core.read(appaddr, &mut header_data)?;
8177
let header = parse_tbf_header(&header_data, tbf_version)
82-
.map_err(TockloaderError::ParsingError)?;
78+
.map_err(TockError::InvalidAppTbfHeader)?;
8379

8480
let binary_end_offset = header.get_binary_end();
8581

@@ -92,12 +88,10 @@ impl AppAttributes {
9288
let mut appfooter =
9389
vec![0u8; (total_footers_size - (footer_offset - binary_end_offset)) as usize];
9490

95-
board_core
96-
.read(appaddr + footer_offset as u64, &mut appfooter)
97-
.map_err(TockloaderError::ProbeRsReadError)?;
91+
board_core.read(appaddr + footer_offset as u64, &mut appfooter)?;
9892

9993
let footer_info =
100-
parse_tbf_footer(&appfooter).map_err(TockloaderError::ParsingError)?;
94+
parse_tbf_footer(&appfooter).map_err(TockError::InvalidAppTbfHeader)?;
10195

10296
footers.insert(footer_number, TbfFooter::new(footer_info.0, footer_info.1));
10397

@@ -170,7 +164,7 @@ impl AppAttributes {
170164
.await?;
171165

172166
let header = parse_tbf_header(&header_data, tbf_version)
173-
.map_err(TockloaderError::ParsingError)?;
167+
.map_err(TockError::InvalidAppTbfHeader)?;
174168
let binary_end_offset = header.get_binary_end();
175169

176170
let mut footers: Vec<TbfFooter> = vec![];
@@ -198,7 +192,7 @@ impl AppAttributes {
198192
.await?;
199193

200194
let footer_info =
201-
parse_tbf_footer(&appfooter).map_err(TockloaderError::ParsingError)?;
195+
parse_tbf_footer(&appfooter).map_err(TockError::InvalidAppTbfHeader)?;
202196

203197
footers.insert(footer_number, TbfFooter::new(footer_info.0, footer_info.1));
204198

tockloader-lib/src/attributes/system_attributes.rs

Lines changed: 10 additions & 18 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::{TockError, TockloaderError};
1111

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

@@ -81,9 +81,7 @@ impl SystemAttributes {
8181
16,
8282
)
8383
.map_err(|_| {
84-
TockloaderError::MisconfiguredBoard(
85-
"Invalid start address.".to_owned(),
86-
)
84+
TockError::MisconfiguredBoard("Invalid start address.".to_owned())
8785
})?,
8886
);
8987
}
@@ -104,7 +102,7 @@ impl SystemAttributes {
104102
let _ = board_core.read_8(address, &mut buf);
105103

106104
let string = String::from_utf8(buf.to_vec()).map_err(|_| {
107-
TockloaderError::MisconfiguredBoard(
105+
TockError::MisconfiguredBoard(
108106
"Data may be corrupted. System attribure is not UTF-8.".to_owned(),
109107
)
110108
})?;
@@ -114,14 +112,10 @@ impl SystemAttributes {
114112
result.bootloader_version = Some(string.to_owned());
115113

116114
let mut kernel_attr_binary = [0u8; 100];
117-
board_core
118-
.read(
119-
result.appaddr.ok_or(TockloaderError::MisconfiguredBoard(
120-
"No start address found.".to_owned(),
121-
))? - 100,
122-
&mut kernel_attr_binary,
123-
)
124-
.map_err(TockloaderError::ProbeRsReadError)?;
115+
let kernel_attr_addr = result.appaddr.ok_or(TockError::MisconfiguredBoard(
116+
"No start address found.".to_owned(),
117+
))? - 100;
118+
board_core.read(kernel_attr_addr, &mut kernel_attr_binary)?;
125119

126120
let sentinel = bytes_to_string(&kernel_attr_binary[96..100]);
127121
let kernel_version = LittleEndian::read_uint(&kernel_attr_binary[95..96], 1);
@@ -192,9 +186,7 @@ impl SystemAttributes {
192186
16,
193187
)
194188
.map_err(|_| {
195-
TockloaderError::MisconfiguredBoard(
196-
"Invalid start address.".to_owned(),
197-
)
189+
TockError::MisconfiguredBoard("Invalid start address.".to_owned())
198190
})?,
199191
);
200192
}
@@ -218,7 +210,7 @@ impl SystemAttributes {
218210
issue_command(port, Command::ReadRange, pkt, true, 8, Response::ReadRange).await?;
219211

220212
let string = String::from_utf8(buf).map_err(|_| {
221-
TockloaderError::MisconfiguredBoard(
213+
TockError::MisconfiguredBoard(
222214
"Data may be corrupted. System attribure is not UTF-8.".to_owned(),
223215
)
224216
})?;
@@ -227,7 +219,7 @@ impl SystemAttributes {
227219

228220
result.bootloader_version = Some(string.to_owned());
229221

230-
let mut pkt = ((result.appaddr.ok_or(TockloaderError::MisconfiguredBoard(
222+
let mut pkt = ((result.appaddr.ok_or(TockError::MisconfiguredBoard(
231223
"No start address found.".to_owned(),
232224
))? - 100) as u32)
233225
.to_le_bytes()

tockloader-lib/src/bootloader_serial.rs

Lines changed: 75 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,36 @@ 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+
while i < input.len() {
227+
if i + 1 < input.len() && input[i] == ESCAPE_CHAR && input[i + 1] == ESCAPE_CHAR {
228+
// Found consecutive ESCAPE_CHAR bytes, add only one
229+
result.push(ESCAPE_CHAR);
230+
i += 2; // Skip both bytes
231+
} else {
232+
// Not consecutive ESCAPE_CHAR, add the current byte
233+
result.push(input[i]);
234+
i += 1;
212235
}
213236
}
214237

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

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)