From a567bd843767d5d18fcb7e4057c376539ce2d083 Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Sat, 8 Mar 2025 00:09:27 +0100 Subject: [PATCH] fix: Project restructuring --- kernel/src/Libraries/CMemory.cpp | 61 ++++++++++++ kernel/src/Libraries/Memory.hpp | 4 +- kernel/src/Platform/Itanium.cpp | 17 ++++ kernel/src/Platform/Limine.hpp | 69 ++++++++++++++ kernel/src/Platform/Util.cpp | 20 ++++ kernel/src/Platform/Util.hpp | 10 ++ kernel/src/main.cpp | 157 +------------------------------ 7 files changed, 183 insertions(+), 155 deletions(-) create mode 100644 kernel/src/Libraries/CMemory.cpp create mode 100644 kernel/src/Platform/Itanium.cpp create mode 100644 kernel/src/Platform/Limine.hpp create mode 100644 kernel/src/Platform/Util.cpp create mode 100644 kernel/src/Platform/Util.hpp diff --git a/kernel/src/Libraries/CMemory.cpp b/kernel/src/Libraries/CMemory.cpp new file mode 100644 index 0000000..af0da14 --- /dev/null +++ b/kernel/src/Libraries/CMemory.cpp @@ -0,0 +1,61 @@ +// GCC and Clang reserve the right to generate calls to the following +// 4 functions even if they are not directly called. +// Implement them as the C specification mandates. +// DO NOT remove or rename these functions, or stuff will eventually break! +// They CAN be moved to a different .cpp file. +#include + +extern "C" { + + void *memcpy(void *dest, const void *src, std::size_t n) { + std::uint8_t *pdest = static_cast(dest); + const std::uint8_t *psrc = static_cast(src); + + for (std::size_t i = 0; i < n; i++) { + pdest[i] = psrc[i]; + } + + return dest; + } + + void *memset(void *s, int c, std::size_t n) { + std::uint8_t *p = static_cast(s); + + for (std::size_t i = 0; i < n; i++) { + p[i] = static_cast(c); + } + + return s; + } + + void *memmove(void *dest, const void *src, std::size_t n) { + std::uint8_t *pdest = static_cast(dest); + const std::uint8_t *psrc = static_cast(src); + + if (src > dest) { + for (std::size_t i = 0; i < n; i++) { + pdest[i] = psrc[i]; + } + } else if (src < dest) { + for (std::size_t i = n; i > 0; i--) { + pdest[i-1] = psrc[i-1]; + } + } + + return dest; + } + + int memcmp(const void *s1, const void *s2, std::size_t n) { + const std::uint8_t *p1 = static_cast(s1); + const std::uint8_t *p2 = static_cast(s2); + + for (std::size_t i = 0; i < n; i++) { + if (p1[i] != p2[i]) { + return p1[i] < p2[i] ? -1 : 1; + } + } + + return 0; + } + + } \ No newline at end of file diff --git a/kernel/src/Libraries/Memory.hpp b/kernel/src/Libraries/Memory.hpp index bc4c346..4719f69 100644 --- a/kernel/src/Libraries/Memory.hpp +++ b/kernel/src/Libraries/Memory.hpp @@ -7,11 +7,11 @@ #pragma once #include -// Signatures, defined in main.cpp, probably will move sometime soon +// Signatures, defined in CMemory.cpp extern "C" { void *memcpy(void *dest, const void *src, std::size_t n); void *memset(void *s, int c, std::size_t n); void *memmove(void *dest, const void *src, std::size_t n); - int memcmp(const void *s1, const void *s2, std::size_t n); + int memcmp(const void *s1, const void *s2, std::size_t n); } \ No newline at end of file diff --git a/kernel/src/Platform/Itanium.cpp b/kernel/src/Platform/Itanium.cpp new file mode 100644 index 0000000..9cee3f3 --- /dev/null +++ b/kernel/src/Platform/Itanium.cpp @@ -0,0 +1,17 @@ +/* + * Itanium.cpp + * Definitions for the Itanium C++ ABI + * Copyright (c) Daniel Hammer, Limine Contributors (via Limine C++ example) +*/ + +#include + +// The following stubs are required by the Itanium C++ ABI (the one we use, +// regardless of the "Itanium" nomenclature). +// Like the memory functions above, these stubs can be moved to a different .cpp file, +// but should not be removed, unless you know what you are doing. +extern "C" { + int __cxa_atexit(void (*)(void *), void *, void *) { return 0; } + void __cxa_pure_virtual() { hcf(); } + void *__dso_handle; +} diff --git a/kernel/src/Platform/Limine.hpp b/kernel/src/Platform/Limine.hpp new file mode 100644 index 0000000..843ee18 --- /dev/null +++ b/kernel/src/Platform/Limine.hpp @@ -0,0 +1,69 @@ +/* + * Limine.hpp + * Limine platform definitions and support + * Copyright (c) Limine Contributors (via Limine C++ example) +*/ + +#include "../limine.h" + +// Set the base revision to 3, this is recommended as this is the latest +// base revision described by the Limine boot protocol specification. +// See specification for further info. + +namespace { + + __attribute__((used, section(".limine_requests"))) + volatile LIMINE_BASE_REVISION(3); + + } + + // The Limine requests can be placed anywhere, but it is important that + // the compiler does not optimise them away, so, usually, they should + // be made volatile or equivalent, _and_ they should be accessed at least + // once or marked as used with the "used" attribute as done here. + + namespace { + + __attribute__((used, section(".limine_requests"))) + volatile limine_framebuffer_request framebuffer_request = { + .id = LIMINE_FRAMEBUFFER_REQUEST, + .revision = 0, + .response = nullptr + }; + + __attribute__((used, section(".limine_requests"))) + volatile limine_efi_system_table_request system_table_request = { + .id = LIMINE_EFI_SYSTEM_TABLE_REQUEST, + .revision = 0, + .response = nullptr + }; + + __attribute__((used, section(".limine_requests"))) + volatile limine_hhdm_request hhdm_request = { + .id = LIMINE_HHDM_REQUEST, + .revision = 0, + .response = nullptr + }; + + __attribute__((used, section(".limine_requests"))) + volatile limine_memmap_request memmap_request = { + .id = LIMINE_MEMMAP_REQUEST, + .revision = 0, + .response = nullptr + }; + + } + + // Finally, define the start and end markers for the Limine requests. + // These can also be moved anywhere, to any .cpp file, as seen fit. + + namespace { + + __attribute__((used, section(".limine_requests_start"))) + volatile LIMINE_REQUESTS_START_MARKER; + + __attribute__((used, section(".limine_requests_end"))) + volatile LIMINE_REQUESTS_END_MARKER; + +} + \ No newline at end of file diff --git a/kernel/src/Platform/Util.cpp b/kernel/src/Platform/Util.cpp new file mode 100644 index 0000000..87b1650 --- /dev/null +++ b/kernel/src/Platform/Util.cpp @@ -0,0 +1,20 @@ +/* + * Util.cpp + * Platform utility routines + * Copyright (c) Daniel Hammer, Limine Contributors (via Limine C++ example) +*/ + +// Halt and catch fire function. +void hcf() +{ + for (;;) + { +#if defined(__x86_64__) + asm("hlt"); +#elif defined(__aarch64__) || defined(__riscv) + asm("wfi"); +#elif defined(__loongarch64) + asm("idle 0"); +#endif + } +} \ No newline at end of file diff --git a/kernel/src/Platform/Util.hpp b/kernel/src/Platform/Util.hpp new file mode 100644 index 0000000..5dfe812 --- /dev/null +++ b/kernel/src/Platform/Util.hpp @@ -0,0 +1,10 @@ +/* + * Util.hpp + * Declarations of platform utility routines + * Copyright (c) Daniel Hammer, Limine Contributors (via Limine C++ example) +*/ + +#pragma once + +// Halt and catch fire function. +void hcf(); \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 6634449..43495a4 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,7 +1,7 @@ /* * main.cpp * Kernel entry point - * Copyright (c) 2025 Daniel Hammer + * Copyright (c) 2025 Daniel Hammer, Limine Contributors (via Limine C++ example) */ #include @@ -19,6 +19,9 @@ #include #include +#include +#include + using namespace Kt; namespace Memory { @@ -29,162 +32,10 @@ namespace Memory { KernelOutStream kout; KernelErrorStream kerr; -// Set the base revision to 3, this is recommended as this is the latest -// base revision described by the Limine boot protocol specification. -// See specification for further info. - -namespace { - -__attribute__((used, section(".limine_requests"))) -volatile LIMINE_BASE_REVISION(3); - -} - -// The Limine requests can be placed anywhere, but it is important that -// the compiler does not optimise them away, so, usually, they should -// be made volatile or equivalent, _and_ they should be accessed at least -// once or marked as used with the "used" attribute as done here. - -namespace { - -__attribute__((used, section(".limine_requests"))) -volatile limine_framebuffer_request framebuffer_request = { - .id = LIMINE_FRAMEBUFFER_REQUEST, - .revision = 0, - .response = nullptr -}; - -__attribute__((used, section(".limine_requests"))) -volatile limine_efi_system_table_request system_table_request = { - .id = LIMINE_EFI_SYSTEM_TABLE_REQUEST, - .revision = 0, - .response = nullptr -}; - -__attribute__((used, section(".limine_requests"))) -volatile limine_hhdm_request hhdm_request = { - .id = LIMINE_HHDM_REQUEST, - .revision = 0, - .response = nullptr -}; - -__attribute__((used, section(".limine_requests"))) -volatile limine_memmap_request memmap_request = { - .id = LIMINE_MEMMAP_REQUEST, - .revision = 0, - .response = nullptr -}; - -} - -// Finally, define the start and end markers for the Limine requests. -// These can also be moved anywhere, to any .cpp file, as seen fit. - -namespace { - -__attribute__((used, section(".limine_requests_start"))) -volatile LIMINE_REQUESTS_START_MARKER; - -__attribute__((used, section(".limine_requests_end"))) -volatile LIMINE_REQUESTS_END_MARKER; - -} - -// GCC and Clang reserve the right to generate calls to the following -// 4 functions even if they are not directly called. -// Implement them as the C specification mandates. -// DO NOT remove or rename these functions, or stuff will eventually break! -// They CAN be moved to a different .cpp file. - -extern "C" { - -void *memcpy(void *dest, const void *src, std::size_t n) { - std::uint8_t *pdest = static_cast(dest); - const std::uint8_t *psrc = static_cast(src); - - for (std::size_t i = 0; i < n; i++) { - pdest[i] = psrc[i]; - } - - return dest; -} - -void *memset(void *s, int c, std::size_t n) { - std::uint8_t *p = static_cast(s); - - for (std::size_t i = 0; i < n; i++) { - p[i] = static_cast(c); - } - - return s; -} - -void *memmove(void *dest, const void *src, std::size_t n) { - std::uint8_t *pdest = static_cast(dest); - const std::uint8_t *psrc = static_cast(src); - - if (src > dest) { - for (std::size_t i = 0; i < n; i++) { - pdest[i] = psrc[i]; - } - } else if (src < dest) { - for (std::size_t i = n; i > 0; i--) { - pdest[i-1] = psrc[i-1]; - } - } - - return dest; -} - -int memcmp(const void *s1, const void *s2, std::size_t n) { - const std::uint8_t *p1 = static_cast(s1); - const std::uint8_t *p2 = static_cast(s2); - - for (std::size_t i = 0; i < n; i++) { - if (p1[i] != p2[i]) { - return p1[i] < p2[i] ? -1 : 1; - } - } - - return 0; -} - -} - -// Halt and catch fire function. -namespace { - -void hcf() { - for (;;) { -#if defined (__x86_64__) - asm ("hlt"); -#elif defined (__aarch64__) || defined (__riscv) - asm ("wfi"); -#elif defined (__loongarch64) - asm ("idle 0"); -#endif - } -} - -} - -// The following stubs are required by the Itanium C++ ABI (the one we use, -// regardless of the "Itanium" nomenclature). -// Like the memory functions above, these stubs can be moved to a different .cpp file, -// but should not be removed, unless you know what you are doing. -extern "C" { - int __cxa_atexit(void (*)(void *), void *, void *) { return 0; } - void __cxa_pure_virtual() { hcf(); } - void *__dso_handle; -} - // Extern declarations for global constructors array. extern void (*__init_array[])(); extern void (*__init_array_end[])(); -// The following will be our kernel's entry point. -// If renaming kmain() to something else, make sure to change the -// linker script accordingly. extern "C" void kmain() { // Ensure the bootloader actually understands our base revision (see spec). if (LIMINE_BASE_REVISION_SUPPORTED == false) {