/*
 * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
 * All rights reserved.
 *
 * This software was developed by the University of Cambridge Computer
 * Laboratory as part of the CTSRD Project, with support from the UK Higher
 * Education Innovation Fund (HEIF).
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "arch/arm/freebsd/process.hh"

#include <sys/mman.h>
#include <sys/param.h>
#include <sys/syscall.h>
#if !defined ( __GNU_LIBRARY__ )
#include <sys/sysctl.h>
#endif
#include <sys/types.h>
#include <utime.h>

#include "arch/arm/freebsd/freebsd.hh"
#include "arch/arm/isa_traits.hh"
#include "base/loader/object_file.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "kern/freebsd/freebsd.hh"
#include "sim/process.hh"
#include "sim/syscall_desc.hh"
#include "sim/syscall_emul.hh"
#include "sim/system.hh"

using namespace std;
using namespace ArmISA;

namespace
{

class ArmFreebsdObjectFileLoader : public Process::Loader
{
  public:
    Process *
    load(ProcessParams *params, ::Loader::ObjectFile *obj_file) override
    {
        auto arch = obj_file->getArch();
        auto opsys = obj_file->getOpSys();

        if (arch != ::Loader::Arm && arch != ::Loader::Thumb &&
                arch != ::Loader::Arm64) {
            return nullptr;
        }

        if (opsys != ::Loader::FreeBSD)
            return nullptr;

        if (arch == ::Loader::Arm64)
            return new ArmFreebsdProcess64(params, obj_file, arch);
        else
            return new ArmFreebsdProcess32(params, obj_file, arch);
    }
};

ArmFreebsdObjectFileLoader loader;

} // anonymous namespace

static SyscallReturn
issetugidFunc(SyscallDesc *desc, ThreadContext *tc)
{
    return 0;
}

#if !defined ( __GNU_LIBRARY__ )
static SyscallReturn
sysctlFunc(SyscallDesc *desc, ThreadContext *tc, Addr namep, size_t nameLen,
           Addr oldp, Addr oldlenp, Addr newp, size_t newlen)
{
    uint64_t ret;

    BufferArg buf(namep, sizeof(size_t));
    BufferArg buf2(oldp, sizeof(size_t));
    BufferArg buf3(oldlenp, sizeof(size_t));
    BufferArg buf4(newp, sizeof(size_t));

    buf.copyIn(tc->getVirtProxy());
    buf2.copyIn(tc->getVirtProxy());
    buf3.copyIn(tc->getVirtProxy());

    void *hnewp = NULL;
    if (newp) {
        buf4.copyIn(tc->getVirtProxy());
        hnewp = (void *)buf4.bufferPtr();
    }

    uint32_t *hnamep = (uint32_t *)buf.bufferPtr();
    void *holdp = (void *)buf2.bufferPtr();
    size_t *holdlenp = (size_t *)buf3.bufferPtr();

    ret = sysctl((int *)hnamep, nameLen, holdp, holdlenp, hnewp, newlen);

    buf.copyOut(tc->getVirtProxy());
    buf2.copyOut(tc->getVirtProxy());
    buf3.copyOut(tc->getVirtProxy());
    if (newp)
        buf4.copyOut(tc->getVirtProxy());

    return (ret);
}
#endif

static SyscallDescTable<ArmFreebsdProcess32::SyscallABI> syscallDescs32({});

static SyscallDescTable<ArmFreebsdProcess64::SyscallABI> syscallDescs64 = {
    {    1, "exit", exitFunc },
    {    3, "read", readFunc<ArmFreebsd64> },
    {    4, "write", writeFunc<ArmFreebsd64> },
    {   17, "obreak", brkFunc },
    {   54, "ioctl", ioctlFunc<ArmFreebsd64> },
    {   58, "readlink", readlinkFunc },
    {  117, "getrusage", getrusageFunc<ArmFreebsd64> },
    {  189, "fstat", fstatFunc<ArmFreebsd64> },
#if !defined ( __GNU_LIBRARY__ )
    {  202, "sysctl", sysctlFunc },
#else
    {  202, "sysctl" },
#endif
    {  253, "issetugid", issetugidFunc },
    {  477, "mmap", mmapFunc<ArmFreebsd64> }
};

ArmFreebsdProcess32::ArmFreebsdProcess32(ProcessParams * params,
        ::Loader::ObjectFile *objFile, ::Loader::Arch _arch) :
    ArmProcess32(params, objFile, _arch)
{}

ArmFreebsdProcess64::ArmFreebsdProcess64(ProcessParams * params,
        ::Loader::ObjectFile *objFile, ::Loader::Arch _arch) :
    ArmProcess64(params, objFile, _arch)
{}

void
ArmFreebsdProcess32::initState()
{
    ArmProcess32::initState();
    // The 32 bit equivalent of the comm page would be set up here.
}

void
ArmFreebsdProcess64::initState()
{
    ArmProcess64::initState();
    // The 64 bit equivalent of the comm page would be set up here.
}

void
ArmFreebsdProcess32::syscall(ThreadContext *tc)
{
    ArmProcess32::syscall(tc);
    syscallDescs32.get(tc->readIntReg(INTREG_R7))->doSyscall(tc);
}

void
ArmFreebsdProcess64::syscall(ThreadContext *tc)
{
    ArmProcess64::syscall(tc);
    syscallDescs64.get(tc->readIntReg(INTREG_X8))->doSyscall(tc);
}
