mirror of
https://github.com/BillyOutlast/oboromi.git
synced 2026-07-01 19:54:43 -04:00
chore: auto-commit after execute-task
GSD-Unit: M003/S03/T01
This commit is contained in:
@@ -3,6 +3,7 @@ use std::rc::Rc;
|
||||
use unicorn_engine::{Arch, Mode, Prot, RegisterARM64, Unicorn};
|
||||
|
||||
use crate::mmio::MmioBus;
|
||||
use crate::security::efuse::{EFUSE_BASE, EFUSE_SIZE};
|
||||
use super::exception::ExceptionModule;
|
||||
use crate::mmio::gic::GicDistributor;
|
||||
|
||||
@@ -73,6 +74,30 @@ impl UnicornCPU {
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
// Register EFUSE MMIO hooks at the real hardware address
|
||||
// (0x7000F800). This is a second, dedicated mmio_map so that
|
||||
// ARM64 LDR/STR instructions targeting EFUSE_BASE trigger
|
||||
// MMIO hooks through the same MmioBus. Resolves MEM054.
|
||||
emu.mmio_map(
|
||||
EFUSE_BASE,
|
||||
EFUSE_SIZE,
|
||||
Some(move |uc: &mut Unicorn<'_, Rc<RefCell<MmioBus>>>, offset: u64, size: usize| {
|
||||
let bus = uc.get_data_mut();
|
||||
let addr = EFUSE_BASE + offset;
|
||||
bus.borrow().read(addr, size as u32)
|
||||
}),
|
||||
Some(move |uc: &mut Unicorn<'_, Rc<RefCell<MmioBus>>>, offset: u64, size: usize, value: u64| {
|
||||
let bus = uc.get_data_mut();
|
||||
let addr = EFUSE_BASE + offset;
|
||||
bus.borrow_mut().write(addr, size as u32, value);
|
||||
}),
|
||||
)
|
||||
.map_err(|e| {
|
||||
eprintln!("Failed to map EFUSE MMIO region: {e:?}");
|
||||
e
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
// Initialize stack pointer
|
||||
let _ = emu.reg_write(RegisterARM64::SP, (8 * 1024 * 1024) - 0x1000);
|
||||
|
||||
@@ -135,15 +160,55 @@ impl UnicornCPU {
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
// Part 2: MMIO_BASE+MMIO_SIZE..memory_size (shared memory after MMIO region)
|
||||
// Part 2: split around the EFUSE region (0x7000F800–0x7000FC00) so
|
||||
// that ARM64 LDR targeting EFUSE_BASE reaches the real hardware
|
||||
// address through dedicated mmio_map hooks (MEM054).
|
||||
let mmio_end = MMIO_BASE + MMIO_SIZE;
|
||||
if mmio_end < memory_size {
|
||||
|
||||
// Part 2a: mmio_end..EFUSE_BASE (shared memory between MMIO and eFuse)
|
||||
if mmio_end < EFUSE_BASE {
|
||||
unsafe {
|
||||
let part2_ptr = memory_ptr.add(mmio_end as usize);
|
||||
let part2_size = memory_size - mmio_end;
|
||||
emu.mem_map_ptr(mmio_end, part2_size, Prot::ALL, part2_ptr as *mut std::ffi::c_void)
|
||||
let part2a_ptr = memory_ptr.add(mmio_end as usize);
|
||||
let part2a_size = EFUSE_BASE - mmio_end;
|
||||
emu.mem_map_ptr(mmio_end, part2a_size, Prot::ALL, part2a_ptr as *mut std::ffi::c_void)
|
||||
.map_err(|e| {
|
||||
eprintln!("Failed to map shared memory (high) for core {}: {:?}", core_id, e);
|
||||
eprintln!("Failed to map shared memory (part2a) for core {}: {:?}", core_id, e);
|
||||
e
|
||||
})
|
||||
.ok()?;
|
||||
}
|
||||
}
|
||||
|
||||
// EFUSE MMIO hooks at real hardware address (0x7000F800)
|
||||
emu.mmio_map(
|
||||
EFUSE_BASE,
|
||||
EFUSE_SIZE,
|
||||
Some(move |uc: &mut Unicorn<'_, Rc<RefCell<MmioBus>>>, offset: u64, size: usize| {
|
||||
let bus = uc.get_data_mut();
|
||||
let addr = EFUSE_BASE + offset;
|
||||
bus.borrow().read(addr, size as u32)
|
||||
}),
|
||||
Some(move |uc: &mut Unicorn<'_, Rc<RefCell<MmioBus>>>, offset: u64, size: usize, value: u64| {
|
||||
let bus = uc.get_data_mut();
|
||||
let addr = EFUSE_BASE + offset;
|
||||
bus.borrow_mut().write(addr, size as u32, value);
|
||||
}),
|
||||
)
|
||||
.map_err(|e| {
|
||||
eprintln!("Failed to map EFUSE MMIO region for core {}: {:?}", core_id, e);
|
||||
e
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
// Part 2b: EFUSE_BASE + EFUSE_SIZE..memory_size (shared memory after eFuse)
|
||||
let efuse_end = EFUSE_BASE + EFUSE_SIZE;
|
||||
if efuse_end < memory_size {
|
||||
unsafe {
|
||||
let part2b_ptr = memory_ptr.add(efuse_end as usize);
|
||||
let part2b_size = memory_size - efuse_end;
|
||||
emu.mem_map_ptr(efuse_end, part2b_size, Prot::ALL, part2b_ptr as *mut std::ffi::c_void)
|
||||
.map_err(|e| {
|
||||
eprintln!("Failed to map shared memory (part2b) for core {}: {:?}", core_id, e);
|
||||
e
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
//! These tests exercise the full MMIO path: register device → encode ARM64
|
||||
//! instructions → run emulation → read register values back.
|
||||
|
||||
use crate::cpu::unicorn_interface::MMIO_BASE;
|
||||
use crate::cpu::UnicornCPU;
|
||||
use crate::security::efuse::{EfuseArray, EFUSE_BASE, EFUSE_SIZE};
|
||||
|
||||
@@ -52,11 +51,25 @@ fn encode_movz(d: u32, imm16: u32, hw: u32) -> u32 {
|
||||
0xD280_0000 | (hw << 21) | (imm16 << 5) | d
|
||||
}
|
||||
|
||||
/// Encode `MOVK Xd, #imm16, LSL #(hw*16)`.
|
||||
fn encode_movk(d: u32, imm16: u32, hw: u32) -> u32 {
|
||||
0xF280_0000 | (hw << 21) | (imm16 << 5) | d
|
||||
}
|
||||
|
||||
/// Encode `BRK #0` — halts emulation.
|
||||
fn encode_brk() -> u32 {
|
||||
0xD420_0000
|
||||
}
|
||||
|
||||
/// Write MOVZ+MOVK pair to load EFUSE_BASE (0x7000F800) into Xd.
|
||||
/// Returns two instructions: `[MOVZ, MOVK]`.
|
||||
fn encode_load_efuse_base_into(d: u32) -> [u32; 2] {
|
||||
[
|
||||
encode_movz(d, 0xF800, 0), // MOVZ Xd, #0xF800
|
||||
encode_movk(d, 0x7000, 1), // MOVK Xd, #0x7000, LSL #16 → Xd = 0x7000F800
|
||||
]
|
||||
}
|
||||
|
||||
/// Write a sequence of 32-bit instructions into the UnicornCPU memory.
|
||||
fn write_code(cpu: &UnicornCPU, addr: u64, insns: &[u32]) {
|
||||
for (i, insn) in insns.iter().enumerate() {
|
||||
@@ -98,20 +111,24 @@ fn test_efuse_registers_on_mmio_bus() {
|
||||
fn test_efuse_read_chip_id_via_ldr() {
|
||||
let mut cpu = UnicornCPU::new().expect("Failed to create UnicornCPU");
|
||||
|
||||
// Register eFuse at MMIO_BASE so Unicorn's mmio_map hooks intercept LDR
|
||||
// Register eFuse at EFUSE_BASE (0x7000F800) — the dedicated mmio_map
|
||||
// hook in UnicornCPU intercepts ARM64 LDR targeting this address.
|
||||
cpu.mmio_bus_mut()
|
||||
.register_device("efuse", MMIO_BASE, EFUSE_SIZE, EfuseArray::new_t210());
|
||||
.register_device("efuse", EFUSE_BASE, EFUSE_SIZE, EfuseArray::new_t210());
|
||||
|
||||
// Code at 0x1000:
|
||||
// MOVZ X1, #0x1000, LSL #16 ; X1 = MMIO_BASE (0x10000000)
|
||||
// MOVZ X1, #0xF800 ; X1 = 0xF800
|
||||
// MOVK X1, #0x7000, LSL #16 ; X1 = EFUSE_BASE (0x7000F800)
|
||||
// LDR W0, [X1] ; load 32-bit chip ID → W0 (X0 low 32b)
|
||||
// BRK #0
|
||||
let code_addr = 0x1000u64;
|
||||
let [movz, movk] = encode_load_efuse_base_into(1);
|
||||
write_code(
|
||||
&cpu,
|
||||
code_addr,
|
||||
&[
|
||||
encode_movz(1, 0x1000, 1), // X1 = 0x10000000
|
||||
movz, // MOVZ X1, #0xF800
|
||||
movk, // MOVK X1, #0x7000, LSL #16 → X1 = EFUSE_BASE
|
||||
encode_ldr_w0_x1(), // LDR W0, [X1] → reads offset 0 (chip ID)
|
||||
encode_brk(),
|
||||
],
|
||||
@@ -133,19 +150,22 @@ fn test_efuse_read_vendor_code_via_ldr() {
|
||||
let mut cpu = UnicornCPU::new().expect("Failed to create UnicornCPU");
|
||||
|
||||
cpu.mmio_bus_mut()
|
||||
.register_device("efuse", MMIO_BASE, EFUSE_SIZE, EfuseArray::new_t210());
|
||||
.register_device("efuse", EFUSE_BASE, EFUSE_SIZE, EfuseArray::new_t210());
|
||||
|
||||
// Code at 0x1000:
|
||||
// MOVZ X1, #0x1000, LSL #16 ; X1 = MMIO_BASE
|
||||
// MOVZ X1, #0xF800 ; X1 = 0xF800
|
||||
// MOVK X1, #0x7000, LSL #16 ; X1 = EFUSE_BASE
|
||||
// LDR W0, [X1, #4] ; load 32-bit from offset 4 → vendor code
|
||||
// BRK #0
|
||||
let code_addr = 0x1000u64;
|
||||
let [movz, movk] = encode_load_efuse_base_into(1);
|
||||
write_code(
|
||||
&cpu,
|
||||
code_addr,
|
||||
&[
|
||||
encode_movz(1, 0x1000, 1), // X1 = 0x10000000
|
||||
encode_ldr_w_offset(0, 1, 4), // LDR W0, [X1, #4]
|
||||
movz, // MOVZ X1, #0xF800
|
||||
movk, // MOVK X1, #0x7000, LSL #16 → X1 = EFUSE_BASE
|
||||
encode_ldr_w_offset(0, 1, 4), // LDR W0, [X1, #4]
|
||||
encode_brk(),
|
||||
],
|
||||
);
|
||||
@@ -165,23 +185,26 @@ fn test_efuse_read_dram_config_via_ldr() {
|
||||
let mut cpu = UnicornCPU::new().expect("Failed to create UnicornCPU");
|
||||
|
||||
cpu.mmio_bus_mut()
|
||||
.register_device("efuse", MMIO_BASE, EFUSE_SIZE, EfuseArray::new_t210());
|
||||
.register_device("efuse", EFUSE_BASE, EFUSE_SIZE, EfuseArray::new_t210());
|
||||
|
||||
// DRAM config is at offset 0x100 — word 0 of Reserved_ODM4.
|
||||
// Value: 0x00000004 (DRAM size = 4 GB).
|
||||
// Code:
|
||||
// MOVZ X1, #0x1000, LSL #16 ; X1 = MMIO_BASE
|
||||
// MOVZ X1, #0xF800 ; X1 = 0xF800
|
||||
// MOVK X1, #0x7000, LSL #16 ; X1 = EFUSE_BASE
|
||||
// MOVZ X2, #0x100 ; X2 = 0x100 (offset for DRAM config)
|
||||
// ADD X1, X1, X2 ; X1 = MMIO_BASE + 0x100
|
||||
// ADD X1, X1, X2 ; X1 = EFUSE_BASE + 0x100
|
||||
// LDR W0, [X1] ; load DRAM config word
|
||||
// BRK #0
|
||||
let code_addr = 0x1000u64;
|
||||
let [movz, movk] = encode_load_efuse_base_into(1);
|
||||
write_code(
|
||||
&cpu,
|
||||
code_addr,
|
||||
&[
|
||||
encode_movz(1, 0x1000, 1), // X1 = 0x10000000
|
||||
encode_movz(2, 0x100, 0), // X2 = 0x100
|
||||
movz, // MOVZ X1, #0xF800
|
||||
movk, // MOVK X1, #0x7000, LSL #16 → X1 = EFUSE_BASE
|
||||
encode_movz(2, 0x100, 0), // MOVZ X2, #0x100
|
||||
0x8B02_0021, // ADD X1, X1, X2
|
||||
encode_ldr_w0_x1(), // LDR W0, [X1]
|
||||
encode_brk(),
|
||||
@@ -203,23 +226,26 @@ fn test_efuse_read_security_flags_via_ldr() {
|
||||
let mut cpu = UnicornCPU::new().expect("Failed to create UnicornCPU");
|
||||
|
||||
cpu.mmio_bus_mut()
|
||||
.register_device("efuse", MMIO_BASE, EFUSE_SIZE, EfuseArray::new_t210());
|
||||
.register_device("efuse", EFUSE_BASE, EFUSE_SIZE, EfuseArray::new_t210());
|
||||
|
||||
// Security flags at offset 0x108 (word 2 of Reserved_ODM4).
|
||||
// Value: 0x00000001 (secure boot enabled).
|
||||
// Code:
|
||||
// MOVZ X1, #0x1000, LSL #16 ; X1 = MMIO_BASE
|
||||
// MOVZ X1, #0xF800 ; X1 = 0xF800
|
||||
// MOVK X1, #0x7000, LSL #16 ; X1 = EFUSE_BASE
|
||||
// MOVZ X2, #0x108 ; X2 = 0x108
|
||||
// ADD X1, X1, X2 ; X1 = MMIO_BASE + 0x108
|
||||
// ADD X1, X1, X2 ; X1 = EFUSE_BASE + 0x108
|
||||
// LDR W0, [X1] ; load security flags
|
||||
// BRK #0
|
||||
let code_addr = 0x1000u64;
|
||||
let [movz, movk] = encode_load_efuse_base_into(1);
|
||||
write_code(
|
||||
&cpu,
|
||||
code_addr,
|
||||
&[
|
||||
encode_movz(1, 0x1000, 1), // X1 = 0x10000000
|
||||
encode_movz(2, 0x108, 0), // X2 = 0x108
|
||||
movz, // MOVZ X1, #0xF800
|
||||
movk, // MOVK X1, #0x7000, LSL #16 → X1 = EFUSE_BASE
|
||||
encode_movz(2, 0x108, 0), // MOVZ X2, #0x108
|
||||
0x8B02_0021, // ADD X1, X1, X2
|
||||
encode_ldr_w0_x1(), // LDR W0, [X1]
|
||||
encode_brk(),
|
||||
|
||||
Reference in New Issue
Block a user