/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <stddef.h>
#include <inttypes.h>
#include <mcu/cortex_m33.h>
#include <mcu/nrf5340_hal.h>
#include <bsp/bsp.h>
#include <nrf_gpio.h>

#if MCUBOOT_MYNEWT
#include <bootutil/bootutil.h>
#endif
#include <os/util.h>

#if MYNEWT_VAL(BOOT_LOADER) && !MYNEWT_VAL(MCU_APP_SECURE)

struct periph_id_range {
    uint8_t first;
    uint8_t last;
};

/* Array of peripheral ID ranges that will be set as unsecure before bootloader jumps to application code */
static const struct periph_id_range ns_peripheral_ids[] = {
    { 0, 0 },
    { 4, 6 },
    { 8, 12 },
    { 14, 17 },
    { 20, 21 },
    { 23, 36 },
    { 38, 38 },
    { 40, 40 },
    { 42, 43 },
    { 45, 45 },
    { 48, 48 },
    { 51, 52 },
    { 54, 55 },
    { 57, 57 },
    { 66, 66 },
    { 128, 129 },
};

/* Below is to unmangle comma separated GPIO pins from MYNEWT_VAL */
#define _Args(...) __VA_ARGS__
#define STRIP_PARENS(X) X
#define UNMANGLE_MYNEWT_VAL(X) STRIP_PARENS(_Args X)

#if MYNEWT_VAL(MCU_GPIO_NET)
static const unsigned int net_gpios[] = { UNMANGLE_MYNEWT_VAL(MYNEWT_VAL(MCU_GPIO_NET)) };
#endif
#if MYNEWT_VAL(MCU_GPIO_PERIPH)
static const unsigned int periph_gpios[] = { UNMANGLE_MYNEWT_VAL(MYNEWT_VAL(MCU_GPIO_PERIPH)) };
#endif

extern uint8_t __StackTop[];

void
hal_system_start(void *img_start)
{
    int i;
    int j;
    int range_count;
    struct flash_sector_range sr;
    uintptr_t *img_data;
    /* Number of 16kB flash regions used by bootloader */
    int bootloader_flash_regions;
    __attribute__((cmse_nonsecure_call, noreturn)) void (* app_reset)(void);

    __disable_irq();

    /* Mark selected peripherals as unsecure */
    for (i = 0; i < ARRAY_SIZE(ns_peripheral_ids); ++i) {
        for (j = ns_peripheral_ids[i].first; j <= ns_peripheral_ids[i].last; ++j) {
            if (((NRF_SPU->PERIPHID[j].PERM & SPU_PERIPHID_PERM_PRESENT_Msk) == 0) ||
                ((NRF_SPU->PERIPHID[j].PERM & SPU_PERIPHID_PERM_SECUREMAPPING_Msk) < SPU_PERIPHID_PERM_SECUREMAPPING_UserSelectable)) {
                continue;
            }
            NRF_SPU->PERIPHID[j].PERM &= ~SPU_PERIPHID_PERM_SECATTR_Msk;
        }
    }

    /* Route exceptions to non-secure, allow software reset from non-secure */
    SCB->AIRCR = 0x05FA0000 | (SCB->AIRCR & (~SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_SYSRESETREQS_Msk)) | SCB_AIRCR_BFHFNMINS_Msk;
    for (i = 0; i < ARRAY_SIZE(NVIC->ITNS); ++i) {
        NVIC->ITNS[i] = 0xFFFFFFFF;
    }

    /* Mark non-bootloader flash regions as non-secure */
    flash_area_to_sector_ranges(FLASH_AREA_BOOTLOADER, &range_count, &sr);
    bootloader_flash_regions = (sr.fsr_sector_count * sr.fsr_sector_size) / 0x4000;

    for (i = bootloader_flash_regions; i < 64; ++i) {
        NRF_SPU->FLASHREGION[i].PERM &= ~SPU_FLASHREGION_PERM_SECATTR_Msk;
    }

    /* Mark RAM as non-secure */
    for (i = 0; i < 64; ++i) {
        NRF_SPU->RAMREGION[i].PERM &= ~SPU_FLASHREGION_PERM_SECATTR_Msk;
    }

    /* Move DPPI to non-secure area */
    NRF_SPU->DPPI->PERM = 0;

    /* Move GPIO to non-secure area */
    NRF_SPU->GPIOPORT[0].PERM = 0;
    NRF_SPU->GPIOPORT[1].PERM = 0;

#if MYNEWT_VAL(MCU_GPIO_NET)
    for (i = 0; i < ARRAY_SIZE(net_gpios); ++i) {
        nrf_gpio_pin_mcu_select(net_gpios[i], GPIO_PIN_CNF_MCUSEL_NetworkMCU);
    }
#endif

#if MYNEWT_VAL(MCU_GPIO_PERIPH)
    for (i = 0; i < ARRAY_SIZE(periph_gpios); ++i) {
        nrf_gpio_pin_mcu_select(periph_gpios[i], GPIO_PIN_CNF_MCUSEL_Peripheral);
    }
#endif

    /*
     * For now whole RAM is marked as non-secure. To prevent data leak from secure to
     * non-secure, whole RAM is cleared before starting application code.
     * Interrupt VTOR for secure world that was previously put in RAM is moved to
     * flash again.
     */
    SCB->VTOR = 0;
    /*
     * Normal loop here is inlined by GCC to call to memset hence asm version of
     * memset that does not use stack (that just get erased).
     */
    asm volatile("    mov     r0, #0        \n"
                 "1:  stmia   %0!, {r0}     \n"
                 "    cmp     %0, %1        \n"
                 "    blt     1b            \n"
        :
        : "r" (&_ram_start), "r" (&__StackTop)
        : "r0");
    /* Application startup code expects interrupts to be enabled */
    __enable_irq();

    img_data = img_start;
    app_reset = (void *)(img_data[1]);
    __TZ_set_MSP_NS(img_data[0]);
    app_reset();
}

#else

/**
 * Boots the image described by the supplied image header.
 *
 * @param hdr                   The header for the image to boot.
 */
void __attribute__((naked))
hal_system_start(void *img_start)
{
    uint32_t *img_data = img_start;

    asm volatile (".syntax unified        \n"
                  /* 1st word is stack pointer */
                  "    msr  msp, %0       \n"
                  /* 2nd word is a reset handler (image entry) */
                  "    bx   %1            \n"
                  : /* no output */
                  : "r" (img_data[0]), "r" (img_data[1]));
}

#endif

/**
 * Boots the image described by the supplied image header.
 * This routine is used in split-app scenario when loader decides
 * that it wants to run the app instead.
 *
 * @param hdr                   The header for the image to boot.
 */
void
hal_system_restart(void *img_start)
{
    int i;

    /*
     * NOTE: on reset, PRIMASK should have global interrupts enabled so
     * the code disables interrupts, clears the interrupt enable bits,
     * clears any pending interrupts, then enables global interrupts
     * so processor looks like state it would be in if it reset.
     */
    __disable_irq();
    for (i = 0; i < sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]); i++) {
        NVIC->ICER[i] = 0xffffffff;
    }

    for (i = 0; i < sizeof(NVIC->ICPR) / sizeof(NVIC->ICPR[0]); i++) {
        NVIC->ICPR[i] = 0xffffffff;
    }
    __enable_irq();

    hal_system_start(img_start);
}
