I'm trying to secure a i.MX6 board, to detect any attempt at JTAG debugging, using the SNVS violation mechanism.
I configured the SNVS_HPSICR to trigger interrupt if a JTAG is plugged in, and it works !
Once I detect this event, I'm trying to clean the board's memory before resetting it. So far, I only managed to shut down the board, because each time I'm trying to reboot it (see code below), the board reboots but the violation is still asserted : I can't manage to clean SNVS_HP_SVSR.
All the following code is running at PL1 SVC mode, in (Trustzone) Secure state.
After reading https://community.nxp.com/message/388572, here is what I tried:
- Setting the interrupt as fatal or not: all other entries have been tested with SNVS in non secure or soft fail mode
- I tried to write 0x3f in SNVS_HP_SVSR to clear the w1c bits, it doesn't have any effect
- I tried to unregister the interrupt by cleaning SNVS_HPSICR before cleaning SNVS_HP_SVSR, it doesn't have any effect
- I set SNVS_HPCOMR[NPSWA_EN] to test unprivileged access: I managed to change the bit but it still can't clear SNVS_HP_SVSR.
Here is my latest attempt:
/* Acknowledge the interrupt ... */
irq = cpu_regs->acknowledge;
cpu_regs->endofinterrupt = irq;
pr_crit("HPCOMR: 0x%" PRIx32 "\n", reg_read32(snvs_base + SNVS_HPCOMR)); /* 0x2002 */
pr_crit("HPSR: 0x%" PRIx32 "\n", reg_read32(snvs_base + SNVS_HPSR)); /* 0x80000b00 or 0x80000300 */
pr_crit("LPSR: 0x%" PRIx32 "\n", reg_read32(snvs_base + SNVS_LPSR)); /* 0x40000000 */
pr_crit("HPSICR: 0x%" PRIx32 "\n", reg_read32(snvs_base + SNVS_HPSICR)); /* 0x17 */
pr_crit("PANIC IRQ %" PRIu32 " DETECTED !\n", irq); /* interrupt 52 */
/* Current SNVS security mode */
uint32_t status = reg_read32(snvs_base + SNVS_HPSR);
status >>= SNVS_HPSR_SSM_ST_OFFSET;
status &= SNVS_HPSR_SSM_ST_MASK;
pr_crit("SNVS mode: 0x%" PRIx32 "\n", status); /* 0xb or 0x3 */
/* Disable all violation interrupts */
reg_write32(snvs_base + SNVS_HPSICR, 0);
pr_crit("New HPSICR: 0x%" PRIx32 "\n", reg_read32(snvs_base + SNVS_HPSICR)); /* 0x0 */
/* dump & ack the violation IRQ in the SNVS */
status = reg_read32(snvs_base + SNVS_HPSVSR);
pr_crit("SNVS violation status: 0x%" PRIx32 "\n", status); /* 0x2 */
reg_write32(snvs_base + SNVS_HPSVSR, status & UINT32_C(0x3f));
isb();
status = reg_read32(snvs_base + SNVS_HPSVSR);
pr_crit("Checking SNVS status: 0x%" PRIx32 "\n", status); /* /!\ 0x2, w1c didn't work */
/* ... and panic */
panic(PANICL_PANIC_IRQ_VIOLATION);
This only way I found to clear SNVS_HP_SVSR is to push the hardware reboot button.
To reset the board, I'm using WDOG1:
reg_clrset16(WDOG1_BASE_PA, UINT16_C(0xff) << 8, UINT16_C(1) << 2);
// wdog reset sequence
reg_write16(WDOG1_BASE_PA, UINT16_C(0x5555));
reg_write16(WDOG1_BASE_PA, UINT16_C(0xaaaa));
while (1) {
wfi();
}
Can anyone guide me to a way to reboot the board with the violation correctly acknowledged and cleaned up ?
Best,
V.
Solved! Go to Solution.
Hi,
You can inspire from this patch (is basically for iMX7D but should work also for iMX6).
Here we implemented a software work-around resetting the board iMX7D_SabreSD using SNVS module
We program the SNVS alarm for 3 seconds to power on system after we issue the SNVS shutdown system, seems something very similar with your needs.
The u-boot branch used for this patch is imx_v2017.03_4.9.11_1.0.0_ga (from [1]).
Best regards,
Marius
Hi,
You can inspire from this patch (is basically for iMX7D but should work also for iMX6).
Here we implemented a software work-around resetting the board iMX7D_SabreSD using SNVS module
We program the SNVS alarm for 3 seconds to power on system after we issue the SNVS shutdown system, seems something very similar with your needs.
The u-boot branch used for this patch is imx_v2017.03_4.9.11_1.0.0_ga (from [1]).
Best regards,
Marius
Dear mariusviorelgrigoras-b32331, I tried to adapt your patch on my i.MX6 board, and I get the SNVS_LP Alarm interrupt (LPSR[LPTA] is set to 1), but I don't reboot, I resume my execution. The board doesn't seem to have been powered off.
I'll try to check on my side, but by any chance do you know if setting SNVS_LPCR to 0x60 is enough to poweroff the board or did I miss another important step ?
It seems that my write to SNVS_LPCR is somehow not done correctly:
uint32_t reg = reg_read32(snvs_base + SNVS_LPCR);
reg |= UINT32_C(0x62);
reg_write32(snvs_base + SNVS_LPCR, reg);
/* wait for reset to assert... */
pr_msg("waiting for reset to be triggered \n");
pr_msg("SNVS_LPCR = 0x%" PRIx32 " (wrote 0x%" PRIx32 ")\n",
reg_read32(snvs_base + SNVS_LPCR), reg);
This codes displays a value written of 0x63 but a value read in the register of 0x23, the bit TOP "Turn off System Power" should be set until the end of the power off, and it is not set .
Thanks, I'll have a look.
From what I understand, you program the SNVS_LP alarm to trigger an interrupt after PowerOff has been achieved.
It didn't work out of the box, but I might be missing some configuration so that the interrupt triggers a reboot.
I'll look more into detail to the u-boot branch you linked, thank you !