Skip to content

Commit f501513

Browse files
committed
feat: uninstall by app_name
Signed-off-by: addrian-77 <lunguadrian30@gmail.com>
1 parent d506889 commit f501513

5 files changed

Lines changed: 146 additions & 96 deletions

File tree

tockloader-cli/src/cli.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ fn get_subcommands() -> Vec<Command> {
5555
.arg_required_else_help(false),
5656
Command::new("uninstall")
5757
.about("Uninstall apps")
58+
.arg(arg!(--"name" <APPNAME>).required(false))
5859
.args(get_app_args())
5960
.args(get_channel_args())
6061
.arg_required_else_help(false),

tockloader-cli/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ async fn main() -> Result<()> {
234234
let mut conn = open_connection(sub_matches).await?;
235235
let settings = get_board_settings(sub_matches);
236236

237-
conn.uninstall_app(&settings)
237+
let app_name = sub_matches.get_one::<String>("name").map(String::as_str);
238+
conn.uninstall_app(&settings, app_name)
238239
.await
239240
.context("Failed to uninstall app.")?;
240241
}

tockloader-lib/src/command_impl/generalized.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,13 @@ impl CommandInstall for TockloaderConnection {
5050

5151
#[async_trait]
5252
impl CommandUninstall for TockloaderConnection {
53-
async fn uninstall_app(&mut self, settings: &BoardSettings) -> Result<(), TockloaderError> {
53+
async fn uninstall_app(
54+
&mut self,
55+
settings: &BoardSettings,
56+
app_name: Option<&str>,
57+
) -> Result<(), TockloaderError> {
5458
match self {
55-
TockloaderConnection::ProbeRS(conn) => conn.uninstall_app(settings).await,
59+
TockloaderConnection::ProbeRS(conn) => conn.uninstall_app(settings, app_name).await,
5660
TockloaderConnection::Serial(_conn) => todo!(),
5761
}
5862
}

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

Lines changed: 132 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -11,113 +11,153 @@ use crate::CommandUninstall;
1111

1212
#[async_trait]
1313
impl CommandUninstall for ProbeRSConnection {
14-
async fn uninstall_app(&mut self, settings: &BoardSettings) -> Result<(), TockloaderError> {
14+
async fn uninstall_app(
15+
&mut self,
16+
settings: &BoardSettings,
17+
app_name: Option<&str>,
18+
) -> Result<(), TockloaderError> {
1519
if !self.is_open() {
1620
return Err(InternalError::ConnectionNotOpen.into());
1721
}
1822
let session = self.session.as_mut().expect("Board must be open");
19-
20-
let mut installed_apps: Vec<AppData> = Vec::new();
21-
let mut index: u8 = 1;
22-
let mut appaddr: u64 = settings.start_address;
23-
24-
// make "Delete all" a part of this vector
25-
installed_apps.push(AppData {
26-
name: "Delete all".to_string(),
27-
address: settings.start_address,
28-
index: 0,
29-
size: 0,
30-
});
31-
3223
loop {
33-
let mut board_core = session.core(self.target_info.core)?;
34-
// Read the first 8 bytes, which is the length of a TLV header.
35-
let mut appdata = vec![0u8; 8];
36-
37-
board_core.read(appaddr, &mut appdata)?;
38-
let tbf_version: u16;
39-
let header_size: u16;
40-
let app_size: u32;
41-
42-
// The first 8 bytes of the application data contain the TBF header
43-
// lengths and version.
44-
//
45-
// Note on expect: `read` always fills up the entire buffer, which
46-
// was previously declared as 8 bytes.
47-
match parse_tbf_header_lengths(
48-
&appdata[0..8]
49-
.try_into()
50-
.expect("Buffer length must be at least 8 bytes long."),
51-
) {
52-
Ok(data) => {
53-
tbf_version = data.0;
54-
header_size = data.1;
55-
app_size = data.2;
56-
}
57-
_ => break,
58-
};
59-
60-
// Read the rest of the header
61-
let mut header_data = vec![0u8; header_size.into()];
62-
board_core.read(appaddr, &mut header_data)?;
24+
let mut installed_apps: Vec<AppData> = Vec::new();
25+
let mut index: u8 = 1;
26+
let mut appaddr: u64 = settings.start_address;
6327

64-
let header = parse_tbf_header(&header_data, tbf_version)
65-
.map_err(TockError::InvalidAppTbfHeader)?;
66-
let pname = header.get_package_name().unwrap_or("").to_owned();
28+
// make "Delete all" a part of this vector
6729
installed_apps.push(AppData {
68-
address: appaddr,
69-
name: pname,
70-
size: app_size,
71-
index,
30+
name: "Delete all".to_string(),
31+
address: settings.start_address,
32+
index: 0,
33+
size: 0,
7234
});
73-
index += 1;
74-
appaddr += app_size as u64;
75-
}
76-
if installed_apps.len() == 1 {
77-
return Err(TockloaderError::Tock(TockError::MissingAttribute(
78-
"No apps installed".to_string(),
79-
)));
80-
}
81-
let app = inquire::Select::new(
82-
"Which app do you want to uninstall?",
83-
installed_apps.iter().clone().collect(),
84-
)
85-
.prompt()
86-
.context("No apps installed")
87-
.unwrap();
88-
let address: u64; // here we'll write the remaining apps
89-
let buf_size: usize = if app.index > 0 {
90-
// buf_size is the size of all apps that are to the right of our target app
91-
address = app.address; // put remaining apps where target app starts
92-
installed_apps.iter().fold(0, |total_size, aux_app| {
93-
if aux_app.index > app.index {
94-
total_size + aux_app.size as usize // increase if app is to the right
35+
36+
loop {
37+
let mut board_core = session.core(self.target_info.core)?;
38+
// Read the first 8 bytes, which is the length of a TLV header.
39+
let mut appdata = vec![0u8; 8];
40+
41+
board_core.read(appaddr, &mut appdata)?;
42+
let tbf_version: u16;
43+
let header_size: u16;
44+
let app_size: u32;
45+
46+
// The first 8 bytes of the application data contain the TBF header
47+
// lengths and version.
48+
//
49+
// Note on expect: `read` always fills up the entire buffer, which
50+
// was previously declared as 8 bytes.
51+
match parse_tbf_header_lengths(
52+
&appdata[0..8]
53+
.try_into()
54+
.expect("Buffer length must be at least 8 bytes long."),
55+
) {
56+
Ok(data) => {
57+
tbf_version = data.0;
58+
header_size = data.1;
59+
app_size = data.2;
60+
}
61+
_ => break,
62+
};
63+
64+
// Read the rest of the header
65+
let mut header_data = vec![0u8; header_size.into()];
66+
board_core.read(appaddr, &mut header_data)?;
67+
68+
let header = parse_tbf_header(&header_data, tbf_version)
69+
.map_err(TockError::InvalidAppTbfHeader)?;
70+
let pname = header.get_package_name().unwrap_or("").to_owned();
71+
installed_apps.push(AppData {
72+
address: appaddr,
73+
name: pname,
74+
size: app_size,
75+
index,
76+
});
77+
index += 1;
78+
appaddr += app_size as u64;
79+
}
80+
if installed_apps.len() == 1 {
81+
if app_name == None {
82+
return Err(TockloaderError::Tock(TockError::MissingAttribute(
83+
"No apps installed".to_string(),
84+
)));
9585
} else {
96-
total_size
86+
return Err(TockloaderError::Tock(TockError::MissingAttribute(
87+
"Requested app is not instaleld".to_string(),
88+
)));
9789
}
98-
})
99-
} else {
100-
// Delete all case
101-
address = settings.start_address; // put a 0x0 byte here, all apps will become invalid
102-
0
103-
};
104-
let mut buffer = vec![0u8; buf_size];
105-
if buf_size > 0 {
106-
// we have apps to the right
107-
let mut board_core = session.core(self.target_info.core)?;
108-
board_core.read(installed_apps[app.index as usize + 1].address, &mut buffer)?;
109-
}
90+
}
91+
let mut app: &AppData;
92+
match app_name {
93+
Some(app_name) => {
94+
app = match installed_apps.iter().find(|iter| iter.name == app_name) {
95+
Some(app) => app,
96+
None => break,
97+
}
98+
}
99+
None => loop {
100+
app = inquire::Select::new(
101+
"Which app do you want to uninstall?",
102+
installed_apps.iter().clone().collect(),
103+
)
104+
.prompt()
105+
.context("No apps installed")
106+
.unwrap();
107+
108+
if inquire::Select::new(
109+
format!("You chose {app}",).as_str(),
110+
["Cancel", "Confirm"].to_vec(),
111+
)
112+
.prompt()
113+
.unwrap()
114+
== "Confirm"
115+
{
116+
break;
117+
}
118+
},
119+
}
120+
let address: u64; // here we'll write the remaining apps
121+
let buf_size: usize = if app.index > 0 {
122+
// buf_size is the size of all apps that are to the right of our target app
123+
address = app.address; // put remaining apps where target app starts
124+
installed_apps.iter().fold(0, |total_size, aux_app| {
125+
if aux_app.index > app.index {
126+
total_size + aux_app.size as usize // increase if app is to the right
127+
} else {
128+
total_size
129+
}
130+
})
131+
} else {
132+
// Delete all case
133+
address = settings.start_address; // put a 0x0 byte here, all apps will become invalid
134+
installed_apps.iter().fold(0, |total_size, aux_app| {
135+
total_size + aux_app.size as usize // increase if app is to the right
136+
})
137+
};
138+
let mut buffer = vec![0u8; buf_size];
139+
if buf_size > 0 && app.index > 0 {
140+
// copy apps only if we didn't choose "Delete all"
141+
// we have apps to the right
142+
let mut board_core = session.core(self.target_info.core)?;
143+
board_core.read(installed_apps[app.index as usize + 1].address, &mut buffer)?;
144+
}
110145

111-
buffer.push(0x0);
112-
let mut loader = session.target().flash_loader();
146+
buffer.extend([0x0; 512]); // add an extra page of 0x0
147+
let mut loader = session.target().flash_loader();
113148

114-
loader.add_data(address, &buffer)?;
149+
loader.add_data(address, &buffer)?;
115150

116-
let mut options = DownloadOptions::default();
117-
options.keep_unwritten_bytes = true;
151+
let mut options = DownloadOptions::default();
152+
options.keep_unwritten_bytes = true;
118153

119-
loader.commit(session, options)?;
154+
loader.commit(session, options)?;
120155

156+
if app_name == None {
157+
// exit if we don't have a name set, else continue removing
158+
break;
159+
}
160+
}
121161
Ok(())
122162
}
123163
}

tockloader-lib/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,9 @@ pub trait CommandInstall {
6262

6363
#[async_trait]
6464
pub trait CommandUninstall {
65-
async fn uninstall_app(&mut self, settings: &BoardSettings) -> Result<(), TockloaderError>;
65+
async fn uninstall_app(
66+
&mut self,
67+
settings: &BoardSettings,
68+
app_name: Option<&str>,
69+
) -> Result<(), TockloaderError>;
6670
}

0 commit comments

Comments
 (0)