Skip to content

Commit b6f9297

Browse files
committed
implement clean command
Signed-off-by: Daniel Maslowski <info@orangecms.org>
1 parent 22113fb commit b6f9297

File tree

2 files changed

+129
-10
lines changed

2 files changed

+129
-10
lines changed

src/clean.rs

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,106 @@
1-
enum Module {
2-
ROMP,
3-
BUP,
4-
RBE,
5-
Kernel,
6-
Syslib,
1+
use log::info;
2+
3+
use intel_fw::EMPTY;
4+
use intel_fw::Removables;
5+
use intel_fw::dir::gen2::{self, Directory as Gen2Directory};
6+
use intel_fw::dir::gen3::{self, CodePartitionDirectory};
7+
use intel_fw::fpt::{FTPR, REMOVABLE_PARTS};
8+
use intel_fw::me::{Directories, ME};
9+
10+
fn fpt_clean(me: &ME, data: &mut [u8]) {
11+
let mut clean_fpt = me.fpt.clone();
12+
clean_fpt.clear();
13+
for (i, v) in clean_fpt.to_vec().iter().enumerate() {
14+
data[me.base + i] = *v;
15+
}
16+
}
17+
18+
fn gen2clean(me: &ME, dirs: &Vec<Gen2Directory>, data: &mut [u8]) {
19+
// TODO: Extend with user-provided list
20+
let retention_list = Vec::from(gen2::ALWAYS_RETAIN)
21+
.iter()
22+
.map(|s| String::from(*s))
23+
.collect();
24+
// Clear out removable ranges in the FTPR directory
25+
for d in dirs {
26+
if d.name == FTPR {
27+
let dir_offset = me.base + d.offset;
28+
info!("FTPR @ {dir_offset:08x}");
29+
for r in d.removables(&retention_list) {
30+
let offset = dir_offset + r.start;
31+
let size = r.end - r.start;
32+
info!("Freeing {size:8} bytes @ {offset:08x}");
33+
for o in r {
34+
data[dir_offset + o] = EMPTY;
35+
}
36+
}
37+
}
38+
}
39+
// Clear out fully removable partitions
40+
for e in &me.fpt.entries {
41+
match e {
42+
// We dealt with the removable ranges in FTPR above.
43+
e if e.name().as_str() == FTPR => {
44+
info!("Retain {e}");
45+
}
46+
e if e.offset == 0xffff_ffff => {
47+
info!("Ignore {e} due to Invalid offset");
48+
}
49+
e => {
50+
let offset = me.base + e.offset as usize;
51+
let size = e.size as usize;
52+
let end = offset + size;
53+
info!("Remove {e}");
54+
for o in offset..end {
55+
data[o] = EMPTY;
56+
}
57+
}
58+
}
59+
}
60+
}
61+
62+
fn gen3clean(me: &ME, dirs: &Vec<CodePartitionDirectory>, data: &mut [u8]) {
63+
// TODO: Extend with user-provided list
64+
let retention_list = Vec::from(gen3::ALWAYS_RETAIN)
65+
.iter()
66+
.map(|s| String::from(*s))
67+
.collect();
68+
// Clear out removable FTPR entries
69+
for d in dirs {
70+
if d.name == FTPR {
71+
let dir_offset = me.base + d.offset;
72+
info!("FTPR @ {dir_offset:08x}");
73+
for r in d.removables(&retention_list) {
74+
let offset = dir_offset + r.start;
75+
let size = r.end - r.start;
76+
info!("Freeing {size:8} bytes @ {offset:08x}");
77+
for o in r {
78+
data[dir_offset + o] = EMPTY;
79+
}
80+
}
81+
}
82+
}
83+
// Clear out fully removable partitions
84+
for e in &me.fpt.entries {
85+
match e.name().as_str() {
86+
n if REMOVABLE_PARTS.contains(&n) => {
87+
let offset = me.base + e.offset as usize;
88+
let end = offset + e.size as usize;
89+
for o in offset..end {
90+
data[o] = EMPTY;
91+
}
92+
}
93+
_ => {} //
94+
}
95+
}
96+
}
97+
98+
pub fn clean(me: &ME, data: &mut [u8]) -> Result<Vec<u8>, ()> {
99+
fpt_clean(me, data);
100+
match &me.dirs {
101+
Directories::Gen2(dirs) => gen2clean(&me, &dirs, data),
102+
Directories::Gen3(dirs) => gen3clean(&me, &dirs, data),
103+
_ => return Err(()),
104+
};
105+
Ok(data.to_vec())
7106
}

src/main.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
//! image in its entirety. This tool brings together all publicly known details.
1010
1111
use std::fs;
12+
use std::io::Write;
1213

1314
use clap::{Parser, Subcommand, ValueEnum};
14-
use log::{debug, info};
15+
use log::{debug, error, info};
1516

1617
mod clean;
1718
mod show;
@@ -163,15 +164,34 @@ fn main() {
163164
if let Some(me_file) = extract_me {
164165
info!("Dump ME region to {me_file}");
165166
}
166-
if let Some(out_file) = output {
167+
if let Some(out_file) = &output {
167168
info!("Output will be written to: {out_file}");
168169
}
169170
info!("Reading {file_name}...");
170-
let data = fs::read(file_name).unwrap();
171+
let mut data = fs::read(file_name).unwrap();
171172
let fw = Firmware::parse(&data, debug);
172173
show::show(&fw, verbose);
173174
println!();
174-
todo!("clean");
175+
176+
let Some(me_res) = fw.me else {
177+
return;
178+
};
179+
let Ok(me) = me_res else {
180+
return;
181+
};
182+
match clean::clean(&me, &mut data) {
183+
Ok(data) => {
184+
if let Some(out_file) = output {
185+
let mut file = fs::File::create(out_file).unwrap();
186+
file.write_all(&data).unwrap();
187+
} else {
188+
error!("Clean operation failed");
189+
}
190+
}
191+
Err(_) => {
192+
error!("Clean operation failed");
193+
}
194+
}
175195
}
176196
MeCommand::Scan { file_name } => {
177197
let data = fs::read(file_name).unwrap();

0 commit comments

Comments
 (0)