mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-03-12 10:06:47 -04:00

Allow FW RAM access only in the following execution contexts: - Firmware mode - IRQ_SYSCALL_HI Input port `system_mode` of the `fw_ram` module is replaced with an enable port. Since access to FW RAM not longer depend only on system_mode
124 lines
2.8 KiB
ArmAsm
124 lines
2.8 KiB
ArmAsm
/*
|
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
|
* SPDX-License-Identifier: GPL-2.0-only
|
|
*/
|
|
|
|
// This firmware copies an app from ROM to app RAM. The app triggers both
|
|
// IRQ_SYSCALL_HI and IRQ_SYSCALL_LO. One after the other. Finally, the
|
|
// app tries to jump firmware. This should result in a trap since the
|
|
// app in executing in app mode.
|
|
//
|
|
|
|
#include "custom_ops.S" // PicoRV32 custom instructions
|
|
|
|
#define illegal_insn() .word 0
|
|
|
|
.section ".text.init"
|
|
.globl _start
|
|
_start:
|
|
j init
|
|
|
|
//
|
|
// IRQ handler
|
|
//
|
|
.=0x10 // IRQ handler at fixed address 0x10
|
|
irq_handler:
|
|
// PicoRV32 stores the IRQ bitmask in x4.
|
|
// If bit 31 is 1: IRQ31 was triggered.
|
|
// If bit 30 is 1: IRQ30 was triggered.
|
|
irq_syscall_lo_check:
|
|
li t4, (1 << 30)
|
|
bne x4, t4, irq_syscall_hi_check
|
|
// Firmware RAM should not be readable from IRQ_SYSCALL_LO
|
|
call check_cannot_read_test_val_from_fw_ram
|
|
j irq_source_check_done
|
|
irq_syscall_hi_check:
|
|
li t4, (1 << 31)
|
|
bne x4, t4, unexpected_irq
|
|
// Firmware RAM should be readable from IRQ_SYSCALL_HI
|
|
call check_can_read_test_val_from_fw_ram
|
|
j irq_source_check_done
|
|
unexpected_irq:
|
|
illegal_insn()
|
|
irq_source_check_done:
|
|
picorv32_retirq_insn() // Return from interrupt
|
|
|
|
//
|
|
// Init
|
|
//
|
|
.=0x100
|
|
init:
|
|
// Save test value in firmware RAM
|
|
li t0, 0xd0000000
|
|
li t1, 0x5555aaaa
|
|
sw t1, 0(t0)
|
|
|
|
// Firmware RAM should be readable from firmware mode
|
|
call check_can_read_test_val_from_fw_ram
|
|
|
|
|
|
// Enable IRQs
|
|
li t0, 0x3fffffff // IRQ31 & IRQ30 mask
|
|
picorv32_maskirq_insn(zero, t0) // Enable IRQs
|
|
|
|
// Copy app to App RAM
|
|
la t0, app_start
|
|
la t1, app_end
|
|
li t2, 0x40000000 // 0x40000000: App RAM
|
|
copy_app:
|
|
lw t3, 0(t0)
|
|
sw t3, 0(t2)
|
|
addi t0, t0, 4
|
|
addi t2, t2, 4
|
|
bleu t0, t1, copy_app
|
|
|
|
// Jump to app
|
|
li t2, 0x40000000 // 0x40000000: App RAM
|
|
jalr zero, 0(t2)
|
|
|
|
//
|
|
// App
|
|
//
|
|
.align 4
|
|
app_start:
|
|
// Firmware RAM should not be readable from app mode
|
|
call check_cannot_read_test_val_from_fw_ram
|
|
|
|
// Raise IRQ_SYSCALL_HI
|
|
li t0, 0xe1000000 // IRQ_SYSCALL_HI (IRQ31) trigger address
|
|
sw zero, 0(t0) // Raise IRQ by writing to interrupt trigger address.
|
|
// Writing any data triggers an interrupt.
|
|
|
|
// Raise IRQ_SYSCALL_LO
|
|
li t0, 0xe0000000 // IRQ_SYSCALL_LO (IRQ30) trigger address
|
|
sw zero, 0(t0) // Raise IRQ by writing to interrupt trigger address.
|
|
// Writing any data triggers an interrupt.
|
|
|
|
jalr zero, 0(zero) // Jumping to firmware. Expecting trap
|
|
app_loop:
|
|
j app_loop
|
|
|
|
|
|
check_cannot_read_test_val_from_fw_ram:
|
|
li t0, 0xd0000000
|
|
lw t1, 0(t0)
|
|
li t2, 0
|
|
bne t1, t2, cannot_read_test_val_from_fw_ram_fail
|
|
ret
|
|
cannot_read_test_val_from_fw_ram_fail:
|
|
illegal_insn()
|
|
|
|
check_can_read_test_val_from_fw_ram:
|
|
// Check that saved test value can not be read while in app mode
|
|
li t0, 0xd0000000
|
|
lw t1, 0(t0)
|
|
li t2, 0x5555aaaa
|
|
bne t1, t2, can_read_test_val_from_fw_ram_fail
|
|
ret
|
|
can_read_test_val_from_fw_ram_fail:
|
|
illegal_insn()
|
|
|
|
.align 4
|
|
app_end:
|
|
|