Skip to content

Instantly share code, notes, and snippets.

@aksh1618
Last active December 10, 2023 12:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aksh1618/7c51f91cfddb501bd24fdaa6d7238d80 to your computer and use it in GitHub Desktop.
Save aksh1618/7c51f91cfddb501bd24fdaa6d7238d80 to your computer and use it in GitHub Desktop.
Convert BadRAM to memmap
// 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
}
}
@aksh1618
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment