This commit is contained in:
Argon 2022-09-22 19:13:19 +08:00
parent 3a11402914
commit f31608749c
2 changed files with 212 additions and 14 deletions

7
Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "sepatch"
version = "0.1.0"

View File

@ -1,4 +1,4 @@
use std::{fs, io::{self, BufRead, BufReader, Write}, fmt::format}; use std::{fs, io::{self, BufRead, BufReader, Write}};
fn main() { fn main() {
let args : Vec<String> = std::env::args().collect(); let args : Vec<String> = std::env::args().collect();
@ -13,6 +13,10 @@ fn main() {
return; return;
} }
}; };
if let Err(e) = verify_code(&codes) {
println!("verify code error: {}", e.to_string());
return;
}
if let Err(e) = apply_code(args[1].as_str(), &codes) { if let Err(e) = apply_code(args[1].as_str(), &codes) {
println!("apply code error: {}", e.to_string()); println!("apply code error: {}", e.to_string());
} }
@ -22,7 +26,7 @@ fn read_codes(code_file : &str) -> io::Result<Vec<(u32, u32)>> {
let file = fs::File::open(code_file).expect("cannot open patch_code"); let file = fs::File::open(code_file).expect("cannot open patch_code");
let reader = BufReader::new(file); let reader = BufReader::new(file);
let mut codes = Vec::new(); let mut codes = Vec::new();
let mut lines = 0u32; let mut lines = 1u32;
for line in reader.lines() { for line in reader.lines() {
if let Ok(l) = line { if let Ok(l) = line {
let r_str = l.as_str(); let r_str = l.as_str();
@ -35,31 +39,218 @@ fn read_codes(code_file : &str) -> io::Result<Vec<(u32, u32)>> {
codes.push((lines, val2.unwrap())); codes.push((lines, val2.unwrap()));
} }
} // else skip } // else skip
lines += 1;
} }
} }
Ok(codes) Ok(codes)
} }
fn verify_code(codes : Vec<(u32, u32)>) -> Result<(), String> { fn verify_code(codes : &Vec<(u32, u32)>) -> Result<(), String> {
let pos = 0usize; let mut pos = 0usize;
while pos < codes.len() { let max_len = codes.len();
let mut search_code = false;
while pos < max_len {
let line = codes[pos].0;
let first_code = codes[pos].1; let first_code = codes[pos].1;
let op_code = first_code >> 28; let op_code = (first_code >> 28) as u8;
let mut search_code = false;
match op_code { match op_code {
0x0 | 0x1 |0x2 => { 0x0 | 0x1 |0x2 => {
return Err(format!("{}", 123)); if search_code {
if first_code & 0xf000000 != 0x8000000 {
return Err(format!("wrong code at line {}: need search code after search", line));
}
search_code = false
}
if pos + 2 > max_len {
return Err(format!("wrong code at line {}: unexpected end", line));
}
pos += 2;
}
0x4 => {
if search_code {
if first_code & 0xf000000 != 0x8000000 {
return Err(format!("wrong code at line {}: need search code after search", line));
}
search_code = false
}
if pos + 4 > max_len {
return Err(format!("wrong code at line {}: unexpected end", line));
}
pos += 4;
}
0x5 => {
if search_code {
return Err(format!("wrong code at line {}: need search code after search", line));
}
if pos + 4 > max_len {
return Err(format!("wrong code at line {}: unexpected end", line));
}
pos += 4;
}
0x8 => {
if search_code {
return Err(format!("wrong code at line {}: need search code after search", line));
}
let search_bytes = (first_code & 0xffff) as usize;
if search_bytes == 0 {
return Err(format!("wrong code at line {}: search length should not be 0", line));
}
let code_len = ((search_bytes - 1) / 4 + 1) * 2;
if pos + code_len > max_len {
return Err(format!("wrong code at line {}: unexpected end", line));
}
search_code = true;
pos += code_len;
}
0xa => {
if search_code {
return Err(format!("wrong code at line {}: need search code after search", line));
}
if pos + 1 >= max_len {
return Err(format!("wrong code at line {}: unexpected end", line));
}
let write_bytes = codes[pos + 1].1 as usize;
if write_bytes == 0 {
return Err(format!("wrong code at line {}: write length should not be 0", line));
}
if write_bytes > 320 {
return Err(format!("wrong code at line {}: write length should not exceed 320", line));
}
let code_len = ((write_bytes - 1) / 8 + 1) * 2 + 2;
if pos + code_len > max_len {
return Err(format!("wrong code at line {}: unexpected end", line));
}
pos += code_len;
}
_ => {
return Err(format!("unknown code at line {}", line));
} }
_ => (),
} }
pos += 1;
} }
Ok(()) Ok(())
} }
fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> io::Result<()> { fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> {
let data = fs::read(patch_file)?; let fn_map_err = |e : io::Error| format!("apply code error: {}", e.to_string());
let mut write_file = fs::OpenOptions::new().write(true).truncate(true).open(patch_file)?; let mut data = fs::read(patch_file).map_err(fn_map_err)?;
write_file.write(data.as_slice())?; let mut pos = 0usize;
let max_code_len = codes.len();
let max_data_len = data.len();
let mut search_addr : Option<u32> = None;
while pos < max_code_len {
let line = codes[pos].0;
let first_code = codes[pos].1;
let op_code = (first_code >> 28) as u8;
match op_code {
0x0 => {
let val = codes[pos + 1].1 as u8;
let addr = if let Some(saddr) = search_addr {
search_addr = None;
(codes[pos].1 & 0xffffff) + saddr
} else {
codes[pos].1 & 0xfffffff
} as usize;
if addr >= max_data_len {
return Err(format!("apply code error at line {}: address overflow", line));
}
data[addr] = val;
pos += 2;
}
0x1 => {
let val = codes[pos + 1].1 as u16;
let addr = if let Some(saddr) = search_addr {
search_addr = None;
(codes[pos].1 & 0xffffff) + saddr
} else {
codes[pos].1 & 0xfffffff
} as usize;
if addr + 1 >= max_data_len {
return Err(format!("apply code error at line {}: address overflow", line));
}
data[addr] = (val & 0xff) as u8;
data[addr + 1] = ((val >> 8) & 0xff) as u8;
pos += 2;
}
0x2 => {
let val = codes[pos + 1].1;
let addr = if let Some(saddr) = search_addr {
search_addr = None;
(codes[pos].1 & 0xffffff) + saddr
} else {
codes[pos].1 & 0xfffffff
} as usize;
if addr + 3 >= max_data_len {
return Err(format!("apply code error at line {}: address overflow", line));
}
data[addr] = (val & 0xff) as u8;
data[addr + 1] = ((val >> 8) & 0xff) as u8;
data[addr + 2] = ((val >> 16) & 0xff) as u8;
data[addr + 3] = ((val >> 24) & 0xff) as u8;
pos += 2;
}
0x4 => {
let mut val = codes[pos + 1].1;
let mut addr = if let Some(saddr) = search_addr {
search_addr = None;
(codes[pos].1 & 0xffffff) + saddr
} else {
codes[pos].1 & 0xfffffff
} as usize;
let mut count = (codes[pos + 2].1 & 0xfff0000) >> 16;
let addr_diff = codes[pos + 2].1 & 0xffff;
let val_diff = codes[pos + 3].1;
while count != 0 {
if codes[pos].1 & 0xf000000 == 0x1000000 {
if addr >= max_data_len {
return Err(format!("apply code error at line {}: address overflow", line));
}
data[addr] = (val & 0xff) as u8;
} else if codes[pos].1 & 0xf000000 == 0x2000000 {
if addr + 1 >= max_data_len {
return Err(format!("apply code error at line {}: address overflow", line));
}
data[addr] = (val & 0xff) as u8;
data[addr + 1] = ((val >> 8) & 0xff) as u8;
} else {
if addr + 3 >= max_data_len {
return Err(format!("apply code error at line {}: address overflow", line));
}
data[addr] = (val & 0xff) as u8;
data[addr + 1] = ((val >> 8) & 0xff) as u8;
data[addr + 2] = ((val >> 16) & 0xff) as u8;
data[addr + 3] = ((val >> 24) & 0xff) as u8;
}
count -= 1;
addr += addr_diff as usize;
val += val_diff;
}
pos += 4;
}
0x5 | 0x8 => {
return Err(format!("apply code error at line {}: not supported", line));
}
0xa => {
let mut addr = (codes[pos].1 & 0xfffffff) as usize;
let write_bytes = codes[pos + 1].1 as usize;
if addr + write_bytes>= max_data_len {
return Err(format!("apply code error at line {}: address overflow", line));
}
let mut bytes = 0;
while bytes < write_bytes {
let offset = pos + 2 + (bytes / 4);
let shift = (3 - (bytes % 4)) * 8;
data[addr] = ((codes[offset].1 >> shift) & 0xff) as u8;
bytes += 1;
addr += 1;
}
let code_len = ((write_bytes - 1) / 8 + 1) * 2 + 2;
pos += code_len;
}
_ => ()
}
}
let mut write_file = fs::OpenOptions::new().write(true).truncate(true).open(patch_file).map_err(fn_map_err)?;
write_file.write(data.as_slice()).map_err(fn_map_err)?;
Ok(()) Ok(())
} }