/*
 * protect.c
 *
 * Copyright (C) 2012-2020, Samsung Electronics Co., Ltd.
 *
 * TZPC, TZASC interface, common implementation
 */

#include <tee_internal_api.h>
#include <errno.h>
#include <fcntl.h>
#include <macros.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "tuiHal.h"
#include "bsp_common.h"
#include "board.h"
#include "dbg.h"
#include "protect.h"

#define TZPC_IO_PROTECT     0
#define TZPC_IO_UNPROTECT   1
#define TZASC_IO_PROTECT    0
#define TZASC_IO_UNPROTECT  1

struct tzasc_prot {
    uint32_t rgn_no;
    uint64_t base;
    uint64_t size;
};

TEE_Result protect_by_tzpc(unsigned int dev_id, bool do_protect)
{
    TEE_Result ret  = TEE_SUCCESS;

    if (do_protect) {
        dbgPrintf("TZPC Protect, dev_id = %d\n", dev_id);
    } else {
        dbgPrintf("TZPC Unprotect, dev_id = %d\n", dev_id);
    }

    int fd = open("/dev/dpu", O_RDONLY, 0);
    if (fd < 0) {
        if (errno == EBUSY) {
            ret = TEE_ERROR_BUSY;
        } else {
            ret = TEE_ERROR_ACCESS_DENIED;
        }
    } else {
        if (ioctl(fd, do_protect?TZPC_IO_PROTECT:TZPC_IO_UNPROTECT, dev_id) < 0) {
            ret = TEE_ERROR_GENERIC;
        }
        ALWAYS_ZERO(close(fd));
    }
    dbgPrintf("TZPC - %s,  ret = 0x%08x\n", (ret == 0)?"SUCCESS":"FAILED", ret);
    return ret;
}

TEE_Result protect_by_tzasc(unsigned int region,
                            unsigned long start,
                            unsigned int size,
                            bool do_protect)
{
    TEE_Result ret  = TEE_SUCCESS;
    struct tzasc_prot cfg;
    unsigned long param;

    if (do_protect) {
        dbgPrintf("TZASC Protect, region = %d, phys.address = 0x%08lx,"
                  " size = %d\n", region, start, size);
        param = (unsigned long)&cfg;
        cfg.rgn_no = region;
        cfg.base = start;
        cfg.size = size;
    } else {
        dbgPrintf("TZASC Unprotect, region = %d\n", region);
        param = region;
    }

    int fd = open("/dev/tzasc", O_RDONLY, 0);
    if (fd < 0) {
        if (errno == EBUSY) {
            ret = TEE_ERROR_BUSY;
        } else {
            ret = TEE_ERROR_ACCESS_DENIED;
        }
    } else {
        if (ioctl(fd, do_protect?TZASC_IO_PROTECT:TZASC_IO_UNPROTECT, param) < 0) {
            ret = TEE_ERROR_GENERIC;
        }
        ALWAYS_ZERO(close(fd));
    }
    dbgPrintf("TZASC - %s,  ret = 0x%08x\n", (ret == 0)?"SUCCESS":"FAILED", ret);
    return ret;
}
