/*
 * Copyright 2017, Data61
 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
 * ABN 41 687 119 230.
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(DATA61_BSD)
 */

#pragma once
/* Builder functions for process configs */
#include <autoconf.h>
#include <sel4utils/gen_config.h>
#include <sel4/types.h>
#include <sel4utils/api.h>
#include <sel4utils/elf.h>
#include <vka/vka.h>

typedef struct {
    /* should we handle elf logic at all? */
    bool is_elf;
    /* if so what is the image name? */
    const char *image_name;
    /* Do you want the elf image preloaded? */
    bool do_elf_load;

    /* otherwise what is the entry point and sysinfo? */
    void *entry_point;
    uintptr_t sysinfo;

    /* should we create a default single level cspace? */
    bool create_cspace;
    /* if so how big ? */
    int one_level_cspace_size_bits;
    /* if not by what CPtr can the initial thread of the process
     * invoke its own TCB (optional) */
    seL4_CPtr dest_cspace_tcb_cptr;

    /* otherwise what is the root cnode ?*/
    /* Note if you use a custom cspace then
     * sel4utils_copy_cap_to_process etc will not work */
    vka_object_t cnode;

    /* do you want us to create a vspace for you? */
    bool create_vspace;
    /* if not what is the page dir, and what is the vspace */
    vspace_t *vspace;
    vka_object_t page_dir;

    /* if so, is there a regions you want left clear?*/
    sel4utils_elf_region_t *reservations;
    int num_reservations;

    /* do you want a fault endpoint created? */
    bool create_fault_endpoint;
    /* otherwise what is it */
    vka_object_t fault_endpoint;

    /* scheduling params */
    sched_params_t sched_params;

    seL4_CPtr asid_pool;
} sel4utils_process_config_t;

static inline sel4utils_process_config_t process_config_asid_pool(sel4utils_process_config_t config,
                                                                  seL4_CPtr asid_pool)
{
    config.asid_pool = asid_pool;
    return config;
}

static inline sel4utils_process_config_t process_config_auth(sel4utils_process_config_t config, seL4_CPtr auth)
{
    config.sched_params.auth = auth;
    return config;
}

static inline sel4utils_process_config_t process_config_new(simple_t *simple)
{
    sel4utils_process_config_t config = {0};
    config = process_config_auth(config, simple_get_tcb(simple));
    return process_config_asid_pool(config, simple_get_init_cap(simple, seL4_CapInitThreadASIDPool));
}

static inline sel4utils_process_config_t process_config_elf(sel4utils_process_config_t config, const char *image_name,
                                                            bool preload)
{
    config.is_elf = true;
    config.image_name = image_name;
    config.do_elf_load = preload;
    return config;
}

static inline sel4utils_process_config_t process_config_noelf(sel4utils_process_config_t config, void *entry_point,
                                                              uintptr_t sysinfo)
{
    config.is_elf = false;
    config.entry_point = entry_point;
    config.sysinfo = sysinfo;
    return config;
}

static inline sel4utils_process_config_t process_config_cnode(sel4utils_process_config_t config, vka_object_t cnode)
{
    config.create_cspace = false;
    config.cnode = cnode;
    return config;
}

static inline sel4utils_process_config_t process_config_create_cnode(sel4utils_process_config_t config, int size_bits)
{
    config.create_cspace = true;
    config.one_level_cspace_size_bits = size_bits;
    return config;
}

static inline sel4utils_process_config_t process_config_vspace(sel4utils_process_config_t config, vspace_t *vspace,
                                                               vka_object_t page_dir)
{
    config.create_vspace = false;
    config.vspace = vspace;
    config.page_dir = page_dir;
    return config;
}

static inline sel4utils_process_config_t process_config_create_vspace(sel4utils_process_config_t config,
                                                                      sel4utils_elf_region_t *reservations,
                                                                      int num_reservations)
{
    config.create_vspace = true;
    config.reservations = reservations;
    config.num_reservations = num_reservations;
    return config;
}

static inline sel4utils_process_config_t process_config_priority(sel4utils_process_config_t config, uint8_t priority)
{
    config.sched_params.priority = priority;
    return config;
}

static inline sel4utils_process_config_t process_config_mcp(sel4utils_process_config_t config, uint8_t mcp)
{
    config.sched_params.mcp = mcp;
    return config;
}

static inline sel4utils_process_config_t process_config_create_fault_endpoint(sel4utils_process_config_t config)
{
    config.create_fault_endpoint = true;
    return config;
}

static inline sel4utils_process_config_t process_config_fault_endpoint(sel4utils_process_config_t config,
                                                                       vka_object_t fault_endpoint)
{
    config.fault_endpoint = fault_endpoint;
    config.create_fault_endpoint = false;
    return config;
}

static inline sel4utils_process_config_t process_config_fault_cptr(sel4utils_process_config_t config,
                                                                   seL4_CPtr fault_cptr)
{
    config.fault_endpoint.cptr = fault_cptr;
    config.create_fault_endpoint = false;
    return config;
}

static inline sel4utils_process_config_t process_config_default(const char *image_name, seL4_CPtr asid_pool)
{
    sel4utils_process_config_t config = {0};
    config = process_config_asid_pool(config, asid_pool);
    config = process_config_elf(config, image_name, true);
    config = process_config_create_cnode(config, CONFIG_SEL4UTILS_CSPACE_SIZE_BITS);
    config = process_config_create_vspace(config, NULL, 0);
    return process_config_create_fault_endpoint(config);
}

static inline sel4utils_process_config_t process_config_default_simple(simple_t *simple, const char *image_name,
                                                                       uint8_t prio)
{
    sel4utils_process_config_t config = process_config_new(simple);
    config = process_config_elf(config, image_name, true);
    config = process_config_create_cnode(config, CONFIG_SEL4UTILS_CSPACE_SIZE_BITS);
    config = process_config_create_vspace(config, NULL, 0);
    config = process_config_create_fault_endpoint(config);

    if (config_set(CONFIG_KERNEL_RT)) {
        uint64_t timeslice = CONFIG_BOOT_THREAD_TIME_SLICE;
        config.sched_params = sched_params_round_robin(config.sched_params, simple, 0, timeslice * US_IN_MS);
    }

    return process_config_priority(config, prio);
}
