# Boot Renode Script (boot.resc)


# Add this script's path to the global path, so
# we can include files relative to ourselves.
path add $ORIGIN

i @peripherals/ESP32_SPIController.cs
i @peripherals/ESP32_UART.cs
i @peripherals/ESP32S3_EXTMEM.cs
i @peripherals/ESP32S3_GPIO.cs
i @peripherals/ESP32S3_RTC_CNTL.cs
i @peripherals/ESP32S3_RTC_I2C_PWDET.cs

using sysbus

mach create "SoC"
machine LoadPlatformDescription @badge.repl

# Silence regions we don't want to implement yet
sysbus SilenceRange <0x60038000, 0x60038FFF> # USB_DEVICE
sysbus SilenceRange <0x60080000, 0x60080FFF> # USB0
sysbus SilenceRange <0x60039000, 0x60039FFF> # USB_WRAP

machine StartGdbServer 3333 true

showAnalyzer uart0
showAnalyzer uart1

# The macro `reset` gets called implicitly when running `machine Reset`
macro reset
"""
sysbus LoadELF @blackmagic.elf
sysbus LoadBinary @partition-table.bin 0x3C008000
sysbus LoadBinary @esp32s3-irom.bin 0x40000000
sysbus LoadBinary @esp32s3-drom.bin 0x3FF00000
#sysbus LoadBinary @esp32s3-efuses.bin 0x60007000
sysbus LoadELF @bootloader.elf
#copy_bootrom_data
setup_hooks sysbus.cpu
#sysbus WriteDoubleWord 0x600c40a0 0x8
cpu PC 0x40000400
"""

python
"""
def memcpy(dest, src, n):
    data = self.Machine.SystemBus.ReadBytes(src, n)
    self.Machine.SystemBus.WriteBytes(data, dest)

def mc_setup_hooks(cpu):
    from Antmicro.Renode.Peripherals.CPU import RegisterValue
#   LR, SP, R0
    A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 = 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
    cpu = self.Machine[cpu]

    def format_val(v):
        try:
            return "0x{:08x}".format(long(v))
        except:
            return str(v)

    def log(*args):
        cpu.Log(LogLevel.Warning, "{0}", ", ".join(map(format_val, args)))

    def get(reg, raw=True):
        v = cpu.GetRegisterUnsafe(reg)
        if raw:
            return v.RawValue
        return v

    def lr():
        return get(A0, raw=False)

    def args():
        return list(map(get, (A2, A3, A4)))

    def set(reg, val):
        cpu.SetRegisterUnsafe(reg, RegisterValue.Create(val, 32))

    def cstr(addr):
        out = bytearray()
        b = self.Machine.SystemBus.ReadByte(addr)
        while b != 0:
            out.append(b)
            addr += 1
            b = self.Machine.SystemBus.ReadByte(addr)
        return bytes(out)

    def hook(addr_or_name):
        def wrap(fn):
            if isinstance(addr_or_name, str):
                addr = self.Machine.SystemBus.GetSymbolAddress(addr_or_name)
            else:
                addr = addr_or_name
            cpu.AddHook(addr, fn)
            return fn
        return wrap

    @hook(0x4004578f)
    def ets_run_flash_bootloader_hook(cpu, pc):
        log("ets_run_flash_bootloader", *args())
        # this function loads software bootloader
        # we have it already loaded, just jump before
        # executing user code (software bootloader)
        cpu.PC = RegisterValue.Create(0x40043ca3,32)

    @hook(0x40043ca6)
    def hook_soft_address(cpu, pc):
        log("hook_soft_address", *args())
        # write address already loaded software bootloader to register
        self.Machine.SystemBus.WriteDoubleWord(0x3fcedf14, 0x403c9908)

    @hook(0x403c9a1c)
    def hook_cpu_rev_check(cpu, pc):
        log("cpu_rev_check", *args())
        cpu.PC = RegisterValue.Create(0x403c9a1f,32)

    @hook (0x403ce971)
    def hook_skip_part_size_check(cpu, pc):
        log("skip_part_size_check", *args())
        cpu.PC = RegisterValue.Create(0x403ce9a3,32)

    @hook (0x403ce129)
    def hook_skip_flash_check(cpu, pc):
        log("skip_flash_check", *args())
        cpu.PC = RegisterValue.Create(0x403ce1b0,32)
"""

runMacro $reset

start
