Files
2021-02-08 19:20:55 +01:00

169 lines
7.3 KiB
Python

from unicorn import unicorn_const, Uc, arm_const
from .periph import *
import struct
import time
import sys
from queue import Queue
from . import consts
from threading import Lock
import os
lcd_lock = Lock()
message_input_queue = Queue()
message_output_queue = Queue()
lcd_interrupt_queue = Queue()
_interrupt_handler_mode = consts.INTERRUPT_NONE
_current_clock = time.monotonic_ns()
_saved_context = None
_last_pc_values = []
lcd = ("LTDC", ltdc.LTDC(), 0x5000_1000, 0x5000_1FFF)
periphs = [
("FLASH", flash.FLASH(), 0x5200_2000, 0x5200_2FFF),
("RCC", rcc.RCC(), 0x5802_4400, 0x5802_47FF),
("PWR", pwr.PWR(), 0x5802_4800, 0x5802_4BFF),
("GPIOA", gpioa.GPIOA(), 0x5802_0000, 0x5802_03FF),
("GPIOB", gpiob.GPIOB(), 0x5802_0400, 0x5802_07FF),
("GPIOC", gpioc.GPIOC(), 0x5802_0800, 0x5802_0BFF),
("GPIOD", gpiod.GPIOD(), 0x5802_0C00, 0x5802_0FFF),
("GPIOE", gpioe.GPIOE(), 0x5802_1000, 0x5802_13FF),
("GPIOF", gpiof.GPIOF(), 0x5802_1400, 0x5802_17FF),
("GPIOG", gpiog.GPIOG(), 0x5802_1800, 0x5802_1BFF),
("GPIOH", gpioh.GPIOH(), 0x5802_1C00, 0x5802_1FFF),
("GPIOI", gpioi.GPIOI(), 0x5802_2000, 0x5802_23FF),
("GPIOJ", gpioj.GPIOJ(), 0x5802_2400, 0x5802_27FF),
("GPIOK", gpiok.GPIOK(), 0x5802_2800, 0x5802_2BFF),
("FMC", fmc.FMC(), 0x5200_4000, 0x5200_4FFF),
lcd,
("RTC", rtc.RTC(), 0x5800_4000, 0x5800_43FF),
("SPI2", spi2.SPI2(), 0x4000_3800, 0x4000_3BFF),
("OCTOSPI1", octospi1.OCTOSPI1(), 0x5200_5000, 0x5200_5FFF),
("OCTOSPIM", octospim.OCTOSPIM(), 0x5200_B400, 0x5200_B7FF),
("TIM5", tim5.TIM5(), 0x4000_0C00, 0x4000_0FFF),
("SAI1", sai1.SAI1(), 0x4001_5800, 0x4001_5BFF)
]
def hook_mem_read(mu: Uc, access, address, size, value, user_data):
try:
if access == unicorn_const.UC_MEM_READ:
if address >= 0x4000_0000 and address <= 0x6000_0000:
data = 0
for periph in periphs:
if _between(address, periph[2], periph[3]):
data = periph[1].read_mem(address, size)
mu.mem_write(address, struct.pack('<L', data))
print(periph[0])
break
print(f'access: read, address: 0x{address:08X}, data: 0x{data:08X}, pc: 0x{mu.reg_read(arm_const.UC_ARM_REG_PC):08X}')
elif access == unicorn_const.UC_MEM_READ_UNMAPPED:
print(f'access unmapped memory: read, address: 0x{address:08X}, pc: 0x{mu.reg_read(arm_const.UC_ARM_REG_PC):08X}')
print(f'data executed: {mu.mem_read(mu.reg_read(arm_const.UC_ARM_REG_PC), 4).hex()}')
except KeyboardInterrupt:
mu.emu_stop()
def hook_mem_write(mu: Uc, access, address, size, value, user_data):
try:
if access == unicorn_const.UC_MEM_WRITE:
for periph in periphs:
if _between(address, periph[2], periph[3]):
periph[1].write_mem(address, size, value)
print(periph[0])
break
if address >= 0x4000_0000 and address <= 0x6000_0000:
print(f'access: write, address: 0x{address:08X}, value: 0x{value:08X}, pc: 0x{mu.reg_read(arm_const.UC_ARM_REG_PC):08X}')
...
elif access == unicorn_const.UC_MEM_WRITE_UNMAPPED:
print(f'access unmapped memory: write, address: 0x{address:08X}, value: 0x{value:08X}, pc: 0x{mu.reg_read(arm_const.UC_ARM_REG_PC):08X}')
print(f'data executed: {mu.mem_read(mu.reg_read(arm_const.UC_ARM_REG_PC), 4).hex()}')
except KeyboardInterrupt:
mu.emu_stop()
def hook_mem_fetch(mu: Uc, access, address, size, value, user_data):
global _current_clock
global _interrupt_handler_mode
global _saved_context
global lcd
global _last_pc_values
if address == 0xFFFF_FFF0 and _interrupt_handler_mode > consts.INTERRUPT_NONE:
# print("Fetch with interrupt")
if lcd_lock.locked() and _interrupt_handler_mode == consts.INTERRUPT_LTDC:
lcd_lock.release()
# print("Leave LCD interrupt")
mu.context_restore(_saved_context)
_saved_context = None
mu.reg_write(arm_const.UC_ARM_REG_PC, mu.reg_read(arm_const.UC_ARM_REG_PC) + 1)
_interrupt_handler_mode = consts.INTERRUPT_NONE
elif address == 0xFFFF_FFF0:
print("Fetch but no interrupt")
pass
def hook_intr(mu: Uc, intr_code: int, user_data):
global _current_clock
global _interrupt_handler_mode
global _saved_context
global lcd
global _last_pc_values
if mu.reg_read(arm_const.UC_ARM_REG_PC) == 0xFFFF_FFF0:
if lcd_lock.locked() and _interrupt_handler_mode == consts.INTERRUPT_LTDC:
lcd_lock.release()
# print("Leave LCD interrupt")
mu.context_restore(_saved_context)
_saved_context = None
mu.reg_write(arm_const.UC_ARM_REG_PC, mu.reg_read(arm_const.UC_ARM_REG_PC) + 1)
_interrupt_handler_mode = consts.INTERRUPT_NONE
return
print(f"CPU interrupt: {intr_code}")
print(f"saved context = None? : {_saved_context == None}")
print(f"Interrupt handler mode: {_interrupt_handler_mode}")
print(f'PC: 0x{mu.reg_read(arm_const.UC_ARM_REG_PC):08X}')
print([hex(i) for i in _last_pc_values])
sys.stdout.flush()
os._exit(0)
def hook_code(mu: Uc, address, size, user_data):
global _current_clock
global _interrupt_handler_mode
global _saved_context
global lcd
global _last_pc_values
_last_pc_values.append(mu.reg_read(arm_const.UC_ARM_REG_PC))
if len(_last_pc_values) > 250:
del _last_pc_values[0]
# if mu.mem_read(mu.reg_read(arm_const.UC_ARM_REG_PC), 2) == b'\x30\xbf':
# mu.reg_write(arm_const.UC_ARM_REG_PC, mu.reg_read(arm_const.UC_ARM_REG_PC) + 3)
# return
try:
if lcd[1]._ISR & 8 and _interrupt_handler_mode == consts.INTERRUPT_NONE:
_saved_context = mu.context_save()
_interrupt_handler_mode = consts.INTERRUPT_LTDC
lcd_lock.acquire()
# print("Interrupt LCD")
mu.reg_write(arm_const.UC_ARM_REG_PC, struct.unpack("<L", mu.mem_read(0x0800_01a0, 4))[0])
mu.reg_write(arm_const.UC_ARM_REG_LR, 0xFFFF_FFF0)
elif time.monotonic_ns() - _current_clock > 1_000_000 and _interrupt_handler_mode == consts.INTERRUPT_NONE and address != 0x08010220:
_current_clock = time.monotonic_ns()
_interrupt_handler_mode = consts.INTERRUPT_SYSTICK
_saved_context = mu.context_save()
mu.reg_write(arm_const.UC_ARM_REG_PC, struct.unpack("<L", mu.mem_read(0x0800_003c, 4))[0])
mu.reg_write(arm_const.UC_ARM_REG_LR, 0xFFFF_FFF0)
elif _interrupt_handler_mode > consts.INTERRUPT_NONE and mu.reg_read(arm_const.UC_ARM_REG_LR) == 0xFFFF_FFF0 and mu.mem_read(address, 2) == b'\x70\x47':
if lcd_lock.locked() and _interrupt_handler_mode == consts.INTERRUPT_LTDC:
lcd_lock.release()
# print("Leave LCD interrupt")
mu.context_restore(_saved_context)
_saved_context = None
mu.reg_write(arm_const.UC_ARM_REG_PC, mu.reg_read(arm_const.UC_ARM_REG_PC) + 1)
_interrupt_handler_mode = consts.INTERRUPT_NONE
except KeyboardInterrupt:
mu.emu_stop()
def _between(val: int, min_val: int, max_val: int) -> bool:
return val >= min_val and val <= max_val