AnsweredAssumed Answered

i.MX6 and JTAG security violation

Question asked by Vincent Siles on Mar 14, 2018
Latest reply on Mar 14, 2018 by Vincent Siles

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.

Outcomes