/* Copyright (c) 2019-2024 Griefer@Work                                       *
 *                                                                            *
 * This software is provided 'as-is', without any express or implied          *
 * warranty. In no event will the authors be held liable for any damages      *
 * arising from the use of this software.                                     *
 *                                                                            *
 * Permission is granted to anyone to use this software for any purpose,      *
 * including commercial applications, and to alter it and redistribute it     *
 * freely, subject to the following restrictions:                             *
 *                                                                            *
 * 1. The origin of this software must not be misrepresented; you must not    *
 *    claim that you wrote the original software. If you use this software    *
 *    in a product, an acknowledgement (see the following) in the product     *
 *    documentation is required:                                              *
 *    Portions Copyright (c) 2019-2024 Griefer@Work                           *
 * 2. Altered source versions must be plainly marked as such, and must not be *
 *    misrepresented as being the original software.                          *
 * 3. This notice may not be removed or altered from any source distribution. *
 */


BEGIN
	DEFINE({ "__KERNEL__" : "1" })
	INCLUDE({
		"/kos/src/kernel/include",
		f"/kos/src/kernel/include/{XARCH}-kos",
	})
	//LD_FLAGS({ "--gc-sections" })
	GCC_FLAGS({
		"-fno-rtti",
		"-ffreestanding",
	})

	/* Arch-specific configurations. */
	if (TARGET_ARCH in ["i386", "x86_64"]) {
		CC_FLAGS({
			"-mno-sse",
			"-mno-sse2",
			"-mno-sse3",
			"-mno-sse4",
			"-mno-ssse3",
			"-mno-mmx",
			"-mno-3dnow",
			"-mno-avx",
			"-mtls-direct-seg-refs",
			"-mcld", /* Because user-space may modify this flag... */
		})
	}
	/* Without SEE (disabled above), 4/8-byte (2^<2/3>) stack alignment is all we really need. */
	if (TARGET_ARCH == "i386") {
		CC_FLAGS({
			"-mpreferred-stack-boundary=2",
		})
	} else if (TARGET_ARCH == "x86_64") {
		CC_FLAGS({
			"-mpreferred-stack-boundary=3",
			"-mno-red-zone",     /* Disable the red zone in kernel-space */
		})
	}

	BEGIN GROUP("kernelspace._verify") { COMPILE };
		SOURCE({
			f"../_verify/arch/{XARCH}/*.c",
			"../_verify/*.c",
		})
	END


	/* Kernel core. */
#include "core/.sources"

	/* Drivers */
	BEGIN
		SET_NOSTDLIB()
		STATIC_USELIBGCC()
		STATIC_USELIB("libssp")
		LIBPATH({ TARGET_BINPATH + "/os/drivers" })
		LD_FLAGS({
			"--nmagic",
			"--no-omagic",
			/* XXX: There shouldn't be a reason why we need to specify Bdynamic
			 *      here, since normally dynamic linking should be the default.
			 * Maybe there's something wrong with our toolchain that can make it
			 * think that  dynamic linking  isn't  supported in  certain  cases? */
			"-Bdynamic"
		})
		if (TARGET_ARCH == "x86_64") {
//			LD_FLAGS({ "-z", "noreloc-overflow" })
			GCC_FLAGS({ "-fno-plt" })
			GCC_FLAGS({ "-fPIC" })
		}
		GCC_FLAGS({
			"-shared",
//			"-fPIC", /* Not needed, and would produce slower code... */
		})

#define DEFINE_SIMPLE_DRIVER_EX(source_prefix, name, ...)  \
		BEGIN GROUP("mod." name) { COMPILE, LINK, MCOPY }; \
			SET_OUTPUT("/os/drivers/" name)                \
			LD_FLAGS({ "-soname=" name })                  \
			SOURCE({ source_prefix name "/" "*.c" })       \
			__VA_ARGS__                                    \
		END
#define DEFINE_SIMPLE_ARCH_DRIVER_EX(source_prefix, name)               \
		BEGIN GROUP("mod." name) { COMPILE };                           \
			SET_LANGUAGE("assembler-with-cpp")                          \
			SOURCE({ source_prefix name "/arch/" + XARCH_ASMFILES })    \
		END                                                             \
		BEGIN GROUP("mod." name) { COMPILE };                           \
			SOURCE({ source_prefix name "/" "*.c" })                    \
			SOURCE({ source_prefix name "/arch/" + XARCH + "/" "*.c" }) \
		END                                                             \
		BEGIN GROUP("mod." name) { LINK, MCOPY };                       \
			SET_OUTPUT("/os/drivers/" name)                             \
			LD_FLAGS({ "-soname=" name })                               \
			SOURCE({                                                    \
				source_prefix name "/" "*.c",                           \
				source_prefix name "/arch/" + XARCH + "/" "*.c",        \
				source_prefix name "/arch/" + XARCH_ASMFILES,           \
			})                                                          \
		END
#define DEFINE_SIMPLE_DRIVER(name, ...)         DEFINE_SIMPLE_DRIVER_EX("mod", name, __VA_ARGS__)
#define DEFINE_SIMPLE_DRIVER_LIBRARY(name, ...) DEFINE_SIMPLE_DRIVER_EX("../lib", name, __VA_ARGS__)
#define DEFINE_SIMPLE_ARCH_DRIVER(name)         DEFINE_SIMPLE_ARCH_DRIVER_EX("mod", name)
#define DEFINE_SIMPLE_ARCH_DRIVER_LIBRARY(name) DEFINE_SIMPLE_ARCH_DRIVER_EX("../lib", name)


#if 0 /* TODO: These drivers have yet to be ported to the new FS system. */
		DEFINE_SIMPLE_DRIVER("usb-hid", LIB(":usb")) /* Link against usb driver */
		DEFINE_SIMPLE_DRIVER("usb-storage", LIB(":usb")) /* Link against usb driver */
#endif

		DEFINE_SIMPLE_DRIVER("procfs")
		DEFINE_SIMPLE_DRIVER("ext2")
		DEFINE_SIMPLE_DRIVER("iso9660")
		DEFINE_SIMPLE_DRIVER("tar")
		if (TARGET_ARCH !in ["arm"]) { // TODO: ARM compat
			DEFINE_SIMPLE_DRIVER("usb")
			DEFINE_SIMPLE_DRIVER("ne2k")
			DEFINE_SIMPLE_DRIVER("ps2")
			DEFINE_SIMPLE_ARCH_DRIVER("gdbserver")
		}

		DEFINE_SIMPLE_DRIVER("dbx") /* DeBug eXtensions */

		DEFINE_SIMPLE_DRIVER("sctrace",
			SOURCE({ "../libsctrace/*.c" }) /* Include libsctrace source files */
		)

		/* X86-specific drivers */
		if (TARGET_ARCH in ["i386", "x86_64"]) {
			DEFINE_SIMPLE_DRIVER("svga",
				SOURCE({ "../libsvgadrv/*.c" }) /* Video driver library */
			)

			DEFINE_SIMPLE_ARCH_DRIVER("rtm")

			/* PE executable driver */
			DEFINE_SIMPLE_DRIVER("pe")
		}

#undef DEFINE_SIMPLE_ARCH_DRIVER
#undef DEFINE_SIMPLE_DRIVER
	END
END
