/*
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/zephyr.h>
#include <zephyr/syscall_handler.h>
#include <ztest.h>
#include <kernel_internal.h>

#define SEM_ARRAY_SIZE	16

/* Show that extern declarations don't interfere with detecting kernel
 * objects, this was at one point a problem.
 */
extern struct k_sem sem1;

static struct k_sem semarray[SEM_ARRAY_SIZE];
static struct k_sem *dyn_sem[SEM_ARRAY_SIZE];

static struct k_mutex *test_dyn_mutex;

K_SEM_DEFINE(sem1, 0, 1);
static struct k_sem sem2;
static char bad_sem[sizeof(struct k_sem)];
static struct k_sem sem3;

static int test_object(struct k_sem *sem, int retval)
{
	int ret;

	if (retval) {
		/* Expected to fail; bypass z_obj_validation_check() so we don't
		 * fill the logs with spam
		 */
		ret = z_object_validate(z_object_find(sem), K_OBJ_SEM, 0);
	} else {
		ret = z_obj_validation_check(z_object_find(sem), sem,
					    K_OBJ_SEM, 0);
	}

	if (ret != retval) {
		TC_PRINT("FAIL check of %p is not %d, got %d instead\n", sem,
			 retval, ret);
		return 1;
	}
	return 0;
}

void object_permission_checks(struct k_sem *sem, bool skip_init)
{
	/* Should fail because we don't have perms on this object */
	zassert_false(test_object(sem, -EPERM),
		      "object should not have had permission granted");

	k_object_access_grant(sem, k_current_get());

	if (!skip_init) {
		/* Should fail, not initialized and we have no permissions */
		zassert_false(test_object(sem, -EINVAL),
			      "object should not have been initialized");
		k_sem_init(sem, 0, 1);
	}

	/* This should succeed now */
	zassert_false(test_object(sem, 0),
		      "object should have had sufficient permissions");
}

/**
 * @brief Test to verify object permission
 *
 * @details
 * - The kernel must be able to associate kernel object memory addresses
 *   with whether the calling thread has access to that object, the object is
 *   of the expected type, and the object is of the expected init state.
 * - Test support freeing kernel objects allocated at runtime manually.
 *
 * @ingroup kernel_memprotect_tests
 *
 * @see k_object_alloc(), k_object_access_grant()
 */
void test_generic_object(void)
{
	struct k_sem stack_sem;

	/* None of these should be even in the table */
	zassert_false(test_object(&stack_sem, -EBADF), NULL);
	zassert_false(test_object((struct k_sem *)&bad_sem, -EBADF), NULL);
	zassert_false(test_object((struct k_sem *)0xFFFFFFFF, -EBADF), NULL);
	object_permission_checks(&sem3, false);
	object_permission_checks(&sem1, true);
	object_permission_checks(&sem2, false);

	for (int i = 0; i < SEM_ARRAY_SIZE; i++) {
		object_permission_checks(&semarray[i], false);
		dyn_sem[i] = k_object_alloc(K_OBJ_SEM);
		zassert_not_null(dyn_sem[i], "couldn't allocate semaphore");
		/* Give an extra reference to another thread so the object
		 * doesn't disappear if we revoke our own
		 */
		k_object_access_grant(dyn_sem[i], &z_main_thread);
	}

	/* dynamic object table well-populated with semaphores at this point */
	for (int i = 0; i < SEM_ARRAY_SIZE; i++) {
		/* Should have permission granted but be uninitialized */
		zassert_false(test_object(dyn_sem[i], -EINVAL), NULL);
		k_object_access_revoke(dyn_sem[i], k_current_get());
		object_permission_checks(dyn_sem[i], false);
		k_object_free(dyn_sem[i]);
		zassert_false(test_object(dyn_sem[i], -EBADF), NULL);
	}
}

/**
 * @brief Test requestor thread will implicitly be assigned permission on the
 * dynamically allocated object
 *
 * @details
 * - Create kernel object semaphore, dynamically allocate it from the calling
 *   thread's resource pool.
 * - Check that object's address is in bounds of that memory pool.
 * - Then check the requestor thread will implicitly be assigned permission on
 *   the allocated object by using semaphore API k_sem_init()
 *
 * @ingroup kernel_memprotect_tests
 *
 * @see k_object_alloc()
 */
void test_kobj_assign_perms_on_alloc_obj(void)
{
	static struct k_sem *test_dyn_sem;
	struct k_thread *thread = _current;

	uintptr_t start_addr, end_addr;
	size_t size_heap = CONFIG_HEAP_MEM_POOL_SIZE;

	/* dynamically allocate kernel object semaphore */
	test_dyn_sem = k_object_alloc(K_OBJ_SEM);
	zassert_not_null(test_dyn_sem, "Cannot allocate sem k_object");

	start_addr = *((uintptr_t *)(void *)thread->resource_pool);
	end_addr = start_addr + size_heap;

	/* check semaphore initialized within thread's mem pool address space */
	zassert_true(((uintptr_t)test_dyn_sem > start_addr) &&
				 ((uintptr_t)test_dyn_sem < end_addr),
				 "semaphore object not in bound of thread's memory pool");

	/* try to init that object, thread should have permissions implicitly */
	k_sem_init(test_dyn_sem, 1, 1);
}

/**
 * @brief Test dynamically allocated kernel object release memory
 *
 * @details Dynamically allocated kernel objects whose access is controlled by
 * the permission system will use object permission as a reference count.
 * If no threads have access to an object, the object's memory released.
 *
 * @ingroup kernel_memprotect_tests
 *
 * @see k_object_alloc()
 */
void test_no_ref_dyn_kobj_release_mem(void)
{
	int ret;

	/* dynamically allocate kernel object mutex */
	test_dyn_mutex = k_object_alloc(K_OBJ_MUTEX);
	zassert_not_null(test_dyn_mutex,
					 "Can not allocate dynamic kernel object");

	struct k_thread *thread = _current;

	/* revoke access from the current thread */
	k_object_access_revoke(test_dyn_mutex, thread);

	/* check object was released, when no threads have access to it */
	ret = z_object_validate(z_object_find(test_dyn_mutex), K_OBJ_MUTEX, 0);
	zassert_true(ret == -EBADF, "Dynamic kernel object not released");
}

void test_main(void)
{
	k_thread_system_pool_assign(k_current_get());

	ztest_test_suite(object_validation,
			 ztest_unit_test(test_generic_object),
			 ztest_unit_test(test_kobj_assign_perms_on_alloc_obj),
			 ztest_unit_test(test_no_ref_dyn_kobj_release_mem)
			 );
	ztest_run_test_suite(object_validation);
}
