amd/
amd.rs

1// SPDX-License-Identifier: MIT
2
3use std::{env, fs, process};
4
5use romulan::amd::{
6    Rom,
7    directory::Directory,
8};
9
10fn print_directory(data: &[u8], address: u64, indent: usize) {
11    //TODO: optimize
12    let mut padding = String::with_capacity(indent);
13    for i in 0..indent {
14        padding.push(' ');
15    }
16    let offset = (address & 0xFFFFFF) as usize;
17    match Directory::new(&data[offset..]) {
18        Ok(Directory::Bios(directory)) => {
19            println!("{}* {:#X}: BIOS Directory", padding, address);
20            for entry in directory.entries() {
21                println!("{}  * Type {:02X} Region {:02X} Flags {:02X} SubProg {:02X} Size {:08X} Source {:08X} Dest {:016X}: {}", padding, entry.kind, entry.region_kind, entry.flags, entry.sub_program, entry.size, entry.source, entry.destination, entry.description());
22                if entry.kind == 0x70 {
23                    print_directory(data, entry.source, indent + 4);
24                }
25            }
26        },
27        Ok(Directory::BiosCombo(combo)) => {
28            println!("{}* {:#X}: BIOS Combo Directory", padding, address);
29            for entry in combo.entries() {
30                println!("{}  * {:X?}", padding, entry);
31                print_directory(data, entry.directory, indent + 4);
32            }
33        },
34        Ok(Directory::BiosLevel2(directory)) => {
35            println!("{}* {:#X}: BIOS Level 2 Directory", padding, address);
36            for entry in directory.entries() {
37                println!("{}  * Type {:02X} Region {:02X} Flags {:02X} SubProg {:02X} Size {:08X} Source {:08X} Dest {:016X}: {}", padding, entry.kind, entry.region_kind, entry.flags, entry.sub_program, entry.size, entry.source, entry.destination, entry.description());
38            }
39        },
40        Ok(Directory::Psp(directory)) => {
41            println!("{}* {:#X}: PSP Directory", padding, address);
42            for entry in directory.entries() {
43                println!("{}  * Type {:02X} SubProg {:02X} Size {:08X} Value {:08X}: {}", padding, entry.kind, entry.sub_program, entry.size, entry.value, entry.description());
44                if entry.kind == 0x40 {
45                    print_directory(data, entry.value, indent + 4);
46                }
47            }
48        },
49        Ok(Directory::PspCombo(combo)) => {
50            println!("{}* {:#X}: PSP Combo Directory", padding, address);
51            for entry in combo.entries() {
52                println!("{}  * {:X?}", padding, entry);
53                print_directory(data, entry.directory, indent + 4);
54            }
55        },
56        Ok(Directory::PspLevel2(directory)) => {
57            println!("{}* {:#X}: PSP Level 2 Directory", padding, address);
58            for entry in directory.entries() {
59                println!("{}  * Type {:02X} SubProg {:02X} Size {:08X} Value {:08X}: {}", padding, entry.kind, entry.sub_program, entry.size, entry.value, entry.description());
60            }
61        },
62        Err(err) => {
63            println!("{}* {:#X}: failed to load directory: {}", padding, address, err);
64        }
65    }
66}
67
68fn main() {
69    let file = if let Some(file) = env::args().nth(1) {
70        file
71    } else {
72        eprintln!("used_regions <file>");
73        process::exit(1);
74    };
75
76    let data = fs::read(file).unwrap();
77
78    let rom = Rom::new(&data).unwrap();
79
80    let signature = rom.signature();
81    println!("{:#X?}", signature);
82
83    print_directory(&data, signature.psp as u64, 0);
84    print_directory(&data, signature.bios as u64, 0);
85}