Skip to content

Commit 92df482

Browse files
committed
feat: reshuffle_apps + generalized commands
Signed-off-by: addrian-77 <lunguadrian30@gmail.com>
1 parent fd458bd commit 92df482

File tree

25 files changed

+673
-598
lines changed

25 files changed

+673
-598
lines changed

tbf-parser/src/parse.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,10 @@ pub fn parse_tbf_header(
203203
}
204204
types::TbfHeaderTypes::TbfHeaderWriteableFlashRegions => {
205205
// Length must be a multiple of the size of a region definition.
206-
if tlv_header.length as usize
207-
% mem::size_of::<types::TbfHeaderV2WriteableFlashRegion>()
208-
== 0
206+
if (tlv_header.length as usize)
207+
.is_multiple_of(mem::size_of::<
208+
types::TbfHeaderV2WriteableFlashRegion,
209+
>())
209210
{
210211
// Calculate how many writeable flash regions
211212
// there are specified in this header.

tbf-parser/src/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,7 @@ pub struct TbfHeaderV2 {
866866
// Clippy suggests we box TbfHeaderV2. We can't really do that, since
867867
// we are runnning under no_std, and I don't think it's that big of a issue.
868868
#[allow(clippy::large_enum_variant)]
869+
#[derive(Clone)]
869870
pub enum TbfHeader {
870871
TbfHeaderV2(TbfHeaderV2),
871872
Padding(TbfHeaderV2Base),

tockloader-lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ serde = { version = "1.0.210", features = ["derive"] }
2121
thiserror = "1.0.63"
2222
async-trait = "0.1.88"
2323
log = "0.4.27"
24+
itertools = "0.14.0"

tockloader-lib/src/attributes/app_attributes.rs

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,41 @@ use tokio_serial::SerialStream;
1111

1212
use crate::bootloader_serial::{issue_command, Command, Response};
1313
use crate::errors::{TockError, TockloaderError};
14+
use crate::IOCommands;
1415

1516
/// This structure contains all relevant information about a tock application.
1617
///
1718
/// All data is stored either within [TbfHeader]s, or [TbfFooter]s.
1819
///
1920
/// See also <https://book.tockos.org/doc/tock_binary_format>
20-
#[derive(Debug)]
21+
#[derive(Debug, Clone)]
2122
pub struct AppAttributes {
23+
pub address: u64,
24+
pub size: u32,
25+
pub index: u8,
2226
pub tbf_header: TbfHeader,
2327
pub tbf_footers: Vec<TbfFooter>,
28+
pub installed: bool,
29+
pub is_padding: bool,
30+
}
31+
32+
impl std::fmt::Display for AppAttributes {
33+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34+
write!(
35+
f,
36+
"{}. {} - start: {:#x}, size: {}",
37+
self.index,
38+
self.tbf_header.get_package_name().unwrap_or(""),
39+
self.address,
40+
self.size
41+
)
42+
}
2443
}
2544

2645
/// This structure represents a footer of a Tock application. Currently, footers
2746
/// only contain credentials, which are used to verify the integrity of the
2847
/// application.
29-
#[derive(Debug)]
48+
#[derive(Debug, Clone)]
3049
pub struct TbfFooter {
3150
pub credentials: TbfFooterV2Credentials,
3251
pub size: u32,
@@ -41,10 +60,22 @@ impl TbfFooter {
4160
// TODO(george-cosma): Could take advantages of the trait rework
4261

4362
impl AppAttributes {
44-
pub(crate) fn new(header_data: TbfHeader, footers_data: Vec<TbfFooter>) -> AppAttributes {
63+
pub(crate) fn new(
64+
address: u64,
65+
size: u32,
66+
index: u8,
67+
header_data: TbfHeader,
68+
footers_data: Vec<TbfFooter>,
69+
installed: bool,
70+
) -> AppAttributes {
4571
AppAttributes {
72+
address,
73+
size,
74+
index,
4675
tbf_header: header_data,
4776
tbf_footers: footers_data,
77+
installed,
78+
is_padding: false,
4879
}
4980
}
5081

@@ -117,6 +148,11 @@ impl AppAttributes {
117148
// crash the process.
118149
let binary_end_offset = header.get_binary_end();
119150

151+
if !header.is_app() {
152+
appaddr += total_size as u64;
153+
continue;
154+
}
155+
120156
let mut footers: Vec<TbfFooter> = vec![];
121157
let total_footers_size = total_size - binary_end_offset;
122158
let mut footer_offset = binary_end_offset;
@@ -129,9 +165,9 @@ impl AppAttributes {
129165
// binary_end_offset`) , even if we overread.
130166
let mut appfooter =
131167
vec![0u8; (total_footers_size - (footer_offset - binary_end_offset)) as usize];
132-
168+
// log::info!("footer init {:?}", appfooter);
133169
board_core.read(appaddr + footer_offset as u64, &mut appfooter)?;
134-
170+
// log::info!("footer read {:?}", appfooter);
135171
let footer_info =
136172
parse_tbf_footer(&appfooter).map_err(TockError::InvalidAppTbfHeader)?;
137173

@@ -142,9 +178,10 @@ impl AppAttributes {
142178
footer_offset += footer_info.1 + 4;
143179
}
144180

145-
let details: AppAttributes = AppAttributes::new(header, footers);
181+
let details: AppAttributes =
182+
AppAttributes::new(appaddr, total_size, apps_counter, header, footers, true);
146183

147-
apps_details.insert(apps_counter, details);
184+
apps_details.insert(apps_counter.into(), details);
148185
apps_counter += 1;
149186
appaddr += total_size as u64;
150187
}
@@ -232,8 +269,14 @@ impl AppAttributes {
232269
log::debug!("App #{apps_counter}: Header data: {header_data:?}");
233270
let header = parse_tbf_header(&header_data, tbf_version)
234271
.map_err(TockError::InvalidAppTbfHeader)?;
272+
235273
let binary_end_offset = header.get_binary_end();
236274

275+
if !header.is_app() {
276+
appaddr += total_size as u64;
277+
continue;
278+
}
279+
237280
let mut footers: Vec<TbfFooter> = vec![];
238281
let total_footers_size = total_size - binary_end_offset;
239282
let mut footer_offset = binary_end_offset;
@@ -273,12 +316,17 @@ impl AppAttributes {
273316
footer_offset += footer_info.1 + 4;
274317
}
275318

276-
let details: AppAttributes = AppAttributes::new(header, footers);
319+
let details: AppAttributes =
320+
AppAttributes::new(appaddr, total_size, apps_counter, header, footers, true);
277321

278-
apps_details.insert(apps_counter, details);
322+
apps_details.insert(apps_counter.into(), details);
279323
apps_counter += 1;
280324
appaddr += total_size as u64;
281325
}
282326
Ok(apps_details)
283327
}
328+
329+
pub async fn read(&mut self, conn: &mut dyn IOCommands) -> Result<Vec<u8>, TockloaderError> {
330+
conn.read(self.address, self.size as usize).await
331+
}
284332
}

tockloader-lib/src/bootloader_serial.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// The "X" commands are for external flash
66

77
use crate::errors::{self, InternalError, TockError};
8-
use bytes::BytesMut;
8+
use bytes::{BufMut, BytesMut};
99
use errors::TockloaderError;
1010
use std::time::Duration;
1111
use tokio::io::{AsyncReadExt, AsyncWriteExt};
@@ -17,7 +17,7 @@ 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);
20+
pub const DEFAULT_TIMEOUT: Duration = Duration::from_millis(5000);
2121

2222
#[allow(dead_code)]
2323
pub enum Command {
@@ -217,7 +217,7 @@ pub async fn issue_command(
217217
}
218218

219219
if response_len != 0 {
220-
let input = read_bytes(port, response_len, DEFAULT_TIMEOUT).await?;
220+
let mut input = read_bytes(port, response_len, DEFAULT_TIMEOUT).await?;
221221
let mut result = Vec::with_capacity(input.len());
222222

223223
// De-escape and add array of read in the bytes
@@ -227,6 +227,7 @@ pub async fn issue_command(
227227
while i < input.len() {
228228
if i + 1 < input.len() && input[i] == ESCAPE_CHAR && input[i + 1] == ESCAPE_CHAR {
229229
// Found consecutive ESCAPE_CHAR bytes, add only one
230+
input.put(read_bytes(port, 1, DEFAULT_TIMEOUT).await?);
230231
result.push(ESCAPE_CHAR);
231232
i += 2; // Skip both bytes
232233
} else {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use async_trait::async_trait;
2+
3+
use crate::board_settings::BoardSettings;
4+
use crate::connection::TockloaderConnection;
5+
use crate::errors::TockloaderError;
6+
use crate::{CommandEraseApps, IOCommands};
7+
8+
#[async_trait]
9+
impl CommandEraseApps for TockloaderConnection {
10+
async fn erase_apps(&mut self, settings: &BoardSettings) -> Result<(), TockloaderError> {
11+
self.write(settings.start_address, [0x0].to_vec()).await
12+
}
13+
}
Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,42 @@
11
use async_trait::async_trait;
22

33
use crate::attributes::app_attributes::AppAttributes;
4-
use crate::attributes::general_attributes::GeneralAttributes;
4+
use crate::attributes::system_attributes::SystemAttributes;
55
use crate::board_settings::BoardSettings;
66
use crate::connection::TockloaderConnection;
77
use crate::errors::TockloaderError;
8-
use crate::tabs::tab::Tab;
9-
use crate::{CommandEraseApps, CommandInfo, CommandInstall, CommandList};
8+
use crate::IOCommands;
109

1110
#[async_trait]
12-
impl CommandList for TockloaderConnection {
13-
async fn list(
14-
&mut self,
15-
settings: &BoardSettings,
16-
) -> Result<Vec<AppAttributes>, TockloaderError> {
11+
impl IOCommands for TockloaderConnection {
12+
async fn read(&mut self, address: u64, size: usize) -> Result<Vec<u8>, TockloaderError> {
1713
match self {
18-
TockloaderConnection::ProbeRS(conn) => conn.list(settings).await,
19-
TockloaderConnection::Serial(conn) => conn.list(settings).await,
14+
TockloaderConnection::ProbeRS(conn) => conn.read(address, size).await,
15+
TockloaderConnection::Serial(conn) => conn.read(address, size).await,
2016
}
2117
}
22-
}
2318

24-
#[async_trait]
25-
impl CommandInfo for TockloaderConnection {
26-
async fn info(
27-
&mut self,
28-
settings: &BoardSettings,
29-
) -> Result<GeneralAttributes, TockloaderError> {
19+
async fn write(&mut self, address: u64, pkt: Vec<u8>) -> Result<(), TockloaderError> {
3020
match self {
31-
TockloaderConnection::ProbeRS(conn) => conn.info(settings).await,
32-
TockloaderConnection::Serial(conn) => conn.info(settings).await,
21+
TockloaderConnection::ProbeRS(conn) => conn.write(address, pkt).await,
22+
TockloaderConnection::Serial(conn) => conn.write(address, pkt).await,
3323
}
3424
}
35-
}
3625

37-
#[async_trait]
38-
impl CommandInstall for TockloaderConnection {
39-
async fn install_app(
26+
async fn list_apps(
4027
&mut self,
4128
settings: &BoardSettings,
42-
tab_file: Tab,
43-
) -> Result<(), TockloaderError> {
29+
) -> Result<Vec<AppAttributes>, TockloaderError> {
4430
match self {
45-
TockloaderConnection::ProbeRS(conn) => conn.install_app(settings, tab_file).await,
46-
TockloaderConnection::Serial(conn) => conn.install_app(settings, tab_file).await,
31+
TockloaderConnection::ProbeRS(conn) => conn.list_apps(settings).await,
32+
TockloaderConnection::Serial(conn) => conn.list_apps(settings).await,
4733
}
4834
}
49-
}
5035

51-
#[async_trait]
52-
impl CommandEraseApps for TockloaderConnection {
53-
async fn erase_apps(&mut self, settings: &BoardSettings) -> Result<(), TockloaderError> {
36+
async fn read_system_attributes(&mut self) -> Result<SystemAttributes, TockloaderError> {
5437
match self {
55-
TockloaderConnection::ProbeRS(conn) => conn.erase_apps(settings).await,
56-
TockloaderConnection::Serial(_conn) => todo!(),
38+
TockloaderConnection::ProbeRS(conn) => conn.read_system_attributes().await,
39+
TockloaderConnection::Serial(conn) => conn.read_system_attributes().await,
5740
}
5841
}
5942
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use async_trait::async_trait;
2+
3+
use crate::attributes::general_attributes::GeneralAttributes;
4+
use crate::board_settings::BoardSettings;
5+
use crate::connection::TockloaderConnection;
6+
use crate::errors::TockloaderError;
7+
use crate::{CommandInfo, IOCommands};
8+
9+
#[async_trait]
10+
impl CommandInfo for TockloaderConnection {
11+
async fn info(
12+
&mut self,
13+
settings: &BoardSettings,
14+
) -> Result<GeneralAttributes, TockloaderError> {
15+
let installed_apps = self.list_apps(settings).await.unwrap();
16+
let system_atributes = self.read_system_attributes().await.unwrap();
17+
Ok(GeneralAttributes::new(system_atributes, installed_apps))
18+
}
19+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use async_trait::async_trait;
2+
3+
use crate::attributes::app_attributes::AppAttributes;
4+
use crate::board_settings::BoardSettings;
5+
use crate::command_impl::reshuffle_apps::{create_pkt, reconstruct_app, reshuffle_apps};
6+
use crate::connection::TockloaderConnection;
7+
use crate::errors::TockloaderError;
8+
use crate::tabs::tab::Tab;
9+
use crate::{CommandInstall, CommandList, IOCommands};
10+
11+
#[async_trait]
12+
impl CommandInstall for TockloaderConnection {
13+
async fn install_app(
14+
&mut self,
15+
settings: &BoardSettings,
16+
tab: Tab,
17+
) -> Result<(), TockloaderError> {
18+
// get the already installed apps
19+
let mut installed_apps: Vec<AppAttributes> = self.list(settings).await.unwrap();
20+
21+
// reconstruct the new app
22+
if let Some(mut app) = reconstruct_app(Some(&tab), settings) {
23+
app.index = installed_apps.len() as u8;
24+
installed_apps.push(app.clone());
25+
}
26+
27+
// obtain the binaries in a vector
28+
let mut app_binaries: Vec<Vec<u8>> = Vec::new();
29+
30+
for app in installed_apps.iter() {
31+
match app.installed {
32+
true => {
33+
app_binaries.push(app.clone().read(self).await.unwrap());
34+
}
35+
false => {
36+
// TODO(adi): change this when TBF Filtering will get merged
37+
app_binaries.push(
38+
tab.extract_binary(settings.arch.as_ref().unwrap().as_str())
39+
.unwrap(),
40+
);
41+
}
42+
}
43+
}
44+
let configuration = reshuffle_apps(settings, installed_apps).unwrap();
45+
46+
// create the pkt, this contains all the binaries in a vec
47+
let pkt = create_pkt(configuration, app_binaries);
48+
49+
// write the pkt
50+
let _ = self.write(settings.start_address, pkt).await;
51+
Ok(())
52+
}
53+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use async_trait::async_trait;
2+
3+
use crate::attributes::app_attributes::AppAttributes;
4+
use crate::board_settings::BoardSettings;
5+
use crate::connection::TockloaderConnection;
6+
use crate::errors::TockloaderError;
7+
use crate::{CommandList, IOCommands};
8+
9+
#[async_trait]
10+
impl CommandList for TockloaderConnection {
11+
async fn list(
12+
&mut self,
13+
settings: &BoardSettings,
14+
) -> Result<Vec<AppAttributes>, TockloaderError> {
15+
self.list_apps(settings).await
16+
}
17+
}

0 commit comments

Comments
 (0)