Last active
December 10, 2023 12:31
-
-
Save aksh1618/7c51f91cfddb501bd24fdaa6d7238d80 to your computer and use it in GitHub Desktop.
Convert BadRAM to memmap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Rust playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7c51f91cfddb501bd24fdaa6d7238d80 | |
const PAGESIZE: u64 = 4096; | |
const MIN_SIZE_KIB: u64 = 4; | |
fn main() { | |
println!("Enter BadRAM string. It must be a single line of comma separated"); | |
println!("values, with address and mask alternating. This is basically the"); | |
println!("badram output from memtest86+ et al with all values in a single"); | |
println!("line without the `badram=` prefix."); | |
println!(); | |
println!("Example input:"); | |
println!("0x00000000990cda38,0xfffffffffffffff8, 0x00000000990ce4b0,0xfffffffffffffff8, 0x00000000990ceee8,0xfffffffffffffff8"); | |
let mut badram_string = String::new(); | |
std::io::stdin() | |
.read_line(&mut badram_string) | |
.expect("Failed to read line"); | |
let badram_patterns = parse_badram_string(&badram_string); | |
println!(); | |
println!("Processing the following BadRAM pattern:"); | |
for (i, (address, mask)) in badram_patterns.iter().enumerate() { | |
if i == 0 { | |
println!("badram={:#018x},{:#018x},", address, mask); | |
} else if i == (badram_patterns.len() - 1) { | |
println!(" {:#018x},{:#018x}", address, mask); | |
} else { | |
println!(" {:#018x},{:#018x},", address, mask); | |
} | |
} | |
println!(); | |
/* | |
let badram_patterns: Vec<(u64, u64)> = vec![ | |
(0x00000000990cda38, 0xfffffffffffffff8), | |
(0x00000000990ce4b0, 0xfffffffffffffff8), | |
(0x00000000990ceee8, 0xfffffffffffffff8), | |
]; | |
*/ | |
println!("(Using steps from https://askubuntu.com/a/1435622)"); | |
println!(); | |
let memmap_patterns: Vec<String> = badram_patterns | |
.iter() | |
.map(|&(address, mask)| { | |
let inverted_mask = mask ^ 0xffffffffffffffff; | |
let size_bytes = inverted_mask + 1; // Add 1 because the mask represents the range of bad bytes | |
let size_kib = u64::max(size_bytes.next_power_of_two() / 1024, MIN_SIZE_KIB); // Convert to KiB and round up to the next power of two | |
format!( | |
"{:#04} | memmap={}K${:#018x} | memmap={}K${:#018x}", | |
size_bytes, | |
size_kib, | |
address, | |
size_kib + (PAGESIZE / 1024), | |
(address - (address % PAGESIZE)) | |
) | |
}) | |
.collect(); | |
println!( | |
"{} | {:#28} | {} {}", | |
"size", "memmap", "memmap adjusted to pagesize", PAGESIZE | |
); | |
println!("{}", "-".repeat(72)); | |
for pattern in memmap_patterns { | |
println!("{}", pattern); | |
} | |
} | |
fn parse_badram_string(badram_string: &str) -> Vec<(u64, u64)> { | |
badram_string | |
.trim() | |
.split(',') | |
.filter_map(|s| s.trim().strip_prefix("0x")) | |
.filter_map(|s| u64::from_str_radix(s, 16).ok()) | |
.collect::<Vec<u64>>() | |
.chunks(2) | |
.filter_map(|chunk| match *chunk { | |
[address, mask] => Some((address, mask)), | |
_ => None, | |
}) | |
.collect() | |
} | |
// Helper function to round up to the next power of two | |
trait NextPowerOfTwo { | |
fn next_power_of_two(self) -> Self; | |
} | |
impl NextPowerOfTwo for u64 { | |
fn next_power_of_two(self) -> Self { | |
let mut n = self - 1; | |
n |= n >> 1; | |
n |= n >> 2; | |
n |= n >> 4; | |
n |= n >> 8; | |
n |= n >> 16; | |
n |= n >> 32; | |
n + 1 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Run now in the rust playground