From 3451d50a37d6d97ac1abf09c1f15dd23411b818e Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 12 Nov 2022 18:13:41 +0100 Subject: [PATCH 001/407] Try building a tmpfs, but weird stuff happens --- initrd/make-folders.sh | 61 ++++++++++++ kernel/include/fs/TmpFS.h | 16 ++++ kernel/include/utils/Dynamic.h | 167 +++++++++++++++++++++++++++++++++ kernel/src/fs/TmpFS.cpp | 94 +++++++++++++++++++ kernel/src/main.cpp | 3 + 5 files changed, 341 insertions(+) create mode 100644 initrd/make-folders.sh create mode 100644 kernel/include/fs/TmpFS.h create mode 100644 kernel/include/utils/Dynamic.h create mode 100644 kernel/src/fs/TmpFS.cpp diff --git a/initrd/make-folders.sh b/initrd/make-folders.sh new file mode 100644 index 00000000..c149ffd8 --- /dev/null +++ b/initrd/make-folders.sh @@ -0,0 +1,61 @@ +mkdir /tmp/folder0 +sleep 1 +mkdir /tmp/folder1 +sleep 1 +mkdir /tmp/folder2 +sleep 1 +mkdir /tmp/folder3 +sleep 1 +mkdir /tmp/folder4 +sleep 1 +mkdir /tmp/folder5 +sleep 1 +mkdir /tmp/folder6 +sleep 1 +mkdir /tmp/folder7 +sleep 1 +mkdir /tmp/folder8 +sleep 1 +mkdir /tmp/folder9 +sleep 1 +mkdir /tmp/folder10 +sleep 1 +mkdir /tmp/folder11 +sleep 1 +mkdir /tmp/folder12 +sleep 1 +mkdir /tmp/folder13 +sleep 1 +mkdir /tmp/folder14 +sleep 1 +mkdir /tmp/folder15 +sleep 1 +mkdir /tmp/folder16 +sleep 1 +mkdir /tmp/folder17 +sleep 1 +mkdir /tmp/folder18 +sleep 1 +mkdir /tmp/folder19 +sleep 1 +mkdir /tmp/folder20 +sleep 1 +mkdir /tmp/folder21 +sleep 1 +mkdir /tmp/folder22 +sleep 1 +mkdir /tmp/folder23 +sleep 1 +mkdir /tmp/folder24 +sleep 1 +mkdir /tmp/folder25 +sleep 1 +mkdir /tmp/folder26 +sleep 1 +mkdir /tmp/folder27 +sleep 1 +mkdir /tmp/folder28 +sleep 1 +mkdir /tmp/folder29 +sleep 1 +mkdir /tmp/folder30 \ No newline at end of file diff --git a/kernel/include/fs/TmpFS.h b/kernel/include/fs/TmpFS.h new file mode 100644 index 00000000..159b406c --- /dev/null +++ b/kernel/include/fs/TmpFS.h @@ -0,0 +1,16 @@ +#pragma once + +#include "fs/VFS.h" + +namespace TmpFS +{ + VFS::Node* get(); + + VFS::Node* finddir(VFS::Node* node, const char* filename); + VFS::Node* readdir(VFS::Node* node, long offset); + + int mkdir(VFS::Node* node, const char* name, mode_t mode); + + ssize_t read(VFS::Node* node, size_t offset, size_t length, char* buffer); + ssize_t write(VFS::Node* node, size_t offset, size_t length, char* buffer); +} \ No newline at end of file diff --git a/kernel/include/utils/Dynamic.h b/kernel/include/utils/Dynamic.h new file mode 100644 index 00000000..6a2fd496 --- /dev/null +++ b/kernel/include/utils/Dynamic.h @@ -0,0 +1,167 @@ +#pragma once +#include "log/Log.h" +#include "std/ensure.h" +#include "std/stdlib.h" +#include "std/string.h" +#include "utils/new.h" + +#define __noinline __attribute__((noinline)) + +template struct Dynamic +{ + Dynamic() + { + set_expand_rate(16); + ensure(expand_fixed()); + } + + Dynamic(size_t capacity) + { + set_expand_rate(16); + ensure(expand_fixed()); + } + + Dynamic(const Dynamic& other) + { + set_expand_rate(other.m_expand_rate); + ensure_capacity(other.capacity()); + m_size = other.size(); + memcpy(m_buf, other.data(), m_capacity * sizeof(T)); + } + + Dynamic(Dynamic&& other) + { + set_expand_rate(other.m_expand_rate); + m_buf = other.release_data(); + m_capacity = other.capacity(); + m_size = other.size(); + } + + Dynamic& operator=(const Dynamic& other) + { + if (this == &other) return *this; + + if (m_buf) + { + while (m_size) pop(); // destroy all objects + kfree(m_buf); + } + + set_expand_rate(other.m_expand_rate); + ensure_capacity(other.capacity()); + m_size = other.size(); + memcpy(m_buf, other.data(), m_capacity * sizeof(T)); + + return *this; + } + + ~Dynamic() + { + if (m_buf) + { + while (m_size) pop(); // destroy all objects + kfree(m_buf); + } + } + + T& at(size_t index) + { + ensure(index < m_size); + return m_buf[index]; + } + + const T& at(size_t index) const + { + ensure(index < m_size); + return m_buf[index]; + } + + T& operator[](size_t index) + { + return at(index); + } + + const T& operator[](size_t index) const + { + return at(index); + } + + bool expand_capacity(size_t capacity) + { + return expand(capacity); + } + + void ensure_capacity(size_t capacity) + { + ensure(expand(capacity)); + } + + void set_expand_rate(size_t rate) + { + if (!rate) return; + m_expand_rate = rate; + } + + __noinline bool push(const T& item) + { + if (m_size == m_capacity) + if (!expand_fixed()) return false; + m_size++; + T* loc = ptr_at(m_size - 1); + new (loc) T(item); + return true; + } + + void pop() + { + at(m_size - 1).~T(); + m_size--; + } + + size_t capacity() const + { + return m_capacity; + } + + size_t size() const + { + return m_size; + } + + const T* data() const + { + return m_buf; + } + + T* release_data() + { + T* result = m_buf; + m_buf = nullptr; + return result; + } + + private: + T* m_buf = nullptr; + size_t m_capacity = 0; + size_t m_size = 0; + size_t m_expand_rate = 16; + + bool expand(size_t new_capacity) + { + m_buf = (T*)krealloc(m_buf, new_capacity * sizeof(T)); + if (!m_buf) return false; + m_capacity = new_capacity; + return true; + } + + bool expand_fixed() + { + ensure(m_expand_rate != 0); + return expand(m_capacity + m_expand_rate); + } + + T* ptr_at(size_t index) + { + return (T*)((char*)m_buf + index * sizeof(T)); + } +}; \ No newline at end of file diff --git a/kernel/src/fs/TmpFS.cpp b/kernel/src/fs/TmpFS.cpp new file mode 100644 index 00000000..a9c3a798 --- /dev/null +++ b/kernel/src/fs/TmpFS.cpp @@ -0,0 +1,94 @@ +#include "fs/TmpFS.h" +#include "std/errno.h" +#include "std/string.h" +#include "utils/Dynamic.h" +#include "utils/move.h" + +namespace TmpFS +{ + struct File + { + char* ptr; + uint64_t pages; + uint64_t length; + }; + + struct Directory + { + Dynamic files; + }; +} + +VFS::Node* tmpfs_root = nullptr; + +Dynamic tmpfs_dirs; +Dynamic tmpfs_files; + +extern uint64_t clock_now(); + +VFS::Node* TmpFS::get() +{ + if (tmpfs_root) return tmpfs_root; + tmpfs_root = new VFS::Node; + tmpfs_root->length = 0; + tmpfs_root->inode = 0; + tmpfs_root->type = VFS_DIRECTORY; + tmpfs_root->find_func = TmpFS::finddir; + tmpfs_root->readdir_func = TmpFS::readdir; + tmpfs_root->mkdir_func = TmpFS::mkdir; + tmpfs_root->mode = 0755; + tmpfs_root->uid = tmpfs_root->gid = 0; + tmpfs_root->atime = tmpfs_root->ctime = tmpfs_root->mtime = clock_now(); + strncpy(tmpfs_root->name, "tmpfs", sizeof(tmpfs_root->name)); + tmpfs_dirs.ensure_capacity(16); + tmpfs_files.ensure_capacity(16); + tmpfs_dirs.set_expand_rate(16); + tmpfs_files.set_expand_rate(16); + ensure(tmpfs_dirs.push({{}})); + return tmpfs_root; +} + +VFS::Node* TmpFS::finddir(VFS::Node* node, const char* filename) +{ + if (!node) return nullptr; + if (node->inode >= tmpfs_dirs.size()) return nullptr; + auto& dir = tmpfs_dirs[node->inode]; + for (size_t i = 0; i < dir.files.size(); i++) + { + if (!strncmp(dir.files[i]->name, filename, sizeof(dir.files[i]->name))) return dir.files[i]; + } + return nullptr; +} + +VFS::Node* TmpFS::readdir(VFS::Node* node, long offset) +{ + if (!node) return nullptr; + if (node->inode >= tmpfs_dirs.size()) return nullptr; + auto& dir = tmpfs_dirs[node->inode]; + if (offset < 0) return nullptr; + if ((size_t)offset >= dir.files.size()) return nullptr; + return dir.files[offset]; +} + +int TmpFS::mkdir(VFS::Node* node, const char* name, mode_t mode) +{ + if (node->inode >= tmpfs_dirs.size()) return -EINVAL; + if (!(node->type & VFS_DIRECTORY)) return -ENOTDIR; + auto& parent = tmpfs_dirs[node->inode]; + uint64_t inode = tmpfs_dirs.size(); + VFS::Node* new_node = new VFS::Node; + new_node->inode = inode; + new_node->find_func = TmpFS::finddir; + new_node->readdir_func = TmpFS::readdir; + new_node->mkdir_func = TmpFS::mkdir; + new_node->length = 0; + new_node->type = VFS_DIRECTORY; + new_node->mode = mode; + new_node->uid = new_node->gid = 0; + new_node->atime = new_node->ctime = new_node->mtime = clock_now(); + strncpy(new_node->name, name, sizeof(new_node->name)); + ensure(tmpfs_dirs.push({{}})); + node->length++; + ensure(parent.files.push(new_node)); + return 0; +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index ec781c93..f12e9e7c 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -2,6 +2,7 @@ #include "config.h" #include "cpu/CPU.h" +#include "fs/TmpFS.h" #include "fs/devices/DeviceFS.h" #include "gdt/GDT.h" #include "init/Init.h" @@ -58,7 +59,9 @@ extern "C" void _start() }); ensure(VFS::mkdir("/dev") == 0); + ensure(VFS::mkdir("/tmp") == 0); VFS::mount("/dev", DeviceFS::get()); + VFS::mount("/tmp", TmpFS::get()); Init::finish_kernel_boot(); From 046065c53334fa0aceb011680db5a3ab0f9ff2d9 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 12 Nov 2022 19:05:47 +0100 Subject: [PATCH 002/407] Fix tmpfs --- initrd/make-folders.sh | 62 ++++------------------------------------- kernel/src/fs/TmpFS.cpp | 13 +++++---- 2 files changed, 13 insertions(+), 62 deletions(-) diff --git a/initrd/make-folders.sh b/initrd/make-folders.sh index c149ffd8..f2fdd17f 100644 --- a/initrd/make-folders.sh +++ b/initrd/make-folders.sh @@ -1,61 +1,9 @@ -mkdir /tmp/folder0 +mkdir /tmp/1 sleep 1 -mkdir /tmp/folder1 +mkdir /tmp/1/2 sleep 1 -mkdir /tmp/folder2 +mkdir /tmp/1/2/3 sleep 1 -mkdir /tmp/folder3 +mkdir /tmp/1/2/3/4 sleep 1 -mkdir /tmp/folder4 -sleep 1 -mkdir /tmp/folder5 -sleep 1 -mkdir /tmp/folder6 -sleep 1 -mkdir /tmp/folder7 -sleep 1 -mkdir /tmp/folder8 -sleep 1 -mkdir /tmp/folder9 -sleep 1 -mkdir /tmp/folder10 -sleep 1 -mkdir /tmp/folder11 -sleep 1 -mkdir /tmp/folder12 -sleep 1 -mkdir /tmp/folder13 -sleep 1 -mkdir /tmp/folder14 -sleep 1 -mkdir /tmp/folder15 -sleep 1 -mkdir /tmp/folder16 -sleep 1 -mkdir /tmp/folder17 -sleep 1 -mkdir /tmp/folder18 -sleep 1 -mkdir /tmp/folder19 -sleep 1 -mkdir /tmp/folder20 -sleep 1 -mkdir /tmp/folder21 -sleep 1 -mkdir /tmp/folder22 -sleep 1 -mkdir /tmp/folder23 -sleep 1 -mkdir /tmp/folder24 -sleep 1 -mkdir /tmp/folder25 -sleep 1 -mkdir /tmp/folder26 -sleep 1 -mkdir /tmp/folder27 -sleep 1 -mkdir /tmp/folder28 -sleep 1 -mkdir /tmp/folder29 -sleep 1 -mkdir /tmp/folder30 \ No newline at end of file +mkdir /tmp/1/2/3/4/5 \ No newline at end of file diff --git a/kernel/src/fs/TmpFS.cpp b/kernel/src/fs/TmpFS.cpp index a9c3a798..9bc65fa2 100644 --- a/kernel/src/fs/TmpFS.cpp +++ b/kernel/src/fs/TmpFS.cpp @@ -36,7 +36,7 @@ VFS::Node* TmpFS::get() tmpfs_root->find_func = TmpFS::finddir; tmpfs_root->readdir_func = TmpFS::readdir; tmpfs_root->mkdir_func = TmpFS::mkdir; - tmpfs_root->mode = 0755; + tmpfs_root->mode = 0777; tmpfs_root->uid = tmpfs_root->gid = 0; tmpfs_root->atime = tmpfs_root->ctime = tmpfs_root->mtime = clock_now(); strncpy(tmpfs_root->name, "tmpfs", sizeof(tmpfs_root->name)); @@ -75,9 +75,8 @@ int TmpFS::mkdir(VFS::Node* node, const char* name, mode_t mode) if (node->inode >= tmpfs_dirs.size()) return -EINVAL; if (!(node->type & VFS_DIRECTORY)) return -ENOTDIR; auto& parent = tmpfs_dirs[node->inode]; - uint64_t inode = tmpfs_dirs.size(); VFS::Node* new_node = new VFS::Node; - new_node->inode = inode; + new_node->inode = tmpfs_dirs.size(); new_node->find_func = TmpFS::finddir; new_node->readdir_func = TmpFS::readdir; new_node->mkdir_func = TmpFS::mkdir; @@ -87,8 +86,12 @@ int TmpFS::mkdir(VFS::Node* node, const char* name, mode_t mode) new_node->uid = new_node->gid = 0; new_node->atime = new_node->ctime = new_node->mtime = clock_now(); strncpy(new_node->name, name, sizeof(new_node->name)); - ensure(tmpfs_dirs.push({{}})); + ensure(parent.files.push( + new_node)); // We have to push the new node to the parent BEFORE we push the directory object to the list of + // tmpfs directories. This is crucial, since pushing to the list of tmpfs directories could relocate + // said list, where the parent object is stored, while we would still be using the old parent + // object. Thus our changes to the parent would be erased as soon as we exit this function. + ensure(tmpfs_dirs.push({{}})); // FIXME: Handle OOM instead of panicking node->length++; - ensure(parent.files.push(new_node)); return 0; } \ No newline at end of file From 42efc211100308c7cccfcb0eb105118885860a29 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 12 Nov 2022 20:11:26 +0100 Subject: [PATCH 003/407] Start implementing read and write support in tmpfs write seems to work fine, read just hangs there, waiting. --- apps/Makefile | 2 +- apps/src/touch.c | 22 ++++++++ apps/src/write.c | 75 +++++++++++++++++++++++++++ kernel/include/fs/TmpFS.h | 4 +- kernel/include/fs/VFS.h | 6 +++ kernel/src/fs/TmpFS.cpp | 91 ++++++++++++++++++++++++++++++++- kernel/src/fs/VFS.cpp | 40 +++++++++++++++ kernel/src/std/stdio.cpp | 22 ++++++++ kernel/src/sys/exec.cpp | 2 + kernel/src/sys/stdio.cpp | 24 +++++++-- kernel/src/thread/Scheduler.cpp | 1 + 11 files changed, 281 insertions(+), 8 deletions(-) create mode 100644 apps/src/touch.c create mode 100644 apps/src/write.c diff --git a/apps/Makefile b/apps/Makefile index b82251ca..3ae58d7e 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,4 +1,4 @@ -C_APPS := init sh uname uptime hello ps ls args cat stat su session date mkdir screen +C_APPS := init sh uname uptime hello ps ls args cat stat su session date mkdir screen touch write CXX_APPS := hello-cpp APPS_DIR := $(LUNA_ROOT)/apps diff --git a/apps/src/touch.c b/apps/src/touch.c new file mode 100644 index 00000000..b2b0a218 --- /dev/null +++ b/apps/src/touch.c @@ -0,0 +1,22 @@ +#include +#include +#include + +int main(int argc, char** argv) +{ + if (argc == 1) + { + fprintf(stderr, "Usage: %s [directory]\n", argv[0]); + return 1; + } + + int fd = creat(argv[1], 0755); + + if (fd < 0) + { + perror("creat"); + return 1; + } + + close(fd); +} \ No newline at end of file diff --git a/apps/src/write.c b/apps/src/write.c new file mode 100644 index 00000000..1b541da9 --- /dev/null +++ b/apps/src/write.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include + +static char* echoing_fgets(char* buf, size_t size, FILE* stream) +{ + char* s = buf; + memset(buf, 0, size); + size_t oldsize = size; + while (size) + { + int c = fgetc(stream); + if (c == EOF) + { + if (ferror(stream)) return NULL; + if (feof(stream)) + { + if (s != buf) return s; + else + return NULL; + }; + } + if ((char)c == '\b') + { + if (size != oldsize) + { + buf--; + size++; + putchar('\b'); + } + } + else + { + size--; + *buf = (char)c; + buf++; + putchar((char)c); + if ((char)c == '\n') return s; + } + *buf = 0; + } + return s; +} + +int main(int argc, char** argv) +{ + if (argc == 1) + { + fprintf(stderr, "Usage: %s [directory]\n", argv[0]); + return 1; + } + + int fd = open(argv[1], O_WRONLY | O_CREAT | O_APPEND, 0755); + + if (fd < 0) + { + perror("open"); + return 1; + } + + FILE* fp = fdopen(fd, "a"); + + char buf[BUFSIZ]; + echoing_fgets(buf, BUFSIZ, stdin); + + fputs(buf, fp); + if (ferror(fp)) + { + perror("fputs"); + return 1; + } + + fclose(fp); +} \ No newline at end of file diff --git a/kernel/include/fs/TmpFS.h b/kernel/include/fs/TmpFS.h index 159b406c..cb79f37a 100644 --- a/kernel/include/fs/TmpFS.h +++ b/kernel/include/fs/TmpFS.h @@ -12,5 +12,7 @@ namespace TmpFS int mkdir(VFS::Node* node, const char* name, mode_t mode); ssize_t read(VFS::Node* node, size_t offset, size_t length, char* buffer); - ssize_t write(VFS::Node* node, size_t offset, size_t length, char* buffer); + ssize_t write(VFS::Node* node, size_t offset, size_t length, const char* buffer); + + VFS::Node* create(VFS::Node* node, const char* name, mode_t mode, uid_t uid, gid_t gid); } \ No newline at end of file diff --git a/kernel/include/fs/VFS.h b/kernel/include/fs/VFS.h index d8db1b15..410c9ec7 100644 --- a/kernel/include/fs/VFS.h +++ b/kernel/include/fs/VFS.h @@ -1,4 +1,5 @@ #pragma once +#include "utils/Result.h" #include #include #include @@ -25,6 +26,7 @@ namespace VFS typedef Node* (*node_readdir)(Node*, long); typedef uintptr_t (*node_mmap)(Node*, uintptr_t, size_t, int, off_t); typedef long (*node_ioctl)(Node*, int, uintptr_t); + typedef Node* (*node_create)(Node*, const char*, mode_t, uid_t, gid_t); struct Node { @@ -49,6 +51,7 @@ namespace VFS node_block block_func; node_mmap mmap_func; node_ioctl ioctl_func; + node_create create_func; Node* link; }; @@ -60,11 +63,14 @@ namespace VFS int do_mkdir(const char* path, const char* name, int uid, int gid, mode_t mode); int do_mkdir(const char* pathname, int uid, int gid, mode_t mode); + Result create(const char* pathname, mode_t mode, uid_t uid, gid_t gid); + int would_block(Node* node); void mount_root(Node* root); Node* resolve_path(const char* filename, Node* root = nullptr); + Node* resolve_parent(const char* filename, Node* root = nullptr); bool exists(const char* pathname); diff --git a/kernel/src/fs/TmpFS.cpp b/kernel/src/fs/TmpFS.cpp index 9bc65fa2..e4e5fccb 100644 --- a/kernel/src/fs/TmpFS.cpp +++ b/kernel/src/fs/TmpFS.cpp @@ -1,4 +1,9 @@ +#define MODULE "tmpfs" + #include "fs/TmpFS.h" +#include "log/Log.h" +#include "memory/MemoryManager.h" +#include "misc/utils.h" #include "std/errno.h" #include "std/string.h" #include "utils/Dynamic.h" @@ -8,7 +13,7 @@ namespace TmpFS { struct File { - char* ptr; + void* ptr; uint64_t pages; uint64_t length; }; @@ -26,9 +31,30 @@ Dynamic tmpfs_files; extern uint64_t clock_now(); +static bool resize_file(TmpFS::File& file, size_t new_size) +{ + size_t pages = Utilities::get_blocks_from_size(PAGE_SIZE, new_size); + if (pages > file.pages) // resize only if we need a bigger chunk of memory + { + auto rc = MemoryManager::get_pages(pages, MAP_READ_WRITE); + if (rc.has_error()) return false; + void* new_ptr = rc.release_value(); + if (file.ptr) + { + memcpy(new_ptr, file.ptr, file.length); + MemoryManager::release_pages(file.ptr, file.pages); + } + file.pages = pages; + file.ptr = new_ptr; + } + file.length = new_size; + return true; +} + VFS::Node* TmpFS::get() { if (tmpfs_root) return tmpfs_root; + kinfoln("initializing tmpfs instance"); tmpfs_root = new VFS::Node; tmpfs_root->length = 0; tmpfs_root->inode = 0; @@ -36,6 +62,7 @@ VFS::Node* TmpFS::get() tmpfs_root->find_func = TmpFS::finddir; tmpfs_root->readdir_func = TmpFS::readdir; tmpfs_root->mkdir_func = TmpFS::mkdir; + tmpfs_root->create_func = TmpFS::create; tmpfs_root->mode = 0777; tmpfs_root->uid = tmpfs_root->gid = 0; tmpfs_root->atime = tmpfs_root->ctime = tmpfs_root->mtime = clock_now(); @@ -53,6 +80,7 @@ VFS::Node* TmpFS::finddir(VFS::Node* node, const char* filename) if (!node) return nullptr; if (node->inode >= tmpfs_dirs.size()) return nullptr; auto& dir = tmpfs_dirs[node->inode]; + kdbgln("searching for '%s' in '%s'", filename, node->name); for (size_t i = 0; i < dir.files.size(); i++) { if (!strncmp(dir.files[i]->name, filename, sizeof(dir.files[i]->name))) return dir.files[i]; @@ -67,6 +95,7 @@ VFS::Node* TmpFS::readdir(VFS::Node* node, long offset) auto& dir = tmpfs_dirs[node->inode]; if (offset < 0) return nullptr; if ((size_t)offset >= dir.files.size()) return nullptr; + kdbgln("reading offset %ld in '%s'", offset, node->name); return dir.files[offset]; } @@ -80,6 +109,7 @@ int TmpFS::mkdir(VFS::Node* node, const char* name, mode_t mode) new_node->find_func = TmpFS::finddir; new_node->readdir_func = TmpFS::readdir; new_node->mkdir_func = TmpFS::mkdir; + new_node->create_func = TmpFS::create; new_node->length = 0; new_node->type = VFS_DIRECTORY; new_node->mode = mode; @@ -93,5 +123,64 @@ int TmpFS::mkdir(VFS::Node* node, const char* name, mode_t mode) // object. Thus our changes to the parent would be erased as soon as we exit this function. ensure(tmpfs_dirs.push({{}})); // FIXME: Handle OOM instead of panicking node->length++; + kdbgln("created directory '%s' in '%s' (which now has %lu entries), mode %o", name, node->name, node->length, mode); return 0; +} + +VFS::Node* TmpFS::create(VFS::Node* node, const char* name, mode_t mode, uid_t uid, gid_t gid) +{ + if (node->inode >= tmpfs_dirs.size()) return nullptr; + if (!(node->type & VFS_DIRECTORY)) return nullptr; + auto& parent = tmpfs_dirs[node->inode]; + VFS::Node* new_node = new VFS::Node; + new_node->inode = tmpfs_files.size(); + new_node->length = 0; + new_node->read_func = TmpFS::read; + new_node->write_func = TmpFS::write; + new_node->type = VFS_FILE; + new_node->mode = mode; + new_node->uid = uid; + new_node->gid = gid; + new_node->atime = new_node->ctime = new_node->mtime = clock_now(); + strncpy(new_node->name, name, sizeof(new_node->name)); + ensure(parent.files.push( + new_node)); // We have to push the new node to the parent BEFORE we push the directory object to the list of + // tmpfs directories. This is crucial, since pushing to the list of tmpfs directories could relocate + // said list, where the parent object is stored, while we would still be using the old parent + // object. Thus our changes to the parent would be erased as soon as we exit this function. + ensure(tmpfs_files.push({nullptr, 0, 0})); // FIXME: Handle OOM instead of panicking + node->length++; + kdbgln("created file '%s' in '%s' (which now has %lu entries), mode %o", name, node->name, node->length, mode); + return 0; +} + +ssize_t TmpFS::read(VFS::Node* node, size_t offset, size_t length, char* buffer) +{ + kdbgln("got to read()"); + if (!node) return -1; + if (node->inode >= tmpfs_files.size()) return -1; + File& file = tmpfs_files[node->inode]; + size_t old_len = length; + if (offset > file.length) return -1; + if (offset + length > file.length) { length = file.length - offset; } + kdbgln("reading %zu bytes from '%s' at offset %zu (requested length was %zu)", length, node->name, offset, old_len); + memcpy(buffer, (void*)((uintptr_t)file.ptr + offset), length); + return length; +} + +ssize_t TmpFS::write(VFS::Node* node, size_t offset, size_t length, const char* buffer) +{ + if (!node) return -1; + if (node->inode >= tmpfs_files.size()) return -1; + File& file = tmpfs_files[node->inode]; + size_t new_length = file.length; + if (offset + length > file.length) new_length = offset + length; + if (new_length != file.length) + { + if (!resize_file(file, new_length)) return -ENOMEM; + node->length = new_length; + } + kdbgln("writing %zu bytes to '%s' at offset %zu", length, node->name, offset); + memcpy((void*)((uintptr_t)file.ptr + offset), buffer, length); + return length; } \ No newline at end of file diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp index 9fe20d37..0d186efa 100644 --- a/kernel/src/fs/VFS.cpp +++ b/kernel/src/fs/VFS.cpp @@ -129,6 +129,14 @@ VFS::Node* VFS::resolve_path(const char* filename, Node* root) } } +VFS::Node* VFS::resolve_parent(const char* filename, Node* root) +{ + char* dir = better_dirname(filename); + auto* result = resolve_path(dir, root); + kfree(dir); + return result; +} + int VFS::mkdir(const char* path, const char* name) { Node* node = resolve_path(path, vfs_root); @@ -236,6 +244,38 @@ int VFS::do_mkdir(const char* pathname, int uid, int gid, mode_t mode) return result; } +Result VFS::create(const char* pathname, mode_t mode, uid_t uid, gid_t gid) +{ + VFS::Node* parent = VFS::resolve_parent(pathname); + if (!parent) return {ENOENT}; + if (parent->type != VFS_DIRECTORY) + { + kwarnln("Attempting to create %s, parent is not a directory", pathname); + return {ENOTDIR}; + } + if (!parent->create_func) + { + kwarnln("Chosen node does not support create()"); + return {ENOTSUP}; // FIXME: Probably EROFS. + } + if (!parent->find_func) + { + kwarnln("Chosen node does not support finddir()"); + return {ENOTSUP}; + } + if (!can_write(parent, uid, gid)) return {EACCES}; + char* child = better_basename(pathname); + if (parent->find_func(parent, child)) + { + kwarnln("Already exists"); + kfree(child); + return {EEXIST}; + } + VFS::Node* child_node = parent->create_func(parent, child, mode, uid, gid); + kfree(child); + return child_node; +} + bool VFS::exists(const char* pathname) { return resolve_path(pathname) != nullptr; diff --git a/kernel/src/std/stdio.cpp b/kernel/src/std/stdio.cpp index 18af8db5..d17a70cc 100644 --- a/kernel/src/std/stdio.cpp +++ b/kernel/src/std/stdio.cpp @@ -115,6 +115,28 @@ static int internal_printf(const char* format, PutString put_string_callback, ss } break; } + case 'o': { + if (is_unsigned_long || is_long) + { + char result[25]; + ultoa(va_arg(ap, uint64_t), result, 8); + if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); + memcpy(buffer + buffer_insert_index, result, strlen(result)); + buffer_insert_index += strlen(result); + if (buffer_insert_index == 1024) flush_buffer(); + is_unsigned_long = is_long = false; + } + else + { + char result[25]; + utoa(va_arg(ap, uint32_t), result, 8); + if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); + memcpy(buffer + buffer_insert_index, result, strlen(result)); + buffer_insert_index += strlen(result); + if (buffer_insert_index == 1024) flush_buffer(); + } + break; + } case 'u': { if (is_unsigned_long || is_long) { diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index 962d0c42..bcbd6572 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -50,6 +50,8 @@ void sys_fork(Context* context) child->gid = parent->gid; child->egid = parent->egid; + child->umask = parent->umask; + child->regs.rax = 0; context->rax = child->id; diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp index 453f0ff5..2058bd00 100644 --- a/kernel/src/sys/stdio.cpp +++ b/kernel/src/sys/stdio.cpp @@ -160,7 +160,7 @@ void sys_write(Context* context, int fd, size_t size, const char* addr) return; } -void sys_open(Context* context, const char* filename, int flags, mode_t) // FIXME: mode is not used. +void sys_open(Context* context, const char* filename, int flags, mode_t mode) { Task* current_task = Scheduler::current_task(); int fd = current_task->alloc_fd(); @@ -182,9 +182,21 @@ void sys_open(Context* context, const char* filename, int flags, mode_t) // FIXM if (!node) { bool create = (flags & OPEN_CREATE) > 0; - if (create) kwarnln("FIXME: open(O_CREAT) is not implemented"); + if (create) + { + mode = mode & (~current_task->umask); + auto rc = VFS::create(kfilename, mode, current_task->euid, current_task->egid); + if (rc.has_error()) context->rax = -rc.error(); + else + { + kinfoln("Created file %s with mode %o, uid %d and gid %d", kfilename, mode, current_task->euid, + current_task->egid); + node = rc.release_value(); + goto do_open; + } + } + else { context->rax = -ENOENT; } kfree(kfilename); - context->rax = -ENOENT; return; } else @@ -199,6 +211,8 @@ void sys_open(Context* context, const char* filename, int flags, mode_t) // FIXM } } +do_open: + bool can_read = (flags & OPEN_READ) > 0; bool can_write = (flags & OPEN_WRITE) > 0; if (!can_read && !can_write) @@ -210,7 +224,7 @@ void sys_open(Context* context, const char* filename, int flags, mode_t) // FIXM if (can_read && !VFS::can_read(node, current_task->euid, current_task->egid)) { - kwarnln("open failed because process with uid %d and gid %d couldn't open file %s with mode %d for reading", + kwarnln("open failed because process with uid %d and gid %d couldn't open file %s with mode %o for reading", current_task->euid, current_task->egid, kfilename, node->mode); kfree(kfilename); context->rax = -EACCES; @@ -219,7 +233,7 @@ void sys_open(Context* context, const char* filename, int flags, mode_t) // FIXM if (can_write && !VFS::can_write(node, current_task->euid, current_task->egid)) { - kwarnln("open failed because process with uid %d and gid %d couldn't open file %s with mode %d for writing", + kwarnln("open failed because process with uid %d and gid %d couldn't open file %s with mode %o for writing", current_task->euid, current_task->egid, kfilename, node->mode); kfree(kfilename); context->rax = -EACCES; diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index ed73d08d..9ff79db3 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -198,6 +198,7 @@ long Scheduler::load_user_task(const char* filename) new_task->user_task = true; new_task->regs.rip = image->entry; new_task->image = image; + new_task->umask = 0; new_task->allocated_stack = (uint64_t)MemoryManager::get_pages_at(0x100000, TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER | MAP_AS_OWNED_BY_TASK) .release_value(); // FIXME: Propagate errors. From cf758fdfdce7856755ddcdd795ecffa5d1719071 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 10:09:09 +0100 Subject: [PATCH 004/407] Initial commit :) --- .gitignore | 14 +- CMakeLists.txt | 18 + apps/Makefile | 33 - apps/src/args.c | 7 - apps/src/cat.c | 45 -- apps/src/date.c | 9 - apps/src/hello-cpp.cpp | 19 - apps/src/hello.c | 6 - apps/src/init.c | 77 --- apps/src/ls.c | 31 - apps/src/mkdir.c | 17 - apps/src/ps.c | 48 -- apps/src/screen.c | 32 - apps/src/session.c | 145 ----- apps/src/sh.c | 364 ----------- apps/src/stat.c | 66 -- apps/src/su.c | 88 --- apps/src/touch.c | 22 - apps/src/uname.c | 18 - apps/src/uptime.c | 38 -- apps/src/write.c | 75 --- initrd/etc/motd | 3 - initrd/etc/passwd | 2 - initrd/make-folders.sh | 9 - initrd/sys/config | 3 +- kernel/CMakeLists.txt | 26 + kernel/Makefile | 85 --- kernel/include/acpi/FADT.h | 93 --- kernel/include/acpi/RSDT.h | 25 - kernel/include/acpi/SDT.h | 20 - kernel/include/bootboot.h | 162 ----- kernel/include/config.h | 7 - kernel/include/cpu/CPU.h | 14 - kernel/include/cpu/Features.h | 72 --- kernel/include/font.h | 260 -------- kernel/include/fs/FileDescriptor.h | 83 --- kernel/include/fs/InitRD.h | 54 -- kernel/include/fs/TmpFS.h | 18 - kernel/include/fs/VFS.h | 92 --- kernel/include/fs/devices/Console.h | 15 - kernel/include/fs/devices/DeviceFS.h | 10 - kernel/include/fs/devices/Framebuffer.h | 13 - kernel/include/fs/devices/Keyboard.h | 13 - kernel/include/fs/devices/NullDevice.h | 10 - kernel/include/fs/devices/Random.h | 9 - kernel/include/fs/devices/Serial.h | 9 - kernel/include/fs/devices/Version.h | 9 - kernel/include/gdt/GDT.h | 6 - kernel/include/init/Init.h | 9 - kernel/include/interrupts/Context.h | 14 - kernel/include/interrupts/IDT.h | 18 - kernel/include/interrupts/IRQ.h | 7 - kernel/include/interrupts/Install.h | 7 - kernel/include/interrupts/Interrupts.h | 17 - kernel/include/io/IO.h | 13 - kernel/include/io/PCI.h | 98 --- kernel/include/io/PIC.h | 12 - kernel/include/io/Serial.h | 13 - kernel/include/log/CLog.h | 41 -- kernel/include/log/Log.h | 41 -- kernel/include/memory/AddressSpace.h | 22 - kernel/include/memory/KernelHeap.h | 15 - kernel/include/memory/Memory.h | 11 - kernel/include/memory/MemoryManager.h | 41 -- kernel/include/memory/MemoryMap.h | 6 - kernel/include/memory/PMM.h | 25 - kernel/include/memory/Paging.h | 34 - kernel/include/memory/UserHeap.h | 27 - kernel/include/memory/VMM.h | 48 -- kernel/include/memory/liballoc/liballoc.h | 75 --- kernel/include/misc/MSR.h | 21 - kernel/include/misc/PCITypes.h | 4 - kernel/include/misc/Scancodes.h | 6 - kernel/include/misc/hang.h | 4 - kernel/include/misc/reboot.h | 3 - kernel/include/misc/shutdown.h | 3 - kernel/include/misc/utils.h | 10 - kernel/include/panic/Panic.h | 15 - kernel/include/rand/Init.h | 7 - kernel/include/rand/Mersenne.h | 8 - kernel/include/render/Color.h | 22 - kernel/include/render/Framebuffer.h | 30 - kernel/include/render/TextRenderer.h | 10 - kernel/include/std/ensure.h | 9 - kernel/include/std/errno.h | 24 - kernel/include/std/libgen.h | 7 - kernel/include/std/stdio.h | 14 - kernel/include/std/stdlib.h | 14 - kernel/include/std/string.h | 23 - kernel/include/sys/Syscall.h | 76 --- kernel/include/sys/UserMemory.h | 30 - kernel/include/sys/elf/ELF.h | 48 -- kernel/include/sys/elf/ELFLoader.h | 13 - kernel/include/sys/elf/Image.h | 15 - kernel/include/thread/PIT.h | 11 - kernel/include/thread/Scheduler.h | 34 - kernel/include/thread/Spinlock.h | 15 - kernel/include/thread/Task.h | 123 ---- kernel/include/trace/Resolve.h | 5 - kernel/include/trace/StackTracer.h | 15 - kernel/include/utils/Addresses.h | 24 - kernel/include/utils/Dynamic.h | 167 ----- kernel/include/utils/PageFaultReason.h | 4 - kernel/include/utils/Registers.h | 52 -- kernel/include/utils/Result.h | 153 ----- kernel/include/utils/StringParsing.h | 4 - kernel/include/utils/Time.h | 8 - kernel/include/utils/move.h | 6 - kernel/include/utils/new.h | 13 - kernel/moon.ld | 5 +- kernel/src/acpi/RSDT.cpp | 109 ---- kernel/src/acpi/SDT.cpp | 15 - kernel/src/cpu/CPU.cpp | 99 --- kernel/src/fs/FileDescriptor.cpp | 96 --- kernel/src/fs/InitRD.cpp | 424 ------------ kernel/src/fs/TmpFS.cpp | 186 ------ kernel/src/fs/VFS.cpp | 340 ---------- kernel/src/fs/devices/Console.cpp | 61 -- kernel/src/fs/devices/DeviceFS.cpp | 61 -- kernel/src/fs/devices/Framebuffer.cpp | 71 -- kernel/src/fs/devices/Keyboard.cpp | 56 -- kernel/src/fs/devices/NullDevice.cpp | 34 - kernel/src/fs/devices/Random.cpp | 43 -- kernel/src/fs/devices/Serial.cpp | 30 - kernel/src/fs/devices/Version.cpp | 30 - kernel/src/gdt/GDT.asm | 21 - kernel/src/gdt/GDT.cpp | 114 ---- kernel/src/init/Init.cpp | 116 ---- kernel/src/interrupts/Entry.cpp | 69 -- kernel/src/interrupts/IDT.cpp | 55 -- kernel/src/interrupts/IRQ.cpp | 37 -- kernel/src/interrupts/Install.cpp | 112 ---- kernel/src/interrupts/InterruptEntry.asm | 136 ---- kernel/src/interrupts/Interrupts.cpp | 59 -- kernel/src/io/IO.cpp | 42 -- kernel/src/io/PCI.cpp | 197 ------ kernel/src/io/PIC.cpp | 82 --- kernel/src/io/Serial.cpp | 49 -- kernel/src/log/CLog.cpp | 56 -- kernel/src/log/Log.cpp | 94 --- kernel/src/main.asm | 40 -- kernel/src/main.cpp | 79 +-- kernel/src/memory/AddressSpace.cpp | 284 -------- kernel/src/memory/KernelHeap.cpp | 135 ---- kernel/src/memory/Memory.cpp | 54 -- kernel/src/memory/MemoryManager.cpp | 223 ------- kernel/src/memory/MemoryMap.cpp | 37 -- kernel/src/memory/PMM.cpp | 191 ------ kernel/src/memory/Paging.cpp | 16 - kernel/src/memory/UserHeap.cpp | 164 ----- kernel/src/memory/VMM.cpp | 362 ----------- kernel/src/memory/liballoc/bindings.cpp | 30 - kernel/src/memory/liballoc/liballoc.c | 721 --------------------- kernel/src/misc/MSR.cpp | 43 -- kernel/src/misc/PCITypes.cpp | 85 --- kernel/src/misc/Scancodes.cpp | 168 ----- kernel/src/misc/config.cpp | 38 -- kernel/src/misc/cxxabi.cpp | 52 -- kernel/src/misc/hang.cpp | 14 - kernel/src/misc/new.cpp | 32 - kernel/src/misc/reboot.cpp | 102 --- kernel/src/misc/shutdown.cpp | 20 - kernel/src/misc/stack.cpp | 14 - kernel/src/misc/ubsan.cpp | 205 ------ kernel/src/panic/Panic.cpp | 176 ----- kernel/src/rand/Init.asm | 11 - kernel/src/rand/Init.cpp | 74 --- kernel/src/rand/Mersenne.cpp | 62 -- kernel/src/render/Color.cpp | 21 - kernel/src/render/Framebuffer.cpp | 59 -- kernel/src/render/TextRenderer.cpp | 116 ---- kernel/src/std/libgen.cpp | 67 -- kernel/src/std/stdio.cpp | 311 --------- kernel/src/std/stdlib.cpp | 153 ----- kernel/src/std/string.cpp | 157 ----- kernel/src/sys/Syscall.cpp | 51 -- kernel/src/sys/UserMemory.cpp | 224 ------- kernel/src/sys/clock.cpp | 76 --- kernel/src/sys/dirent.cpp | 60 -- kernel/src/sys/elf/ELFLoader.cpp | 225 ------- kernel/src/sys/exec.cpp | 262 -------- kernel/src/sys/id.cpp | 123 ---- kernel/src/sys/mem.cpp | 226 ------- kernel/src/sys/sched.cpp | 24 - kernel/src/sys/stat.cpp | 78 --- kernel/src/sys/stdio.cpp | 411 ------------ kernel/src/thread/PIT.cpp | 30 - kernel/src/thread/Scheduler.cpp | 634 ------------------ kernel/src/thread/Spinlock.asm | 20 - kernel/src/thread/Spinlock.cpp | 27 - kernel/src/thread/Task.cpp | 140 ---- kernel/src/trace/Resolve.cpp | 41 -- kernel/src/trace/StackTracer.cpp | 55 -- kernel/src/utils/PageFaultReason.cpp | 20 - kernel/src/utils/StringParsing.cpp | 49 -- kernel/src/utils/Time.cpp | 42 -- libs/Makefile | 8 - libs/libc/Makefile | 87 --- libs/libc/crt0.asm | 35 - libs/libc/crti.asm | 11 - libs/libc/crtn.asm | 7 - libs/libc/include/alloca.h | 6 - libs/libc/include/assert.h | 24 - libs/libc/include/bits/error.h | 28 - libs/libc/include/bits/getprocid.h | 11 - libs/libc/include/bits/liballoc.h | 74 --- libs/libc/include/bits/macros.h | 12 - libs/libc/include/bits/seek.h | 8 - libs/libc/include/ctype.h | 64 -- libs/libc/include/dirent.h | 66 -- libs/libc/include/errno.h | 84 --- libs/libc/include/fcntl.h | 58 -- libs/libc/include/inttypes.h | 71 -- libs/libc/include/libgen.h | 21 - libs/libc/include/locale.h | 49 -- libs/libc/include/luna.h | 28 - libs/libc/include/luna/dirent.h | 27 - libs/libc/include/luna/os-limits.h | 13 - libs/libc/include/luna/pstat.h | 38 -- libs/libc/include/luna/syscall.h | 70 -- libs/libc/include/luna/vfs.h | 10 - libs/libc/include/math.h | 90 --- libs/libc/include/memory.h | 0 libs/libc/include/pwd.h | 42 -- libs/libc/include/sched.h | 16 - libs/libc/include/setjmp.h | 32 - libs/libc/include/signal.h | 21 - libs/libc/include/stdio.h | 176 ----- libs/libc/include/stdlib.h | 140 ---- libs/libc/include/string.h | 105 --- libs/libc/include/strings.h | 27 - libs/libc/include/sys/ioctl.h | 25 - libs/libc/include/sys/mman.h | 41 -- libs/libc/include/sys/param.h | 0 libs/libc/include/sys/stat.h | 82 --- libs/libc/include/sys/syscall.h | 35 - libs/libc/include/sys/time.h | 26 - libs/libc/include/sys/types.h | 40 -- libs/libc/include/sys/wait.h | 30 - libs/libc/include/time.h | 87 --- libs/libc/include/unistd.h | 121 ---- libs/libc/include/utime.h | 23 - libs/libc/include/wchar.h | 24 - libs/libc/src/assert.cpp | 12 - libs/libc/src/atexit.cpp | 25 - libs/libc/src/bits/bindings.c | 24 - libs/libc/src/bits/liballoc.c | 748 ---------------------- libs/libc/src/ctype.cpp | 86 --- libs/libc/src/cxxabi.cpp | 50 -- libs/libc/src/dirent.cpp | 73 --- libs/libc/src/errno.cpp | 4 - libs/libc/src/fcntl.cpp | 33 - libs/libc/src/file.cpp | 305 --------- libs/libc/src/init.cpp | 69 -- libs/libc/src/libgen.cpp | 50 -- libs/libc/src/locale.cpp | 25 - libs/libc/src/luna.cpp | 25 - libs/libc/src/luna/dirent.cpp | 11 - libs/libc/src/luna/pstat.cpp | 24 - libs/libc/src/luna/syscall.asm | 50 -- libs/libc/src/math.cpp | 106 --- libs/libc/src/printf.cpp | 331 ---------- libs/libc/src/pwd.cpp | 196 ------ libs/libc/src/rand.cpp | 64 -- libs/libc/src/sched.cpp | 11 - libs/libc/src/setjmp.asm | 36 -- libs/libc/src/setjmp.cpp | 15 - libs/libc/src/signal.cpp | 15 - libs/libc/src/stdio.cpp | 82 --- libs/libc/src/stdlib.cpp | 311 --------- libs/libc/src/strftime.cpp | 318 --------- libs/libc/src/string.cpp | 311 --------- libs/libc/src/strings.cpp | 43 -- libs/libc/src/sys/ioctl.cpp | 17 - libs/libc/src/sys/mman.cpp | 24 - libs/libc/src/sys/stat.cpp | 37 -- libs/libc/src/sys/wait.cpp | 16 - libs/libc/src/syscall.cpp | 69 -- libs/libc/src/time.cpp | 183 ------ libs/libc/src/unistd.cpp | 180 ------ libs/libc/src/utime.cpp | 10 - libs/libc/src/wchar.cpp | 24 - luna/Types.h | 10 + ports/add-port.sh | 140 ---- ports/bc/bc.patch | 60 -- ports/bc/package.sh | 40 -- ports/binutils/binutils.patch | 144 ----- ports/binutils/package.sh | 48 -- ports/gmp/gmp.patch | 11 - ports/gmp/package.sh | 44 -- ports/list-ports.sh | 56 -- ports/make-package.sh | 24 - ports/mpc/package.sh | 41 -- ports/mpfr/package.sh | 41 -- ports/nasm/nasm.patch | 13 - ports/nasm/package.sh | 41 -- ports/remove-port.sh | 45 -- tests/Makefile | 9 - tests/Test.h | 45 -- tests/libc/Makefile | 15 - tests/libc/Test.c | 70 -- tests/libc/stdlib.c | 234 ------- tests/libc/string.c | 385 ----------- tests/libc/wchar.c | 21 - 304 files changed, 62 insertions(+), 21552 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 apps/Makefile delete mode 100644 apps/src/args.c delete mode 100644 apps/src/cat.c delete mode 100644 apps/src/date.c delete mode 100644 apps/src/hello-cpp.cpp delete mode 100644 apps/src/hello.c delete mode 100644 apps/src/init.c delete mode 100644 apps/src/ls.c delete mode 100644 apps/src/mkdir.c delete mode 100644 apps/src/ps.c delete mode 100644 apps/src/screen.c delete mode 100644 apps/src/session.c delete mode 100644 apps/src/sh.c delete mode 100644 apps/src/stat.c delete mode 100644 apps/src/su.c delete mode 100644 apps/src/touch.c delete mode 100644 apps/src/uname.c delete mode 100644 apps/src/uptime.c delete mode 100644 apps/src/write.c delete mode 100644 initrd/etc/motd delete mode 100644 initrd/etc/passwd delete mode 100644 initrd/make-folders.sh create mode 100644 kernel/CMakeLists.txt delete mode 100644 kernel/Makefile delete mode 100644 kernel/include/acpi/FADT.h delete mode 100644 kernel/include/acpi/RSDT.h delete mode 100644 kernel/include/acpi/SDT.h delete mode 100644 kernel/include/bootboot.h delete mode 100644 kernel/include/config.h delete mode 100644 kernel/include/cpu/CPU.h delete mode 100644 kernel/include/cpu/Features.h delete mode 100644 kernel/include/font.h delete mode 100644 kernel/include/fs/FileDescriptor.h delete mode 100644 kernel/include/fs/InitRD.h delete mode 100644 kernel/include/fs/TmpFS.h delete mode 100644 kernel/include/fs/VFS.h delete mode 100644 kernel/include/fs/devices/Console.h delete mode 100644 kernel/include/fs/devices/DeviceFS.h delete mode 100644 kernel/include/fs/devices/Framebuffer.h delete mode 100644 kernel/include/fs/devices/Keyboard.h delete mode 100644 kernel/include/fs/devices/NullDevice.h delete mode 100644 kernel/include/fs/devices/Random.h delete mode 100644 kernel/include/fs/devices/Serial.h delete mode 100644 kernel/include/fs/devices/Version.h delete mode 100644 kernel/include/gdt/GDT.h delete mode 100644 kernel/include/init/Init.h delete mode 100644 kernel/include/interrupts/Context.h delete mode 100644 kernel/include/interrupts/IDT.h delete mode 100644 kernel/include/interrupts/IRQ.h delete mode 100644 kernel/include/interrupts/Install.h delete mode 100644 kernel/include/interrupts/Interrupts.h delete mode 100644 kernel/include/io/IO.h delete mode 100644 kernel/include/io/PCI.h delete mode 100644 kernel/include/io/PIC.h delete mode 100644 kernel/include/io/Serial.h delete mode 100644 kernel/include/log/CLog.h delete mode 100644 kernel/include/log/Log.h delete mode 100644 kernel/include/memory/AddressSpace.h delete mode 100644 kernel/include/memory/KernelHeap.h delete mode 100644 kernel/include/memory/Memory.h delete mode 100644 kernel/include/memory/MemoryManager.h delete mode 100644 kernel/include/memory/MemoryMap.h delete mode 100644 kernel/include/memory/PMM.h delete mode 100644 kernel/include/memory/Paging.h delete mode 100644 kernel/include/memory/UserHeap.h delete mode 100644 kernel/include/memory/VMM.h delete mode 100644 kernel/include/memory/liballoc/liballoc.h delete mode 100644 kernel/include/misc/MSR.h delete mode 100644 kernel/include/misc/PCITypes.h delete mode 100644 kernel/include/misc/Scancodes.h delete mode 100644 kernel/include/misc/hang.h delete mode 100644 kernel/include/misc/reboot.h delete mode 100644 kernel/include/misc/shutdown.h delete mode 100644 kernel/include/misc/utils.h delete mode 100644 kernel/include/panic/Panic.h delete mode 100644 kernel/include/rand/Init.h delete mode 100644 kernel/include/rand/Mersenne.h delete mode 100644 kernel/include/render/Color.h delete mode 100644 kernel/include/render/Framebuffer.h delete mode 100644 kernel/include/render/TextRenderer.h delete mode 100644 kernel/include/std/ensure.h delete mode 100644 kernel/include/std/errno.h delete mode 100644 kernel/include/std/libgen.h delete mode 100644 kernel/include/std/stdio.h delete mode 100644 kernel/include/std/stdlib.h delete mode 100644 kernel/include/std/string.h delete mode 100644 kernel/include/sys/Syscall.h delete mode 100644 kernel/include/sys/UserMemory.h delete mode 100644 kernel/include/sys/elf/ELF.h delete mode 100644 kernel/include/sys/elf/ELFLoader.h delete mode 100644 kernel/include/sys/elf/Image.h delete mode 100644 kernel/include/thread/PIT.h delete mode 100644 kernel/include/thread/Scheduler.h delete mode 100644 kernel/include/thread/Spinlock.h delete mode 100644 kernel/include/thread/Task.h delete mode 100644 kernel/include/trace/Resolve.h delete mode 100644 kernel/include/trace/StackTracer.h delete mode 100644 kernel/include/utils/Addresses.h delete mode 100644 kernel/include/utils/Dynamic.h delete mode 100644 kernel/include/utils/PageFaultReason.h delete mode 100644 kernel/include/utils/Registers.h delete mode 100644 kernel/include/utils/Result.h delete mode 100644 kernel/include/utils/StringParsing.h delete mode 100644 kernel/include/utils/Time.h delete mode 100644 kernel/include/utils/move.h delete mode 100644 kernel/include/utils/new.h delete mode 100644 kernel/src/acpi/RSDT.cpp delete mode 100644 kernel/src/acpi/SDT.cpp delete mode 100644 kernel/src/cpu/CPU.cpp delete mode 100644 kernel/src/fs/FileDescriptor.cpp delete mode 100644 kernel/src/fs/InitRD.cpp delete mode 100644 kernel/src/fs/TmpFS.cpp delete mode 100644 kernel/src/fs/VFS.cpp delete mode 100644 kernel/src/fs/devices/Console.cpp delete mode 100644 kernel/src/fs/devices/DeviceFS.cpp delete mode 100644 kernel/src/fs/devices/Framebuffer.cpp delete mode 100644 kernel/src/fs/devices/Keyboard.cpp delete mode 100644 kernel/src/fs/devices/NullDevice.cpp delete mode 100644 kernel/src/fs/devices/Random.cpp delete mode 100644 kernel/src/fs/devices/Serial.cpp delete mode 100644 kernel/src/fs/devices/Version.cpp delete mode 100644 kernel/src/gdt/GDT.asm delete mode 100644 kernel/src/gdt/GDT.cpp delete mode 100644 kernel/src/init/Init.cpp delete mode 100644 kernel/src/interrupts/Entry.cpp delete mode 100644 kernel/src/interrupts/IDT.cpp delete mode 100644 kernel/src/interrupts/IRQ.cpp delete mode 100644 kernel/src/interrupts/Install.cpp delete mode 100644 kernel/src/interrupts/InterruptEntry.asm delete mode 100644 kernel/src/interrupts/Interrupts.cpp delete mode 100644 kernel/src/io/IO.cpp delete mode 100644 kernel/src/io/PCI.cpp delete mode 100644 kernel/src/io/PIC.cpp delete mode 100644 kernel/src/io/Serial.cpp delete mode 100644 kernel/src/log/CLog.cpp delete mode 100644 kernel/src/log/Log.cpp delete mode 100644 kernel/src/main.asm delete mode 100644 kernel/src/memory/AddressSpace.cpp delete mode 100644 kernel/src/memory/KernelHeap.cpp delete mode 100644 kernel/src/memory/Memory.cpp delete mode 100644 kernel/src/memory/MemoryManager.cpp delete mode 100644 kernel/src/memory/MemoryMap.cpp delete mode 100644 kernel/src/memory/PMM.cpp delete mode 100644 kernel/src/memory/Paging.cpp delete mode 100644 kernel/src/memory/UserHeap.cpp delete mode 100644 kernel/src/memory/VMM.cpp delete mode 100644 kernel/src/memory/liballoc/bindings.cpp delete mode 100644 kernel/src/memory/liballoc/liballoc.c delete mode 100644 kernel/src/misc/MSR.cpp delete mode 100644 kernel/src/misc/PCITypes.cpp delete mode 100644 kernel/src/misc/Scancodes.cpp delete mode 100644 kernel/src/misc/config.cpp delete mode 100644 kernel/src/misc/cxxabi.cpp delete mode 100644 kernel/src/misc/hang.cpp delete mode 100644 kernel/src/misc/new.cpp delete mode 100644 kernel/src/misc/reboot.cpp delete mode 100644 kernel/src/misc/shutdown.cpp delete mode 100644 kernel/src/misc/stack.cpp delete mode 100644 kernel/src/misc/ubsan.cpp delete mode 100644 kernel/src/panic/Panic.cpp delete mode 100644 kernel/src/rand/Init.asm delete mode 100644 kernel/src/rand/Init.cpp delete mode 100644 kernel/src/rand/Mersenne.cpp delete mode 100644 kernel/src/render/Color.cpp delete mode 100644 kernel/src/render/Framebuffer.cpp delete mode 100644 kernel/src/render/TextRenderer.cpp delete mode 100644 kernel/src/std/libgen.cpp delete mode 100644 kernel/src/std/stdio.cpp delete mode 100644 kernel/src/std/stdlib.cpp delete mode 100644 kernel/src/std/string.cpp delete mode 100644 kernel/src/sys/Syscall.cpp delete mode 100644 kernel/src/sys/UserMemory.cpp delete mode 100644 kernel/src/sys/clock.cpp delete mode 100644 kernel/src/sys/dirent.cpp delete mode 100644 kernel/src/sys/elf/ELFLoader.cpp delete mode 100644 kernel/src/sys/exec.cpp delete mode 100644 kernel/src/sys/id.cpp delete mode 100644 kernel/src/sys/mem.cpp delete mode 100644 kernel/src/sys/sched.cpp delete mode 100644 kernel/src/sys/stat.cpp delete mode 100644 kernel/src/sys/stdio.cpp delete mode 100644 kernel/src/thread/PIT.cpp delete mode 100644 kernel/src/thread/Scheduler.cpp delete mode 100644 kernel/src/thread/Spinlock.asm delete mode 100644 kernel/src/thread/Spinlock.cpp delete mode 100644 kernel/src/thread/Task.cpp delete mode 100644 kernel/src/trace/Resolve.cpp delete mode 100644 kernel/src/trace/StackTracer.cpp delete mode 100644 kernel/src/utils/PageFaultReason.cpp delete mode 100644 kernel/src/utils/StringParsing.cpp delete mode 100644 kernel/src/utils/Time.cpp delete mode 100644 libs/Makefile delete mode 100644 libs/libc/Makefile delete mode 100644 libs/libc/crt0.asm delete mode 100644 libs/libc/crti.asm delete mode 100644 libs/libc/crtn.asm delete mode 100644 libs/libc/include/alloca.h delete mode 100644 libs/libc/include/assert.h delete mode 100644 libs/libc/include/bits/error.h delete mode 100644 libs/libc/include/bits/getprocid.h delete mode 100644 libs/libc/include/bits/liballoc.h delete mode 100644 libs/libc/include/bits/macros.h delete mode 100644 libs/libc/include/bits/seek.h delete mode 100644 libs/libc/include/ctype.h delete mode 100644 libs/libc/include/dirent.h delete mode 100644 libs/libc/include/errno.h delete mode 100644 libs/libc/include/fcntl.h delete mode 100644 libs/libc/include/inttypes.h delete mode 100644 libs/libc/include/libgen.h delete mode 100644 libs/libc/include/locale.h delete mode 100644 libs/libc/include/luna.h delete mode 100644 libs/libc/include/luna/dirent.h delete mode 100644 libs/libc/include/luna/os-limits.h delete mode 100644 libs/libc/include/luna/pstat.h delete mode 100644 libs/libc/include/luna/syscall.h delete mode 100644 libs/libc/include/luna/vfs.h delete mode 100644 libs/libc/include/math.h delete mode 100644 libs/libc/include/memory.h delete mode 100644 libs/libc/include/pwd.h delete mode 100644 libs/libc/include/sched.h delete mode 100644 libs/libc/include/setjmp.h delete mode 100644 libs/libc/include/signal.h delete mode 100644 libs/libc/include/stdio.h delete mode 100644 libs/libc/include/stdlib.h delete mode 100644 libs/libc/include/string.h delete mode 100644 libs/libc/include/strings.h delete mode 100644 libs/libc/include/sys/ioctl.h delete mode 100644 libs/libc/include/sys/mman.h delete mode 100644 libs/libc/include/sys/param.h delete mode 100644 libs/libc/include/sys/stat.h delete mode 100644 libs/libc/include/sys/syscall.h delete mode 100644 libs/libc/include/sys/time.h delete mode 100644 libs/libc/include/sys/types.h delete mode 100644 libs/libc/include/sys/wait.h delete mode 100644 libs/libc/include/time.h delete mode 100644 libs/libc/include/unistd.h delete mode 100644 libs/libc/include/utime.h delete mode 100644 libs/libc/include/wchar.h delete mode 100644 libs/libc/src/assert.cpp delete mode 100644 libs/libc/src/atexit.cpp delete mode 100644 libs/libc/src/bits/bindings.c delete mode 100644 libs/libc/src/bits/liballoc.c delete mode 100644 libs/libc/src/ctype.cpp delete mode 100644 libs/libc/src/cxxabi.cpp delete mode 100644 libs/libc/src/dirent.cpp delete mode 100644 libs/libc/src/errno.cpp delete mode 100644 libs/libc/src/fcntl.cpp delete mode 100644 libs/libc/src/file.cpp delete mode 100644 libs/libc/src/init.cpp delete mode 100644 libs/libc/src/libgen.cpp delete mode 100644 libs/libc/src/locale.cpp delete mode 100644 libs/libc/src/luna.cpp delete mode 100644 libs/libc/src/luna/dirent.cpp delete mode 100644 libs/libc/src/luna/pstat.cpp delete mode 100644 libs/libc/src/luna/syscall.asm delete mode 100644 libs/libc/src/math.cpp delete mode 100644 libs/libc/src/printf.cpp delete mode 100644 libs/libc/src/pwd.cpp delete mode 100644 libs/libc/src/rand.cpp delete mode 100644 libs/libc/src/sched.cpp delete mode 100644 libs/libc/src/setjmp.asm delete mode 100644 libs/libc/src/setjmp.cpp delete mode 100644 libs/libc/src/signal.cpp delete mode 100644 libs/libc/src/stdio.cpp delete mode 100644 libs/libc/src/stdlib.cpp delete mode 100644 libs/libc/src/strftime.cpp delete mode 100644 libs/libc/src/string.cpp delete mode 100644 libs/libc/src/strings.cpp delete mode 100644 libs/libc/src/sys/ioctl.cpp delete mode 100644 libs/libc/src/sys/mman.cpp delete mode 100644 libs/libc/src/sys/stat.cpp delete mode 100644 libs/libc/src/sys/wait.cpp delete mode 100644 libs/libc/src/syscall.cpp delete mode 100644 libs/libc/src/time.cpp delete mode 100644 libs/libc/src/unistd.cpp delete mode 100644 libs/libc/src/utime.cpp delete mode 100644 libs/libc/src/wchar.cpp create mode 100644 luna/Types.h delete mode 100755 ports/add-port.sh delete mode 100644 ports/bc/bc.patch delete mode 100644 ports/bc/package.sh delete mode 100644 ports/binutils/binutils.patch delete mode 100644 ports/binutils/package.sh delete mode 100644 ports/gmp/gmp.patch delete mode 100644 ports/gmp/package.sh delete mode 100755 ports/list-ports.sh delete mode 100755 ports/make-package.sh delete mode 100644 ports/mpc/package.sh delete mode 100644 ports/mpfr/package.sh delete mode 100644 ports/nasm/nasm.patch delete mode 100644 ports/nasm/package.sh delete mode 100755 ports/remove-port.sh delete mode 100644 tests/Makefile delete mode 100644 tests/Test.h delete mode 100644 tests/libc/Makefile delete mode 100644 tests/libc/Test.c delete mode 100644 tests/libc/stdlib.c delete mode 100644 tests/libc/string.c delete mode 100644 tests/libc/wchar.c diff --git a/.gitignore b/.gitignore index c759f33d..1a09d8ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,5 @@ Luna.iso toolchain/ .vscode/ -**/*.o -initrd/boot/moon -kernel/bin/moon -initrd/sys/moon.sym -initrd/bin/** -apps/bin/** -tests/**/bin/** -base/usr/** -**/*.a -ports/**/workdir/** -ports/ports.list -**/*.pkg.tar.xz \ No newline at end of file +build/ +initrd/boot/moon \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..97cc6d2b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.8..3.22) + +set(CMAKE_C_COMPILER_WORKS 1) +set(CMAKE_CXX_COMPILER_WORKS 1) + +set(CMAKE_SYSTEM_NAME Luna) +set(CMAKE_CROSSCOMPILING true) + +project(Luna LANGUAGES C CXX ASM) + +set(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR}) + +set(CMAKE_C_COMPILER x86_64-luna-gcc) +set(CMAKE_CXX_COMPILER x86_64-luna-g++) + +set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) + +add_subdirectory(kernel) \ No newline at end of file diff --git a/apps/Makefile b/apps/Makefile deleted file mode 100644 index 3ae58d7e..00000000 --- a/apps/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -C_APPS := init sh uname uptime hello ps ls args cat stat su session date mkdir screen touch write -CXX_APPS := hello-cpp - -APPS_DIR := $(LUNA_ROOT)/apps -APPS_SRC := $(APPS_DIR)/src -APPS_BIN := $(APPS_DIR)/bin - -C_APPS_PATH := $(patsubst %, $(APPS_BIN)/%, $(C_APPS)) -CXX_APPS_PATH := $(patsubst %, $(APPS_BIN)/%, $(CXX_APPS)) - -CFLAGS := -Wall -Wextra -Werror -Os -fno-asynchronous-unwind-tables -ffunction-sections -fdata-sections -Wl,--gc-sections -CXXFLAGS := -fno-exceptions - -$(APPS_BIN)/%: $(APPS_SRC)/%.c - @mkdir -p $(@D) - @$(CC) $(CFLAGS) -o $@ $^ - @echo " CC $^" - -$(APPS_BIN)/%: $(APPS_SRC)/%.cpp - @mkdir -p $(@D) - @$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ $^ - @echo " CXX $^" - -build: $(C_APPS_PATH) $(CXX_APPS_PATH) - -install: $(C_APPS_PATH) $(CXX_APPS_PATH) - @mkdir -p $(LUNA_ROOT)/initrd/bin - @cp $(C_APPS_PATH) $(CXX_APPS_PATH) $(LUNA_ROOT)/initrd/bin - @echo " INSTALL $(C_APPS) $(CXX_APPS)" - @chmod a+s $(LUNA_ROOT)/initrd/bin/su - -clean: - rm -f $(APPS_BIN)/* \ No newline at end of file diff --git a/apps/src/args.c b/apps/src/args.c deleted file mode 100644 index aa3bf2f3..00000000 --- a/apps/src/args.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -int main(int argc, char** argv) -{ - for (int i = 0; i < argc; i++) puts(argv[i]); -} \ No newline at end of file diff --git a/apps/src/cat.c b/apps/src/cat.c deleted file mode 100644 index 7c744913..00000000 --- a/apps/src/cat.c +++ /dev/null @@ -1,45 +0,0 @@ -#define _GNU_SOURCE // for program_invocation_name -#include - -#include -#include -#include - -void cat(FILE* stream) -{ - char buf[BUFSIZ]; - do { - fgets(buf, BUFSIZ, stream); - if (ferror(stream)) - { - perror(program_invocation_name); - exit(EXIT_FAILURE); - } - fputs(buf, stdout); - } while (!feof(stream)); -} - -int main(int argc, char** argv) -{ - if (argc == 1) cat(stdin); - else - { - for (int i = 1; i < argc; i++) - { - if (strcmp(argv[i], "-") == 0) cat(stdin); - else if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--newline") == 0) - putchar('\n'); - else - { - FILE* stream = fopen(argv[i], "r"); - if (!stream) - { - perror(program_invocation_name); - return EXIT_FAILURE; - } - cat(stream); - fclose(stream); - } - } - } -} \ No newline at end of file diff --git a/apps/src/date.c b/apps/src/date.c deleted file mode 100644 index b8243899..00000000 --- a/apps/src/date.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -int main() -{ - time_t date = time(NULL); - - fputs(ctime(&date), stdout); -} \ No newline at end of file diff --git a/apps/src/hello-cpp.cpp b/apps/src/hello-cpp.cpp deleted file mode 100644 index a6eda67f..00000000 --- a/apps/src/hello-cpp.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include - -int main() -{ - std::printf("Well hello world!\n"); - - std::string str = "this is a c++ string"; - - str.append(" yay"); - - std::printf("%s\n", str.c_str()); - - std::vector vec = {3, 2, 8}; - - for (int i : vec) { std::printf("%d ", i); } - std::putchar('\n'); -} \ No newline at end of file diff --git a/apps/src/hello.c b/apps/src/hello.c deleted file mode 100644 index 50106f10..00000000 --- a/apps/src/hello.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main() -{ - puts("Hello, world!"); -} \ No newline at end of file diff --git a/apps/src/init.c b/apps/src/init.c deleted file mode 100644 index 9a97a46b..00000000 --- a/apps/src/init.c +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void show_motd() -{ - int fd = open("/etc/motd", O_RDONLY | O_CLOEXEC); - if (fd < 0) - { - if (errno != ENOENT) { perror("open"); } - return; - } - FILE* fp = fdopen(fd, "r"); - if (!fp) - { - perror("fopen"); - return; - } - - char buf[4096]; - size_t nread = fread(buf, 1, sizeof(buf) - 1, fp); - if (ferror(fp)) - { - perror("fread"); - fclose(fp); - return; - } - buf[nread] = 0; - - puts(buf); - - fclose(fp); - - putchar('\n'); -} - -int main() -{ - if (getpid() != 1) - { - fprintf(stderr, "init must be started as PID 1\n"); - return 1; - } - - if (getuid() != 0) - { - fprintf(stderr, "init must be started as root\n"); - return 1; - } - - show_motd(); - - pid_t child = fork(); - if (child < 0) - { - perror("fork"); - return 1; - } - if (child == 0) - { - char* argv[] = {"/bin/session", NULL}; - execv(argv[0], argv); - perror("execv"); - return 1; - } - - pid_t result; - - for (;;) - { - result = wait(NULL); - if (result == child) return 0; - } -} diff --git a/apps/src/ls.c b/apps/src/ls.c deleted file mode 100644 index aa81fb2f..00000000 --- a/apps/src/ls.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include -#include -#include - -int main(int argc, char** argv) -{ - const char* pathname; - if (argc == 1) pathname = "/"; - else - pathname = argv[1]; - DIR* dp = opendir(pathname); - if (!dp) - { - perror("opendir"); - return 1; - } - bool first_ent = true; - do { - struct dirent* ent = readdir(dp); - if (!ent) break; - printf(first_ent ? "%s" : " %s", ent->d_name); - first_ent = false; - } while (1); - - printf("\n"); - - closedir(dp); - return 0; -} \ No newline at end of file diff --git a/apps/src/mkdir.c b/apps/src/mkdir.c deleted file mode 100644 index 60a00b86..00000000 --- a/apps/src/mkdir.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -int main(int argc, char** argv) -{ - if (argc == 1) - { - fprintf(stderr, "Usage: %s [directory]\n", argv[0]); - return 1; - } - - if (mkdir(argv[1], 0755) < 0) - { - perror("mkdir"); - return 1; - } -} \ No newline at end of file diff --git a/apps/src/ps.c b/apps/src/ps.c deleted file mode 100644 index 1a58c8e2..00000000 --- a/apps/src/ps.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include -#include -#include -#include - -pid_t get_current_max_threads() -{ - pid_t result = pstat(-1, NULL); - if (result < 0) - { - perror("pstat(-1)"); - exit(1); - } - return result; -} - -void display_process(struct pstat* pstatbuf) -{ - struct passwd* pwd = getpwuid(pstatbuf->pt_uid); - if (!pwd && errno) perror("getpwuid"); - printf("%s %ld %ld %s %s (%ld ms)\n", pwd ? pwd->pw_name : "???", pstatbuf->pt_pid, pstatbuf->pt_ppid, - pstatbuf->pt_name, pstatname(pstatbuf), pstatbuf->pt_time); -} - -int try_pstat(pid_t pid, struct pstat* pstatbuf) -{ - pid_t result = pstat(pid, pstatbuf); - if (result < 0) - { - if (errno == ESRCH) return 0; - perror("pstat"); - exit(1); - } - return 1; -} - -int main() -{ - struct pstat pst; - pid_t max = get_current_max_threads(); - for (pid_t pid = 0; pid <= max; pid++) - { - if (try_pstat(pid, &pst)) { display_process(&pst); } - } - endpwent(); -} \ No newline at end of file diff --git a/apps/src/screen.c b/apps/src/screen.c deleted file mode 100644 index 7b26ba33..00000000 --- a/apps/src/screen.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include -#include - -int main() -{ - int fd = open("/dev/fb0", O_WRONLY | O_CLOEXEC); - if (fd < 0) - { - perror("open"); - return 1; - } - - int fb_width = ioctl(fd, FB_GET_WIDTH); - if (fb_width < 0) - { - perror("ioctl(FB_GET_WIDTH)"); - return 1; - } - - int fb_height = ioctl(fd, FB_GET_HEIGHT); - if (fb_height < 0) - { - perror("ioctl(FB_GET_HEIGHT)"); - return 1; - } - - printf("Your screen is %dx%d\n", fb_width, fb_height); - - close(fd); -} \ No newline at end of file diff --git a/apps/src/session.c b/apps/src/session.c deleted file mode 100644 index 7faf8df0..00000000 --- a/apps/src/session.c +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static char* echoing_fgets(char* buf, size_t size, FILE* stream) -{ - char* s = buf; - memset(buf, 0, size); - size_t oldsize = size; - while (size) - { - int c = fgetc(stream); - if (c == EOF) - { - if (ferror(stream)) return NULL; - if (feof(stream)) - { - if (s != buf) return s; - else - return NULL; - }; - } - if ((char)c == '\b') - { - if (size != oldsize) - { - buf--; - size++; - putchar('\b'); - } - } - else - { - size--; - *buf = (char)c; - buf++; - putchar((char)c); - if ((char)c == '\n') return s; - } - *buf = 0; - } - return s; -} - -static void strip_newline(char* str) -{ - size_t len = strlen(str); - if (str[len - 1] == '\n') str[len - 1] = 0; -} - -static char* collect_password() -{ - static char buf[BUFSIZ]; - - printf("Password: "); - fgets(buf, BUFSIZ, stdin); - - strip_newline(buf); - putchar('\n'); - - char* copy = strdup( - buf); // The password only stays in a caller-controlled heap-allocated buffer, where it can be freed at will. - - memset(buf, 0, BUFSIZ); - - return copy; -} - -static void login_as(struct passwd* user) -{ - pid_t child = fork(); - if (child < 0) - { - perror("fork"); - return; - } - if (child == 0) - { - setgid(user->pw_gid); - setuid(user->pw_uid); - char* argv[] = {user->pw_shell, NULL}; - execv(argv[0], argv); - perror("execv"); - exit(EXIT_FAILURE); - } - wait(NULL); -} - -static int login() -{ - printf("Username: "); - char username[BUFSIZ]; - echoing_fgets(username, BUFSIZ, stdin); - strip_newline(username); - if (strcmp("exit", username) == 0) return 1; - struct passwd* user = getpwnam(username); - if (!user) - { - if (errno) perror("getpwnam"); - else - printf("Unknown user %s\n", username); - return 0; - } - char* password = collect_password(); - putchar('\n'); - if (strcmp(user->pw_passwd, password) == 0) - { - free(password); - login_as(user); - puts("logout\n"); - } - else - { - free(password); - puts("Invalid password.\n"); - } - return 0; -} - -int main(int argc, char** argv) -{ - (void)argc; - - if (getuid() != 0) - { - fprintf(stderr, - "%s must be run as root.\nYou are probably looking for the 'su' command, which lets you switch users " - "once logged in.\n", - argv[0]); - return EXIT_FAILURE; - } - - for (;;) - { - if (login()) break; - } - - endpwent(); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/apps/src/sh.c b/apps/src/sh.c deleted file mode 100644 index 8545f485..00000000 --- a/apps/src/sh.c +++ /dev/null @@ -1,364 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int status = 0; -static char* username = NULL; - -typedef struct -{ - char* buffer; - size_t size; - size_t capacity; - int interactive; -} command_t; - -char** split_command_into_argv(const char* cmd) -{ - size_t argc = 1; - char* ptr = strdup(cmd); - char* endptr; - char** arr = calloc(sizeof(char*), argc); - for (;;) - { - endptr = strchr(ptr, ' '); - arr[argc - 1] = ptr; - if (endptr == NULL) break; - *endptr = 0; - ptr = endptr + 1; - if (*ptr) - { - argc++; - arr = realloc(arr, sizeof(char*) * argc); - } - else - break; - } - argc++; - arr = realloc(arr, sizeof(char*) * argc); - arr[argc - 1] = NULL; - return arr; -} - -char* shell_concat_path(const char* dirname, const char* basename) -{ - char* buf = malloc(strlen(basename) + strlen(dirname) + 6); - strlcpy(buf, dirname, strlen(dirname) + 1); - strncat(buf, basename, strlen(basename)); - return buf; -} - -void shell_execvp(char* pathname, char* const argv[]) -{ - char* new_path; - if (access(pathname, F_OK) == 0) - { - execv(pathname, argv); - return; - } - if (pathname[0] == '/') return; // We do not want to lookup absolute paths - new_path = shell_concat_path("/bin/", pathname); - if (access(new_path, F_OK) == 0) - { - execv(new_path, argv); - return; - } - free(new_path); - new_path = shell_concat_path("/usr/bin/", pathname); - execv(new_path, argv); - int saved = errno; - free(new_path); - errno = saved; -} - -void show_prompt() -{ - if (WEXITSTATUS(status)) { printf("%d [%s]> ", WEXITSTATUS(status), username); } - else - printf("[%s]> ", username); -} - -int command_matches(command_t* cmd, const char* string) -{ - if (cmd->size <= strlen(string)) // cmd->size includes null terminator - return 0; - return strncmp(cmd->buffer, string, strlen(string)) == 0; -} - -int command_matches_exactly(command_t* cmd, const char* string) -{ - if (cmd->size <= strlen(string)) // cmd->size includes null terminator - return 0; - if (cmd->size > (strlen(string) + 1)) return 0; - return strncmp(cmd->buffer, string, strlen(string)) == 0; -} - -int command_match_builtins(command_t* cmd) -{ - if (command_matches(cmd, "exit ")) { exit(atoi(cmd->buffer + 5)); } - if (command_matches_exactly(cmd, "exit")) { exit(0); } - if (command_matches_exactly(cmd, "id")) - { - printf("pid %ld, ppid %ld, uid %d (%s), gid %d\n", getpid(), getppid(), getuid(), username, getgid()); - return 1; - } - if (command_matches(cmd, "sleep")) - { - sleep(atoi(cmd->buffer + 6)); - return 1; - } - if (command_matches_exactly(cmd, "clear")) - { - fputs("\033@", stdout); // clear screen. for now, escape sequences in luna are non-standard. - return 1; - } - return 0; -} - -void command_expand(command_t* cmd, long new_capacity) -{ - char* buffer = realloc(cmd->buffer, new_capacity); - if (!buffer) - { - perror("realloc"); - exit(1); - } - cmd->buffer = buffer; - cmd->capacity = new_capacity; -} - -void command_push(command_t* cmd, char c) -{ - if (cmd->size == cmd->capacity) command_expand(cmd, cmd->capacity + 8); - cmd->buffer[cmd->size] = c; - cmd->size++; -} - -void command_pop(command_t* cmd) -{ - cmd->size--; -} - -void command_init(command_t* cmd) -{ - cmd->buffer = malloc(5); - cmd->capacity = 5; - cmd->size = 0; -} - -void command_clear(command_t* cmd) -{ - free(cmd->buffer); - return command_init(cmd); -} - -void process_execute_command(const char* command) -{ - char** argv = split_command_into_argv(command); - shell_execvp(argv[0], argv); - perror(argv[0]); - exit(127); -} - -void command_execute(command_t* cmd) -{ - command_push(cmd, '\0'); - if (command_match_builtins(cmd)) - { - command_clear(cmd); - if (cmd->interactive) show_prompt(); - return; - } - pid_t child = fork(); - if (child < 0) - { - perror("fork"); - command_clear(cmd); - if (cmd->interactive) show_prompt(); - return; - } - if (child == 0) process_execute_command(cmd->buffer); - pid_t result = waitpid(child, &status, 0); - if (result < 0) - { - perror("waitpid"); - command_clear(cmd); - if (cmd->interactive) show_prompt(); - return; - } - int exit_status = WEXITSTATUS(status); - if (exit_status == -2 || exit_status == -3) printf("(PID %ld) Segmentation fault\n", result); - if (exit_status == -1) printf("(PID %ld) Aborted\n", result); - command_clear(cmd); - if (cmd->interactive) show_prompt(); -} - -void command_concat_char(command_t* cmd, char c) -{ - if (c == '\b') - { - if (cmd->size != 0) - { - if (cmd->interactive) putchar(c); - command_pop(cmd); - } - } - else if (c == '\n') - { - if (cmd->interactive) putchar(c); - if (cmd->size == 0) - { - status = 0; - if (cmd->interactive) show_prompt(); - } - else - command_execute(cmd); - } - else - { - if (cmd->interactive) putchar(c); - command_push(cmd, c); - } -} - -void command_concat(command_t* cmd, const char* str) -{ - while (*str) - { - command_concat_char(cmd, *str); - str++; - } -} - -void shell_interactive() -{ - show_prompt(); - - command_t shell_command; - command_init(&shell_command); - - shell_command.interactive = 1; - - while (1) - { - int c = getchar(); - if (c == EOF) - { - if (ferror(stdin)) - { - perror("getchar"); - exit(EXIT_FAILURE); - } - if (feof(stdin)) exit(EXIT_SUCCESS); - assert(false); // we should never get here - } - command_concat_char(&shell_command, (char)c); - } -} - -void shell_read_from_file(const char* pathname) -{ - FILE* fp = fopen(pathname, "r"); - if (!fp) - { - perror("sh"); - exit(EXIT_FAILURE); - } - - command_t file_command; - command_init(&file_command); - - file_command.interactive = 0; - - char buffer[BUFSIZ]; - while (fgets(buffer, BUFSIZ, fp)) - { - command_concat(&file_command, buffer); - if (feof(fp)) break; - } - - if (file_command.size > 0) // last line of file, does not end with newline - { - command_execute(&file_command); - } - - fclose(fp); -} - -void shell_execute_command(const char* command) -{ - command_t cmd; - cmd.buffer = strdup(command); - cmd.size = strlen(command) + 1; - if (command_match_builtins(&cmd)) return; - command_clear(&cmd); - process_execute_command(command); -} - -void fetch_username() -{ - struct passwd* user = getpwuid(getuid()); - if (!user) - { - perror("getpwuid"); - exit(EXIT_FAILURE); - } - username = user->pw_name; - endpwent(); -} - -int main(int argc, char** argv) -{ - fetch_username(); - - if (argc == 1) shell_interactive(); - else if (argc == 2) - { - if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) - { - puts("Luna sh version 0.1"); // FIXME: Store the version somewhere, or use the kernel's version. - return 0; - } - - if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) - { - printf("To use interactively: %s\n", argv[0]); - printf("To run a script: %s [script-name]\n", argv[0]); - printf("To get help: %s --help\n", argv[0]); - printf("To show the version: %s --version\n", argv[0]); - printf("To run a command: %s -c [command]\n", argv[0]); - return 0; - } - - if (!strcmp(argv[1], "-c") || !strcmp(argv[1], "--command")) - { - fprintf(stderr, "Usage: %s %s [command]\n", argv[0], argv[1]); - fprintf(stderr, "Use the --help flag for more help.\n"); - return 1; - } - - shell_read_from_file(argv[1]); - } - else if (argc == 3) - { - if (!strcmp(argv[1], "-c") || !strcmp(argv[1], "--command")) shell_execute_command(argv[2]); - else - { - fprintf(stderr, "%s: too many arguments\n", argv[0]); - fprintf(stderr, "Use the --help flag for more help.\n"); - return 1; - } - } - else - { - fprintf(stderr, "%s: too many arguments\n", argv[0]); - fprintf(stderr, "Use the --help flag for more help.\n"); - return 1; - } -} \ No newline at end of file diff --git a/apps/src/stat.c b/apps/src/stat.c deleted file mode 100644 index 7e158bea..00000000 --- a/apps/src/stat.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include - -const char* mode_to_string(mode_t mode) -{ - static char mode_string[12]; - - char mode_set[12] = {'s', 'g', 'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x', 0}; - mode_t mode_val[12] = {S_ISUID, S_ISGID, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, - S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH, S_IFMT}; - - for (int i = 0; i < 12; i++) - { - if (mode & mode_val[i]) mode_string[i] = mode_set[i]; - else - mode_string[i] = '-'; - } - - return mode_string; -} - -int main(int argc, char** argv) -{ - if (argc == 1) - { - fprintf(stderr, "Usage: stat [file]\n"); - return EXIT_FAILURE; - } - - struct stat st; - if (stat(argv[1], &st) < 0) - { - perror("stat"); - return EXIT_FAILURE; - } - - printf("Type: "); - - switch (st.st_mode & S_IFMT) - { - case S_IFREG: puts("Regular file"); break; - case S_IFDIR: puts("Directory"); break; - case S_IFCHR: puts("Character device"); break; - default: puts("Unknown"); break; - } - - struct passwd* own = getpwuid(st.st_uid); - - printf("Length: %ld\n", st.st_size); - printf("Inode: %ld\n", st.st_ino); - if (!own) printf("Owned by: UID %d\n", st.st_uid); - else - printf("Owned by: %s\n", own->pw_name); - printf("Mode: %s\n", mode_to_string(st.st_mode)); - - printf("Accessed on: %s", ctime(&st.st_atime)); - printf("Modified on: %s", ctime(&st.st_mtime)); - printf("Changed on: %s", ctime(&st.st_ctime)); - - endpwent(); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/apps/src/su.c b/apps/src/su.c deleted file mode 100644 index 4c9c2a02..00000000 --- a/apps/src/su.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void run_program(char** argv) -{ - execv(argv[0], argv); - - perror("execv"); - exit(EXIT_FAILURE); -} - -void strip_newline(char* str) -{ - size_t len = strlen(str); - if (str[len - 1] == '\n') str[len - 1] = 0; -} - -static const char* collect_password() -{ - static char buf[BUFSIZ]; - - printf("Password: "); - fgets(buf, BUFSIZ, stdin); - - strip_newline(buf); - putchar('\n'); - - return buf; -} - -int main(int argc, char** argv) -{ - const char* username; - - if (argc == 1) username = "root"; - else - username = argv[1]; - - if (geteuid() != 0) - { - fprintf(stderr, "%s must be setuid root", argv[0]); - return EXIT_FAILURE; - } - - struct passwd* user = getpwnam(username); - - endpwent(); - - if (!user) - { - if (errno) perror("getpwnam"); - else - fprintf(stderr, "Unknown user %s\n", username); - return EXIT_FAILURE; - } - - if (getuid() != geteuid()) // we were started from a non-root user - { - const char* pw = collect_password(); - if (strcmp(pw, user->pw_passwd) != 0) - { - fprintf(stderr, "Invalid password\n"); - return EXIT_FAILURE; - } - } - - if (setgid(user->pw_gid) < 0) - { - perror("setgid"); - return EXIT_FAILURE; - } - - if (setuid(user->pw_uid) < 0) - { - perror("setuid"); - return EXIT_FAILURE; - } - - char* default_argv[] = {user->pw_shell, NULL}; - - if (argc < 3) run_program(default_argv); - else - run_program(argv + 2); -} \ No newline at end of file diff --git a/apps/src/touch.c b/apps/src/touch.c deleted file mode 100644 index b2b0a218..00000000 --- a/apps/src/touch.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include - -int main(int argc, char** argv) -{ - if (argc == 1) - { - fprintf(stderr, "Usage: %s [directory]\n", argv[0]); - return 1; - } - - int fd = creat(argv[1], 0755); - - if (fd < 0) - { - perror("creat"); - return 1; - } - - close(fd); -} \ No newline at end of file diff --git a/apps/src/uname.c b/apps/src/uname.c deleted file mode 100644 index 380e00ff..00000000 --- a/apps/src/uname.c +++ /dev/null @@ -1,18 +0,0 @@ -#include - -int main() -{ - FILE* fp = fopen("/dev/version", "r"); - if (!fp) - { - perror("fopen"); - return 1; - } - - char buf[BUFSIZ]; - fgets(buf, sizeof(buf), fp); - - printf("%s\n", buf); - - fclose(fp); -} \ No newline at end of file diff --git a/apps/src/uptime.c b/apps/src/uptime.c deleted file mode 100644 index 673ff47c..00000000 --- a/apps/src/uptime.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#define VALUE_SINGULAR_AT_ONE(v) v, v == 1 ? "" : "s" - -int main() -{ - struct timespec tp; - clock_gettime(CLOCK_MONOTONIC, &tp); // On Luna, CLOCK_MONOTONIC starts at boot. - - struct tm* time = gmtime( - &tp.tv_sec); // just splitting the value into seconds, minutes, hours, days... not the best way to do it but ok. - time->tm_year -= 70; - - if (time->tm_year) - { - printf("up for %d year%s, %d day%s, %d hour%s, %d minute%s, %d second%s\n", - VALUE_SINGULAR_AT_ONE(time->tm_year), VALUE_SINGULAR_AT_ONE(time->tm_yday), - VALUE_SINGULAR_AT_ONE(time->tm_hour), VALUE_SINGULAR_AT_ONE(time->tm_min), - VALUE_SINGULAR_AT_ONE(time->tm_sec)); - } - else if (time->tm_yday) - { - printf("up for %d day%s, %d hour%s, %d minute%s, %d second%s\n", VALUE_SINGULAR_AT_ONE(time->tm_yday), - VALUE_SINGULAR_AT_ONE(time->tm_hour), VALUE_SINGULAR_AT_ONE(time->tm_min), - VALUE_SINGULAR_AT_ONE(time->tm_sec)); - } - else if (time->tm_hour) - { - printf("up for %d hour%s, %d minute%s, %d second%s\n", VALUE_SINGULAR_AT_ONE(time->tm_hour), - VALUE_SINGULAR_AT_ONE(time->tm_min), VALUE_SINGULAR_AT_ONE(time->tm_sec)); - } - else if (time->tm_min) - printf("up for %d minute%s, %d second%s\n", VALUE_SINGULAR_AT_ONE(time->tm_min), - VALUE_SINGULAR_AT_ONE(time->tm_sec)); - else - printf("up for %d second%s\n", VALUE_SINGULAR_AT_ONE(time->tm_sec)); -} \ No newline at end of file diff --git a/apps/src/write.c b/apps/src/write.c deleted file mode 100644 index 1b541da9..00000000 --- a/apps/src/write.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include - -static char* echoing_fgets(char* buf, size_t size, FILE* stream) -{ - char* s = buf; - memset(buf, 0, size); - size_t oldsize = size; - while (size) - { - int c = fgetc(stream); - if (c == EOF) - { - if (ferror(stream)) return NULL; - if (feof(stream)) - { - if (s != buf) return s; - else - return NULL; - }; - } - if ((char)c == '\b') - { - if (size != oldsize) - { - buf--; - size++; - putchar('\b'); - } - } - else - { - size--; - *buf = (char)c; - buf++; - putchar((char)c); - if ((char)c == '\n') return s; - } - *buf = 0; - } - return s; -} - -int main(int argc, char** argv) -{ - if (argc == 1) - { - fprintf(stderr, "Usage: %s [directory]\n", argv[0]); - return 1; - } - - int fd = open(argv[1], O_WRONLY | O_CREAT | O_APPEND, 0755); - - if (fd < 0) - { - perror("open"); - return 1; - } - - FILE* fp = fdopen(fd, "a"); - - char buf[BUFSIZ]; - echoing_fgets(buf, BUFSIZ, stdin); - - fputs(buf, fp); - if (ferror(fp)) - { - perror("fputs"); - return 1; - } - - fclose(fp); -} \ No newline at end of file diff --git a/initrd/etc/motd b/initrd/etc/motd deleted file mode 100644 index 08cac88a..00000000 --- a/initrd/etc/motd +++ /dev/null @@ -1,3 +0,0 @@ -Welcome to Luna! - -Tip of the day: Log in as user 'selene' and password 'moon' :) \ No newline at end of file diff --git a/initrd/etc/passwd b/initrd/etc/passwd deleted file mode 100644 index 3a1d10e2..00000000 --- a/initrd/etc/passwd +++ /dev/null @@ -1,2 +0,0 @@ -root:secure:0:0:Administrator:/:/bin/sh -selene:moon:1:1:Default User:/:/bin/sh \ No newline at end of file diff --git a/initrd/make-folders.sh b/initrd/make-folders.sh deleted file mode 100644 index f2fdd17f..00000000 --- a/initrd/make-folders.sh +++ /dev/null @@ -1,9 +0,0 @@ -mkdir /tmp/1 -sleep 1 -mkdir /tmp/1/2 -sleep 1 -mkdir /tmp/1/2/3 -sleep 1 -mkdir /tmp/1/2/3/4 -sleep 1 -mkdir /tmp/1/2/3/4/5 \ No newline at end of file diff --git a/initrd/sys/config b/initrd/sys/config index 926fdc83..e7a9cff1 100644 --- a/initrd/sys/config +++ b/initrd/sys/config @@ -1,3 +1,2 @@ screen=1024x768 -kernel=boot/moon -verbose=1 \ No newline at end of file +kernel=boot/moon \ No newline at end of file diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt new file mode 100644 index 00000000..70bf59ca --- /dev/null +++ b/kernel/CMakeLists.txt @@ -0,0 +1,26 @@ +set(SOURCES + src/main.cpp +) + +add_compile_options(-Os) + +add_compile_options(-pedantic -Wall -Wextra -Werror -Wvla) +add_compile_options(-Wdisabled-optimization -Wformat=2 -Winit-self) +add_compile_options(-Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) +add_compile_options(-Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) +add_compile_options(-fno-rtti -ffreestanding -fno-exceptions) +add_compile_options(-fno-asynchronous-unwind-tables -fno-omit-frame-pointer) +add_compile_options(-nostdlib -mcmodel=kernel) +add_compile_options(-mno-red-zone) + +add_compile_options(-mno-80387 -mno-mmx -mno-sse -mno-sse2) + +add_link_options(-lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mno-red-zone -mcmodel=kernel) + +add_executable(moon ${SOURCES}) + +target_include_directories(moon PUBLIC ${LUNA_ROOT}/luna) + +target_link_options(moon PRIVATE LINKER:-T ${CMAKE_CURRENT_LIST_DIR}/moon.ld -nostdlib -nodefaultlibs) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/moon" DESTINATION ${LUNA_ROOT}/initrd/boot) \ No newline at end of file diff --git a/kernel/Makefile b/kernel/Makefile deleted file mode 100644 index 14d800c5..00000000 --- a/kernel/Makefile +++ /dev/null @@ -1,85 +0,0 @@ -MOON_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) -MOON_SRC := $(MOON_DIR)/src -MOON_OBJ := $(MOON_DIR)/lib -MOON_BIN := $(MOON_DIR)/bin - -CFLAGS ?= -Os -CFLAGS := ${CFLAGS} -pedantic -Wall -Wextra -Werror -Wvla -Wfloat-equal -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion -ffreestanding -fstack-protector-strong -fno-omit-frame-pointer -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fshort-wchar -mcmodel=kernel -I$(MOON_DIR)/include -isystem $(MOON_DIR)/include/std -CXXFLAGS := -fno-rtti -fno-exceptions -Wsign-promo -Wstrict-null-sentinel -Wctor-dtor-privacy -ASMFLAGS := -felf64 -LDFLAGS := -T$(MOON_DIR)/moon.ld -nostdlib -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mno-red-zone -mcmodel=kernel - -ifneq ($(MOON_BUILD_STABLE), 1) -CFLAGS := ${CFLAGS} -D_MOON_SUFFIX=-$(shell git rev-parse --short HEAD) -endif - -ifeq ($(MOON_BUILD_DEBUG), 1) -CFLAGS := -ggdb -fsanitize=undefined ${CFLAGS} -endif - -rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) - -CXX_SRC = $(call rwildcard,$(MOON_SRC),*.cpp) -C_SRC = $(call rwildcard,$(MOON_SRC),*.c) -NASM_SRC = $(call rwildcard,$(MOON_SRC),*.asm) - -OBJS = $(patsubst $(MOON_SRC)/%.cpp, $(MOON_OBJ)/%.cpp.o, $(CXX_SRC)) -OBJS += $(patsubst $(MOON_SRC)/%.c, $(MOON_OBJ)/%.c.o, $(C_SRC)) -OBJS += $(patsubst $(MOON_SRC)/%.asm, $(MOON_OBJ)/%.asm.o, $(NASM_SRC)) - -default: $(MOON_BIN)/moon - -$(MOON_OBJ)/main.cpp.o: $(MOON_SRC)/main.cpp - @mkdir -p $(@D) - @$(CXX) $(CFLAGS) -fno-stack-protector $(CXXFLAGS) -o $@ -c $^ - @echo " CXX $^" - -$(MOON_OBJ)/misc/config.cpp.o: $(MOON_SRC)/misc/config.cpp FORCE - @mkdir -p $(@D) - @$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $(MOON_SRC)/misc/config.cpp - @echo " CXX $^" - -$(MOON_OBJ)/init/Init.cpp.o: $(MOON_SRC)/init/Init.cpp - @mkdir -p $(@D) - @$(CXX) $(CFLAGS) -fno-stack-protector $(CXXFLAGS) -o $@ -c $^ - @echo " CXX $^" - -$(MOON_OBJ)/%.cpp.o: $(MOON_SRC)/%.cpp - @mkdir -p $(@D) - @$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $^ - @echo " CXX $^" - -$(MOON_OBJ)/memory/liballoc/liballoc.c.o: $(MOON_SRC)/memory/liballoc/liballoc.c - @mkdir -p $(@D) - @$(CC) $(CFLAGS) -fno-sanitize=undefined -o $@ -c $^ - @echo " CC $^" - -$(MOON_OBJ)/%.c.o: $(MOON_SRC)/%.c - @mkdir -p $(@D) - @$(CC) $(CFLAGS) -o $@ -c $^ - @echo " CC $^" - -$(MOON_OBJ)/%.asm.o: $(MOON_SRC)/%.asm - @mkdir -p $(@D) - @$(ASM) $(ASMFLAGS) -o $@ $^ - @echo " ASM $^" - -build: $(OBJS) - @mkdir -p $(MOON_BIN) - @$(CC) $(OBJS) $(LDFLAGS) -o $(MOON_BIN)/moon - @echo " CCLD $(MOON_BIN)/moon" - -clean: - rm -rf $(MOON_OBJ)/* - rm -rf $(MOON_BIN)/* - -install: $(MOON_BIN)/moon - @mkdir -p $(LUNA_ROOT)/initrd/boot - @cp $^ $(LUNA_ROOT)/initrd/boot/moon - @echo " INSTALL $^" - @$(LUNA_ROOT)/tools/generate-symbols.sh - @$(STRIP) $(LUNA_ROOT)/initrd/boot/moon - @echo " STRIP $(LUNA_ROOT)/initrd/boot/moon" - -.PHONY: build clean install FORCE -FORCE: \ No newline at end of file diff --git a/kernel/include/acpi/FADT.h b/kernel/include/acpi/FADT.h deleted file mode 100644 index 553bb43c..00000000 --- a/kernel/include/acpi/FADT.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once -#include "acpi/SDT.h" - -namespace ACPI -{ - enum AddressSpace - { - SystemMemory = 0, - SystemIO = 1, - PCI = 2, - EmbeddedController = 3, - SystemManagementBus = 4, - SystemCMOS = 5, - PCIBarTarget = 6, - IPMI = 7, - GeneralPurposeIO = 8, - GenericSerialBus = 9, - PlatformCommunicationChannel = 10 - }; - - struct GenericAddressStructure - { - uint8_t AddressSpace; - uint8_t BitWidth; - uint8_t BitOffset; - uint8_t AccessSize; - uint64_t Address; - }; - - struct FADT - { - SDTHeader header; - uint32_t FirmwareCtrl; - uint32_t Dsdt; - - uint8_t Reserved; - - uint8_t PreferredPowerManagementProfile; - uint16_t SCI_Interrupt; - uint32_t SMI_CommandPort; - uint8_t AcpiEnable; - uint8_t AcpiDisable; - uint8_t S4BIOS_REQ; - uint8_t PSTATE_Control; - uint32_t PM1aEventBlock; - uint32_t PM1bEventBlock; - uint32_t PM1aControlBlock; - uint32_t PM1bControlBlock; - uint32_t PM2ControlBlock; - uint32_t PMTimerBlock; - uint32_t GPE0Block; - uint32_t GPE1Block; - uint8_t PM1EventLength; - uint8_t PM1ControlLength; - uint8_t PM2ControlLength; - uint8_t PMTimerLength; - uint8_t GPE0Length; - uint8_t GPE1Length; - uint8_t GPE1Base; - uint8_t CStateControl; - uint16_t WorstC2Latency; - uint16_t WorstC3Latency; - uint16_t FlushSize; - uint16_t FlushStride; - uint8_t DutyOffset; - uint8_t DutyWidth; - uint8_t DayAlarm; - uint8_t MonthAlarm; - uint8_t Century; - - uint16_t BootArchitectureFlags; - - uint8_t Reserved2; - uint32_t Flags; - - GenericAddressStructure ResetReg; - - uint8_t ResetValue; - uint8_t Reserved3[3]; - - uint64_t X_FirmwareControl; - uint64_t X_Dsdt; - - GenericAddressStructure X_PM1aEventBlock; - GenericAddressStructure X_PM1bEventBlock; - GenericAddressStructure X_PM1aControlBlock; - GenericAddressStructure X_PM1bControlBlock; - GenericAddressStructure X_PM2ControlBlock; - GenericAddressStructure X_PMTimerBlock; - GenericAddressStructure X_GPE0Block; - GenericAddressStructure X_GPE1Block; - }; -} \ No newline at end of file diff --git a/kernel/include/acpi/RSDT.h b/kernel/include/acpi/RSDT.h deleted file mode 100644 index 9e136cb7..00000000 --- a/kernel/include/acpi/RSDT.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "acpi/SDT.h" - -namespace ACPI -{ - struct XSDT - { - SDTHeader header; - uint64_t other_sdt[1]; - }; - - struct RSDT - { - SDTHeader header; - uint32_t other_sdt[1]; - }; - - SDTHeader* get_rsdt_or_xsdt(); - - bool validate_rsdt_or_xsdt(SDTHeader* root_sdt); - - bool is_xsdt(); - - void* find_table(SDTHeader* root_sdt, const char* signature); -} \ No newline at end of file diff --git a/kernel/include/acpi/SDT.h b/kernel/include/acpi/SDT.h deleted file mode 100644 index b757203c..00000000 --- a/kernel/include/acpi/SDT.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include - -namespace ACPI -{ - struct SDTHeader - { - char Signature[4]; - uint32_t Length; - uint8_t Revision; - uint8_t Checksum; - char OEMID[6]; - char OEMTableID[8]; - uint32_t OEMRevision; - uint32_t CreatorID; - uint32_t CreatorRevision; - }; - - bool validate_sdt_header(SDTHeader* header); -} \ No newline at end of file diff --git a/kernel/include/bootboot.h b/kernel/include/bootboot.h deleted file mode 100644 index 8ac1207e..00000000 --- a/kernel/include/bootboot.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * bootboot.h - * https://gitlab.com/bztsrc/bootboot - * - * Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * This file is part of the BOOTBOOT Protocol package. - * @brief The BOOTBOOT structure - * - */ - -#ifndef _BOOTBOOT_H_ -#define _BOOTBOOT_H_ - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif -#ifndef _MSC_VER -#define _pack __attribute__((packed)) -#else -#define _pack -#pragma pack(push) -#pragma pack(1) -#endif - -#define BOOTBOOT_MAGIC "BOOT" - -/* default virtual addresses for level 0 and 1 static loaders */ -#define BOOTBOOT_MMIO 0xfffffffff8000000 /* memory mapped IO virtual address */ -#define BOOTBOOT_FB 0xfffffffffc000000 /* frame buffer virtual address */ -#define BOOTBOOT_INFO 0xffffffffffe00000 /* bootboot struct virtual address */ -#define BOOTBOOT_ENV 0xffffffffffe01000 /* environment string virtual address */ -#define BOOTBOOT_CORE 0xffffffffffe02000 /* core loadable segment start */ - -/* minimum protocol level: - * hardcoded kernel name, static kernel memory addresses */ -#define PROTOCOL_MINIMAL 0 -/* static protocol level: - * kernel name parsed from environment, static kernel memory addresses */ -#define PROTOCOL_STATIC 1 -/* dynamic protocol level: - * kernel name parsed, kernel memory addresses from ELF or PE symbols */ -#define PROTOCOL_DYNAMIC 2 -/* big-endian flag */ -#define PROTOCOL_BIGENDIAN 0x80 - -/* loader types, just informational */ -#define LOADER_BIOS (0 << 2) -#define LOADER_UEFI (1 << 2) -#define LOADER_RPI (2 << 2) -#define LOADER_COREBOOT (3 << 2) - -/* framebuffer pixel format, only 32 bits supported */ -#define FB_ARGB 0 -#define FB_RGBA 1 -#define FB_ABGR 2 -#define FB_BGRA 3 - - /* mmap entry, type is stored in least significant tetrad (half byte) of size - * this means size described in 16 byte units (not a problem, most modern - * firmware report memory in pages, 4096 byte units anyway). */ - typedef struct - { - uint64_t ptr; - uint64_t size; - } _pack MMapEnt; -#define MMapEnt_Ptr(a) ((a)->ptr) -#define MMapEnt_Size(a) ((a)->size & 0xFFFFFFFFFFFFFFF0) -#define MMapEnt_Type(a) ((a)->size & 0xF) -#define MMapEnt_IsFree(a) (((a)->size & 0xF) == 1) - -#define MMAP_USED 0 /* don't use. Reserved or unknown regions */ -#define MMAP_FREE 1 /* usable memory */ -#define MMAP_ACPI 2 /* acpi memory, volatile and non-volatile as well */ -#define MMAP_MMIO 3 /* memory mapped IO region */ - -#define INITRD_MAXSIZE 16 /* Mb */ - - typedef struct - { - /* first 64 bytes is platform independent */ - uint8_t magic[4]; /* 'BOOT' magic */ - uint32_t size; /* length of bootboot structure, minimum 128 */ - uint8_t protocol; /* 1, static addresses, see PROTOCOL_* and LOADER_* above */ - uint8_t fb_type; /* framebuffer type, see FB_* above */ - uint16_t numcores; /* number of processor cores */ - uint16_t bspid; /* Bootsrap processor ID (Local APIC Id on x86_64) */ - int16_t timezone; /* in minutes -1440..1440 */ - uint8_t datetime[8]; /* in BCD yyyymmddhhiiss UTC (independent to timezone) */ - uint64_t initrd_ptr; /* ramdisk image position and size */ - uint64_t initrd_size; - uint64_t fb_ptr; /* framebuffer pointer and dimensions */ - uint32_t fb_size; - uint32_t fb_width; - uint32_t fb_height; - uint32_t fb_scanline; - - /* the rest (64 bytes) is platform specific */ - union { - struct - { - uint64_t acpi_ptr; - uint64_t smbi_ptr; - uint64_t efi_ptr; - uint64_t mp_ptr; - uint64_t unused0; - uint64_t unused1; - uint64_t unused2; - uint64_t unused3; - } x86_64; - struct - { - uint64_t acpi_ptr; - uint64_t mmio_ptr; - uint64_t efi_ptr; - uint64_t unused0; - uint64_t unused1; - uint64_t unused2; - uint64_t unused3; - uint64_t unused4; - } aarch64; - } arch; - - /* from 128th byte, MMapEnt[], more records may follow */ - MMapEnt mmap; - /* use like this: - * MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++; - * until you reach bootboot->size, while(mmap_ent < bootboot + bootboot->size) */ - } _pack BOOTBOOT; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/kernel/include/config.h b/kernel/include/config.h deleted file mode 100644 index f59a47e0..00000000 --- a/kernel/include/config.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -int __moon_version_major(); -int __moon_version_minor(); -const char* __moon_version_suffix(); - -const char* moon_version(); \ No newline at end of file diff --git a/kernel/include/cpu/CPU.h b/kernel/include/cpu/CPU.h deleted file mode 100644 index 81b0ef83..00000000 --- a/kernel/include/cpu/CPU.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "cpu/Features.h" -#include - -namespace CPU -{ - const char* get_vendor_string(); - const char* get_brand_string(); - void log_cpu_information(); - uint64_t get_feature_bitmask(); - uint64_t get_initial_apic_id(); - bool has_feature(CPU::Features); - bool has_nx(); -} \ No newline at end of file diff --git a/kernel/include/cpu/Features.h b/kernel/include/cpu/Features.h deleted file mode 100644 index c5e99053..00000000 --- a/kernel/include/cpu/Features.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -namespace CPU -{ - enum class Features - { - FPU, - VME, - DE, - PSE, - TSC, - MSR, - PAE, - MCE, - CX8, - APIC, - UNUSED1, - SEP, - MTRR, - PGE, - MCA, - CMOV, - PAT, - PSE36, - PSN, - CLFLUSH, - UNUSED2, - DS, - ACPI, - MMX, - FXSR, - SSE, - SSE2, - SS, - HTT, - TM, - IA64, - PBE, - SSE3, - PCLMUL, - DTES64, - MONITOR, - DS_CPL, - VMX, - SMX, - EST, - TM2, - SSSE3, - CID, - SDBG, - FMA, - CX16, - XTPR, - PDCM, - UNUSED3, - PCID, - DCA, - SSE4_1, - SSE4_2, - X2APIC, - MOVBE, - POPCNT, - TSC_2, - AES, - XSAVE, - OSXSAVE, - AVX, - F16C, - RDRAND, - HYPERVISOR, - }; -} \ No newline at end of file diff --git a/kernel/include/font.h b/kernel/include/font.h deleted file mode 100644 index 1122471f..00000000 --- a/kernel/include/font.h +++ /dev/null @@ -1,260 +0,0 @@ -#pragma once - -unsigned char font[] = { - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, /* 2 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 */ - 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 11 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 12 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 13 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 14 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 15 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 17 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 21 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 22 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 24 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 25 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 26 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 27 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 29 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 30 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32 */ - 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 33 */ - 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 34 */ - 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, /* 35 */ - 0x00, 0x00, 0x08, 0x08, 0x1e, 0x20, 0x20, 0x1c, 0x02, 0x02, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 36 */ - 0x00, 0x00, 0x00, 0x30, 0x49, 0x4a, 0x34, 0x08, 0x16, 0x29, 0x49, 0x06, 0x00, 0x00, 0x00, 0x00, /* 37 */ - 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x31, 0x49, 0x46, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, /* 38 */ - 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ - 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, /* 40 */ - 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, /* 41 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 */ - 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 43 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 44 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 45 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 46 */ - 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, /* 47 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 48 */ - 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 49 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 50 */ - 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x1c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 51 */ - 0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* 52 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 53 */ - 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 54 */ - 0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 55 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 56 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* 57 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 58 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 59 */ - 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, /* 60 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 61 */ - 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, /* 62 */ - 0x00, 0x00, 0x3c, 0x42, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 63 */ - 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4f, 0x51, 0x51, 0x51, 0x53, 0x4d, 0x40, 0x20, 0x1f, 0x00, 0x00, /* 64 */ - 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 65 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 66 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 67 */ - 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x00, /* 68 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 69 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 70 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x46, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 71 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 72 */ - 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 73 */ - 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 74 */ - 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 75 */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 76 */ - 0x00, 0x00, 0x00, 0x41, 0x63, 0x55, 0x49, 0x49, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 77 */ - 0x00, 0x00, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 78 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 79 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 80 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x04, 0x02, 0x00, 0x00, /* 81 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 82 */ - 0x00, 0x00, 0x00, 0x3e, 0x40, 0x40, 0x20, 0x18, 0x04, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 83 */ - 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 84 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 85 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 86 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x41, 0x49, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 87 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 88 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 89 */ - 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 90 */ - 0x00, 0x00, 0x1e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x00, 0x00, /* 91 */ - 0x00, 0x00, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* 92 */ - 0x00, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, 0x00, /* 93 */ - 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 94 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, /* 95 */ - 0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 96 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 97 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 98 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 99 */ - 0x00, 0x00, 0x02, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 100 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 101 */ - 0x00, 0x00, 0x0e, 0x10, 0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 102 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 103 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 104 */ - 0x00, 0x00, 0x08, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 105 */ - 0x00, 0x00, 0x04, 0x04, 0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x00, /* 106 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 107 */ - 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 108 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, /* 109 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 110 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 111 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, /* 112 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, /* 113 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, /* 114 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 115 */ - 0x00, 0x00, 0x00, 0x10, 0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 116 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 117 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 118 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 119 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, /* 120 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 121 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 122 */ - 0x00, 0x0e, 0x10, 0x10, 0x10, 0x10, 0x10, 0xe0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, /* 123 */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 124 */ - 0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, /* 125 */ - 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 126 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 127 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 129 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 130 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 131 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 132 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 133 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 134 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 135 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 136 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 137 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 138 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 139 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 140 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 141 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 142 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 143 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 144 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 145 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 146 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 147 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 148 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 149 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 150 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 151 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 152 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 153 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 154 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 155 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 156 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 157 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 158 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 159 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 160 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /* 161 */ - 0x00, 0x00, 0x08, 0x08, 0x1c, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 162 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 163 */ - 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x24, 0x24, 0x3c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* 164 */ - 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x3e, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 165 */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 166 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 167 */ - 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 168 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4d, 0x51, 0x51, 0x4d, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 169 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 170 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x12, 0x24, 0x48, 0x24, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, /* 171 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 172 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 173 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 174 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 175 */ - 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 176 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 177 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 178 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 179 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 180 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 181 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 182 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 183 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x30, 0x00, /* 184 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 185 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 186 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x09, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, /* 187 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 189 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 190 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x42, 0x3c, 0x00, /* 191 */ - 0x20, 0x10, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 192 */ - 0x04, 0x08, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 193 */ - 0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 194 */ - 0x32, 0x4c, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 195 */ - 0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 196 */ - 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 197 */ - 0x00, 0x00, 0x00, 0x0f, 0x14, 0x14, 0x24, 0x27, 0x3c, 0x44, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00, /* 198 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e, 0x08, 0x08, 0x30, 0x00, /* 199 */ - 0x20, 0x10, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 200 */ - 0x04, 0x08, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 201 */ - 0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 202 */ - 0x24, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 203 */ - 0x10, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 204 */ - 0x04, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 205 */ - 0x18, 0x24, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 206 */ - 0x22, 0x22, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 207 */ - 0x00, 0x00, 0x00, 0x3c, 0x22, 0x21, 0x21, 0x79, 0x21, 0x21, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 208 */ - 0x32, 0x4c, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 209 */ - 0x10, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 210 */ - 0x04, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 211 */ - 0x18, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 212 */ - 0x32, 0x4c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 213 */ - 0x24, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 214 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 215 */ - 0x00, 0x00, 0x02, 0x3c, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 216 */ - 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 217 */ - 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 218 */ - 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 219 */ - 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 220 */ - 0x04, 0x08, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 221 */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 222 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x44, 0x4c, 0x42, 0x42, 0x42, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* 223 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 224 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 225 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 226 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 227 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 228 */ - 0x18, 0x24, 0x24, 0x18, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 229 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09, 0x39, 0x4f, 0x48, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, /* 230 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, /* 231 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 232 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 233 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 234 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 235 */ - 0x00, 0x00, 0x10, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 236 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 237 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 238 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 239 */ - 0x00, 0x09, 0x06, 0x1a, 0x01, 0x1d, 0x23, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 240 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 241 */ - 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 242 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 243 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 244 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 245 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 246 */ - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 247 */ - 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 248 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 249 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 250 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 251 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 252 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 253 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x00, /* 254 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, - /* 255 */}; \ No newline at end of file diff --git a/kernel/include/fs/FileDescriptor.h b/kernel/include/fs/FileDescriptor.h deleted file mode 100644 index 9e34df83..00000000 --- a/kernel/include/fs/FileDescriptor.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once -#include "fs/VFS.h" -#include - -struct Descriptor -{ - bool is_open() - { - return m_is_open; - } - - bool can_read() - { - return m_can_read && m_is_open; - } - - bool can_write() - { - return m_can_write && m_is_open; - } - - void close() - { - m_is_open = false; - } - - VFS::Node* node() - { - return m_node; - } - - ssize_t read(size_t size, char* buffer); - ssize_t write(size_t size, const char* buffer); - - ssize_t user_read(size_t size, char* buffer); - ssize_t user_write(size_t size, const char* buffer); - - uintptr_t mmap(uintptr_t addr, size_t size, int prot, off_t offset); - - long ioctl(int cmd, uintptr_t arg); - - void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec); - - int seek(long offset); - long offset() - { - return (long)m_offset; - } - - unsigned long length() - { - return m_node->length; - } - - bool able_to_block() - { - return m_able_to_block; - } - - bool close_on_exec() - { - return m_close_on_exec; - } - - void set_close_on_exec(bool value) - { - m_close_on_exec = value; - } - - Descriptor(const Descriptor& other); - Descriptor(); - - const Descriptor& operator=(const Descriptor& other); - - private: - bool m_is_open; - bool m_can_read; - bool m_can_write; - bool m_able_to_block; - bool m_close_on_exec; - VFS::Node* m_node; - uint64_t m_offset; -}; \ No newline at end of file diff --git a/kernel/include/fs/InitRD.h b/kernel/include/fs/InitRD.h deleted file mode 100644 index d0ce7b42..00000000 --- a/kernel/include/fs/InitRD.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include -#include - -#define TAR_MAGIC "ustar" -#define TAR_BLOCKSIZE 512 - -namespace InitRD -{ - struct TarHeader - { /* byte offset */ - char name[100]; /* 0 */ - char mode[8]; /* 100 */ - char uid[8]; /* 108 */ - char gid[8]; /* 116 */ - char size[12]; /* 124 */ - char mtime[12]; /* 136 */ - char chksum[8]; /* 148 */ - char typeflag; /* 156 */ - char linkname[100]; /* 157 */ - char magic[6]; /* 257 */ - char version[2]; /* 263 */ - char uname[32]; /* 265 */ - char gname[32]; /* 297 */ - char devmajor[8]; /* 329 */ - char devminor[8]; /* 337 */ - char prefix[155]; /* 345 */ - /* 500 */ - } __attribute__((packed)); - - struct File - { - char name[100]; - uint64_t size; - uint64_t size_in_blocks; - void* addr; - mode_t mode; - }; - - uint64_t get_total_blocks(); - File get_file(TarHeader* header); - void free_file(File& file); - TarHeader* get_block(uint64_t block_index); - bool is_valid_header(TarHeader* header); - - uint64_t get_file_physical_address(File& file); - - File open(const char* filename); - void for_each(void (*callback)(File& file)); - - bool is_initialized(); - - void init(); -} \ No newline at end of file diff --git a/kernel/include/fs/TmpFS.h b/kernel/include/fs/TmpFS.h deleted file mode 100644 index cb79f37a..00000000 --- a/kernel/include/fs/TmpFS.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "fs/VFS.h" - -namespace TmpFS -{ - VFS::Node* get(); - - VFS::Node* finddir(VFS::Node* node, const char* filename); - VFS::Node* readdir(VFS::Node* node, long offset); - - int mkdir(VFS::Node* node, const char* name, mode_t mode); - - ssize_t read(VFS::Node* node, size_t offset, size_t length, char* buffer); - ssize_t write(VFS::Node* node, size_t offset, size_t length, const char* buffer); - - VFS::Node* create(VFS::Node* node, const char* name, mode_t mode, uid_t uid, gid_t gid); -} \ No newline at end of file diff --git a/kernel/include/fs/VFS.h b/kernel/include/fs/VFS.h deleted file mode 100644 index 410c9ec7..00000000 --- a/kernel/include/fs/VFS.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -#include "utils/Result.h" -#include -#include -#include - -typedef long ssize_t; - -#define VFS_FILE 0x0 -#define VFS_DIRECTORY 0x1 -#define VFS_DEVICE 0x2 - -#define VFS_MOUNTPOINT 0x1 - -#define NAME_MAX 64 - -namespace VFS -{ - struct Node; - - typedef ssize_t (*node_read)(Node*, size_t, size_t, char*); - typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*); - typedef Node* (*node_finddir)(Node*, const char*); - typedef int (*node_mkdir)(Node*, const char*, mode_t); - typedef int (*node_block)(Node*); - typedef Node* (*node_readdir)(Node*, long); - typedef uintptr_t (*node_mmap)(Node*, uintptr_t, size_t, int, off_t); - typedef long (*node_ioctl)(Node*, int, uintptr_t); - typedef Node* (*node_create)(Node*, const char*, mode_t, uid_t, gid_t); - - struct Node - { - char name[NAME_MAX]; - int type; - int flags; - int tty = 0; - int uid; - int gid; - mode_t mode; - uint64_t impl; - uint64_t atime; - uint64_t ctime; - uint64_t mtime; - uint64_t inode; - uint64_t length; - node_read read_func; - node_finddir find_func; - node_readdir readdir_func; - node_mkdir mkdir_func; - node_write write_func; - node_block block_func; - node_mmap mmap_func; - node_ioctl ioctl_func; - node_create create_func; - Node* link; - }; - - ssize_t read(Node* node, size_t offset, size_t length, char* buffer); - ssize_t write(Node* node, size_t offset, size_t length, const char* buffer); - int mkdir(const char* path, const char* name); - int mkdir(const char* pathname); - - int do_mkdir(const char* path, const char* name, int uid, int gid, mode_t mode); - int do_mkdir(const char* pathname, int uid, int gid, mode_t mode); - - Result create(const char* pathname, mode_t mode, uid_t uid, gid_t gid); - - int would_block(Node* node); - - void mount_root(Node* root); - - Node* resolve_path(const char* filename, Node* root = nullptr); - Node* resolve_parent(const char* filename, Node* root = nullptr); - - bool exists(const char* pathname); - - void mount(Node* mountpoint, Node* mounted); - void mount(const char* pathname, Node* mounted); - - void unmount(Node* mountpoint); - - Node* root(); - - Node* readdir(Node* dir, long offset); - - bool can_execute(Node* node, int uid, int gid); - bool can_read(Node* node, int uid, int gid); - bool can_write(Node* node, int uid, int gid); - - bool is_setuid(Node* node); - bool is_setgid(Node* node); -} \ No newline at end of file diff --git a/kernel/include/fs/devices/Console.h b/kernel/include/fs/devices/Console.h deleted file mode 100644 index aef42b14..00000000 --- a/kernel/include/fs/devices/Console.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "fs/VFS.h" - -namespace ConsoleDevice -{ - VFS::Node* create_new(const char* devname); - - ssize_t write(VFS::Node* node, size_t offset, size_t size, const char* buffer); - - ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); - - int would_block(VFS::Node* node); - - void append(char c); -} \ No newline at end of file diff --git a/kernel/include/fs/devices/DeviceFS.h b/kernel/include/fs/devices/DeviceFS.h deleted file mode 100644 index d6a37998..00000000 --- a/kernel/include/fs/devices/DeviceFS.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "fs/VFS.h" - -namespace DeviceFS -{ - VFS::Node* get(); - - VFS::Node* finddir(VFS::Node* node, const char* filename); - VFS::Node* readdir(VFS::Node* node, long offset); -} \ No newline at end of file diff --git a/kernel/include/fs/devices/Framebuffer.h b/kernel/include/fs/devices/Framebuffer.h deleted file mode 100644 index 32b2a04f..00000000 --- a/kernel/include/fs/devices/Framebuffer.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "fs/VFS.h" - -namespace FramebufferDevice -{ - VFS::Node* create_new(const char* devname); - - ssize_t write(VFS::Node* node, size_t offset, size_t size, const char* buffer); - - uintptr_t mmap(VFS::Node* node, uintptr_t addr, size_t size, int prot, off_t offset); - - long ioctl(VFS::Node* node, int cmd, uintptr_t arg); -} \ No newline at end of file diff --git a/kernel/include/fs/devices/Keyboard.h b/kernel/include/fs/devices/Keyboard.h deleted file mode 100644 index 3dc30575..00000000 --- a/kernel/include/fs/devices/Keyboard.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "fs/VFS.h" - -namespace KeyboardDevice -{ - VFS::Node* create_new(const char* devname); - - ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); - - int would_block(VFS::Node* node); - - void append(char c); -} \ No newline at end of file diff --git a/kernel/include/fs/devices/NullDevice.h b/kernel/include/fs/devices/NullDevice.h deleted file mode 100644 index 5c264fcd..00000000 --- a/kernel/include/fs/devices/NullDevice.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "fs/VFS.h" - -namespace NullDevice -{ - VFS::Node* create_new(const char* devname); - - ssize_t write(VFS::Node* node, size_t offset, size_t size, const char* buffer); - ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); -} \ No newline at end of file diff --git a/kernel/include/fs/devices/Random.h b/kernel/include/fs/devices/Random.h deleted file mode 100644 index 916ba0c4..00000000 --- a/kernel/include/fs/devices/Random.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "fs/VFS.h" - -namespace RandomDevice -{ - VFS::Node* create_new(const char* devname); - - ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); -} \ No newline at end of file diff --git a/kernel/include/fs/devices/Serial.h b/kernel/include/fs/devices/Serial.h deleted file mode 100644 index 2f9728ca..00000000 --- a/kernel/include/fs/devices/Serial.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "fs/VFS.h" - -namespace SerialDevice -{ - VFS::Node* create_new(const char* devname); - - ssize_t write(VFS::Node* node, size_t offset, size_t size, const char* buffer); -} \ No newline at end of file diff --git a/kernel/include/fs/devices/Version.h b/kernel/include/fs/devices/Version.h deleted file mode 100644 index 72590515..00000000 --- a/kernel/include/fs/devices/Version.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "fs/VFS.h" - -namespace VersionDevice -{ - VFS::Node* create_new(const char* devname); - - ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); -} \ No newline at end of file diff --git a/kernel/include/gdt/GDT.h b/kernel/include/gdt/GDT.h deleted file mode 100644 index 297199ad..00000000 --- a/kernel/include/gdt/GDT.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace GDT -{ - void load(); -} \ No newline at end of file diff --git a/kernel/include/init/Init.h b/kernel/include/init/Init.h deleted file mode 100644 index 0870c600..00000000 --- a/kernel/include/init/Init.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -namespace Init -{ - void check_magic(); - void disable_smp(); - void early_init(); - void finish_kernel_boot(); -} \ No newline at end of file diff --git a/kernel/include/interrupts/Context.h b/kernel/include/interrupts/Context.h deleted file mode 100644 index 41f60847..00000000 --- a/kernel/include/interrupts/Context.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include - -struct Context -{ - uint64_t cr2, ds; - uint64_t r15, r14, r13, r12, r11, r10, r9, r8, rsi, rdi, rbp, rdx, rcx, rbx, rax; - uint64_t number; - union { - uint64_t error_code; - uint64_t irq_number; - }; - uint64_t rip, cs, rflags, rsp, ss; -}; \ No newline at end of file diff --git a/kernel/include/interrupts/IDT.h b/kernel/include/interrupts/IDT.h deleted file mode 100644 index edded58e..00000000 --- a/kernel/include/interrupts/IDT.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include - -#define IDT_TA_InterruptGate 0b10001110 -#define IDT_TA_InterruptGateUser 0b11101110 -#define IDT_TA_TrapGate 0b10001111 - -struct IDTR -{ - uint16_t limit; - uint64_t offset; -} __attribute__((packed)); - -namespace IDT -{ - void add_handler(short interrupt_number, void* handler, uint8_t type_attr); - void load(); -} \ No newline at end of file diff --git a/kernel/include/interrupts/IRQ.h b/kernel/include/interrupts/IRQ.h deleted file mode 100644 index a61540ce..00000000 --- a/kernel/include/interrupts/IRQ.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include "Context.h" - -namespace IRQ -{ - void interrupt_handler(Context* context); -} \ No newline at end of file diff --git a/kernel/include/interrupts/Install.h b/kernel/include/interrupts/Install.h deleted file mode 100644 index 18d985b2..00000000 --- a/kernel/include/interrupts/Install.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include - -namespace Interrupts -{ - void install(); -} \ No newline at end of file diff --git a/kernel/include/interrupts/Interrupts.h b/kernel/include/interrupts/Interrupts.h deleted file mode 100644 index e5e5b26f..00000000 --- a/kernel/include/interrupts/Interrupts.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "interrupts/Context.h" - -namespace Interrupts -{ - void enable(); - void disable(); - - bool is_in_handler(); - void return_from_handler(Context* context); - - bool are_enabled(); - bool were_enabled(); - void push_and_disable(); - void push_and_enable(); - void pop(); -} \ No newline at end of file diff --git a/kernel/include/io/IO.h b/kernel/include/io/IO.h deleted file mode 100644 index 883983ad..00000000 --- a/kernel/include/io/IO.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include - -namespace IO -{ - uint8_t inb(uint16_t); - void outb(uint16_t, uint8_t); - uint16_t inw(uint16_t); - void outw(uint16_t, uint16_t); - uint32_t inl(uint16_t); - void outl(uint16_t, uint32_t); - void delay(); -} \ No newline at end of file diff --git a/kernel/include/io/PCI.h b/kernel/include/io/PCI.h deleted file mode 100644 index e5bea2e6..00000000 --- a/kernel/include/io/PCI.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include - -#define PCI_VENDOR_FIELD 0x0 -#define PCI_DEVICE_FIELD 0x2 -#define PCI_SUBCLASS_FIELD 0xa -#define PCI_CLASS_FIELD 0xb -#define PCI_REVISION_ID_FIELD 0x8 -#define PCI_PROG_IF_FIELD 0x9 -#define PCI_HEADER_TYPE_FIELD 0xe -#define PCI_SECONDARY_BUS_NUMBER_FIELD 0x19 -#define PCI_BAR0_FIELD 0x10 -#define PCI_BAR1_FIELD 0x14 -#define PCI_BAR2_FIELD 0x18 -#define PCI_BAR3_FIELD 0x1C -#define PCI_BAR4_FIELD 0x20 -#define PCI_BAR5_FIELD 0x24 - -namespace PCI -{ - struct DeviceID - { - uint16_t vendor; - uint16_t device; - }; - - struct DeviceType - { - uint8_t dev_class; - uint8_t dev_subclass; - uint8_t prog_if; - uint8_t revision; - }; - - struct Device - { - void write8(int32_t offset, uint8_t value); - void write16(int32_t offset, uint16_t value); - void write32(int32_t offset, uint32_t value); - uint8_t read8(int32_t offset); - uint16_t read16(int32_t offset); - uint32_t read32(int32_t offset); - - uint32_t getBAR0(); - uint32_t getBAR1(); - uint32_t getBAR2(); - uint32_t getBAR3(); - uint32_t getBAR4(); - uint32_t getBAR5(); - - uint8_t bus() - { - return m_bus; - } - - uint8_t slot() - { - return m_slot; - } - - uint8_t function() - { - return m_function; - } - - DeviceID id() - { - return m_id; - } - - DeviceType type() - { - return m_type; - } - - Device(DeviceID id, DeviceType type, uint8_t bus, uint8_t slot, uint8_t function); - Device(uint8_t bus, uint8_t slot, uint8_t function); - Device(const Device& other); - - private: - DeviceID m_id; - DeviceType m_type; - uint8_t m_bus; - uint8_t m_slot; - uint8_t m_function; - }; - - uint32_t raw_address(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset); - void raw_write8(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint8_t value); - void raw_write16(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint16_t value); - void raw_write32(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint32_t value); - uint8_t raw_read8(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset); - uint16_t raw_read16(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset); - uint32_t raw_read32(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset); - DeviceID get_device_id(uint32_t bus, uint32_t slot, uint32_t function); - DeviceType get_device_type(uint32_t bus, uint32_t slot, uint32_t function); - void scan(void (*callback)(PCI::Device&)); -} \ No newline at end of file diff --git a/kernel/include/io/PIC.h b/kernel/include/io/PIC.h deleted file mode 100644 index 1aaf6079..00000000 --- a/kernel/include/io/PIC.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -namespace PIC -{ - void remap(); - void end_slave(); - void end_master(); - void enable_master(uint8_t mask); - void enable_slave(uint8_t mask); - void send_eoi(unsigned char irq); -} \ No newline at end of file diff --git a/kernel/include/io/Serial.h b/kernel/include/io/Serial.h deleted file mode 100644 index 9d371563..00000000 --- a/kernel/include/io/Serial.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "render/Color.h" -#include - -namespace Serial -{ - void wait(); - void write(const char* string, size_t size); - void print(const char* string); - void println(const char* string); - void set_color(Color& color); - void reset_color(); -} \ No newline at end of file diff --git a/kernel/include/log/CLog.h b/kernel/include/log/CLog.h deleted file mode 100644 index 0c02696a..00000000 --- a/kernel/include/log/CLog.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _MOON_CLOG_H -#define _MOON_CLOG_H - -enum log_level -{ - LOG_DEBUG, - LOG_INFO, - LOG_WARN, - LOG_ERROR -}; - -#define PRINTF_LIKE(n, m) __attribute__((format(printf, n, m))) - -#ifdef __cplusplus -extern "C" -{ -#endif - - void clog_log(const char* function, enum log_level level, const char* message, ...) PRINTF_LIKE(3, 4); - void clog_logln(const char* function, enum log_level level, const char* message, ...) PRINTF_LIKE(3, 4); - -#ifdef __cplusplus -} -#endif - -#ifndef MODULE -#define kcommonlog(function, level, ...) clog_##function(__FUNCTION__, level, __VA_ARGS__) -#else -#define kcommonlog(function, level, ...) clog_##function(MODULE, level, __VA_ARGS__) -#endif - -#define kdbg(...) kcommonlog(log, LOG_DEBUG, __VA_ARGS__) -#define kdbgln(...) kcommonlog(logln, LOG_DEBUG, __VA_ARGS__) -#define kinfo(...) kcommonlog(log, LOG_INFO, __VA_ARGS__) -#define kinfoln(...) kcommonlog(logln, LOG_INFO, __VA_ARGS__) -#define kwarn(...) kcommonlog(log, LOG_WARN, __VA_ARGS__) -#define kwarnln(...) kcommonlog(logln, LOG_WARN, __VA_ARGS__) -#define kerror(...) kcommonlog(log, LOG_ERROR, __VA_ARGS__) -#define kerrorln(...) kcommonlog(logln, LOG_ERROR, __VA_ARGS__) - -#endif \ No newline at end of file diff --git a/kernel/include/log/Log.h b/kernel/include/log/Log.h deleted file mode 100644 index f27dcb80..00000000 --- a/kernel/include/log/Log.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -enum class LogLevel -{ - DEBUG, - INFO, - WARN, - ERROR -}; - -enum class Backend -{ - Serial, - Console -}; - -#define PRINTF_LIKE(n, m) __attribute__((format(printf, n, m))) - -namespace KernelLog -{ - void log(const char* function, LogLevel level, const char* message, ...) PRINTF_LIKE(3, 4); - void logln(const char* function, LogLevel level, const char* message, ...) PRINTF_LIKE(3, 4); - void toggle_log_level(LogLevel level); - void toggle_log_backend(Backend backend); - void enable_log_backend(Backend backend); -} - -#ifndef MODULE -#define kcommonlog(function, level, ...) KernelLog::function(__FUNCTION__, level, __VA_ARGS__) -#else -#define kcommonlog(function, level, ...) KernelLog::function(MODULE, level, __VA_ARGS__) -#endif - -#define kdbg(...) kcommonlog(log, LogLevel::DEBUG, __VA_ARGS__) -#define kdbgln(...) kcommonlog(logln, LogLevel::DEBUG, __VA_ARGS__) -#define kinfo(...) kcommonlog(log, LogLevel::INFO, __VA_ARGS__) -#define kinfoln(...) kcommonlog(logln, LogLevel::INFO, __VA_ARGS__) -#define kwarn(...) kcommonlog(log, LogLevel::WARN, __VA_ARGS__) -#define kwarnln(...) kcommonlog(logln, LogLevel::WARN, __VA_ARGS__) -#define kerror(...) kcommonlog(log, LogLevel::ERROR, __VA_ARGS__) -#define kerrorln(...) kcommonlog(logln, LogLevel::ERROR, __VA_ARGS__) \ No newline at end of file diff --git a/kernel/include/memory/AddressSpace.h b/kernel/include/memory/AddressSpace.h deleted file mode 100644 index c125b0a0..00000000 --- a/kernel/include/memory/AddressSpace.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "memory/Paging.h" -#include "utils/Result.h" - -struct AddressSpace -{ - static Result create(); - - void destroy(); - - void clear(); - - AddressSpace clone(); - - PageTable* get_pml4() - { - return m_pml4; - } - - private: - PageTable* m_pml4; -}; \ No newline at end of file diff --git a/kernel/include/memory/KernelHeap.h b/kernel/include/memory/KernelHeap.h deleted file mode 100644 index 5dc14d64..00000000 --- a/kernel/include/memory/KernelHeap.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include - -namespace KernelHeap -{ // Virtual memory allocator for the kernel, goes from -128MB to -64MB - uint64_t request_virtual_page(); - uint64_t request_virtual_pages(uint64_t count); - - void free_virtual_page(uint64_t address); - void free_virtual_pages(uint64_t address, uint64_t count); - - void clear(); - - void dump_usage(); -} \ No newline at end of file diff --git a/kernel/include/memory/Memory.h b/kernel/include/memory/Memory.h deleted file mode 100644 index aa5aebf3..00000000 --- a/kernel/include/memory/Memory.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include - -namespace Memory -{ - uint64_t get_system(); - uint64_t get_usable(); - - bool is_user_address(uintptr_t address); - bool is_kernel_address(uintptr_t address); -} \ No newline at end of file diff --git a/kernel/include/memory/MemoryManager.h b/kernel/include/memory/MemoryManager.h deleted file mode 100644 index 3cecf2ae..00000000 --- a/kernel/include/memory/MemoryManager.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include "utils/Result.h" -#include - -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - -#define MAP_READ_WRITE 1 << 0 -#define MAP_USER 1 << 1 -#define MAP_EXEC 1 << 2 -#define MAP_AS_OWNED_BY_TASK 1 << 3 - -namespace MemoryManager -{ - void init(); - - void protect_kernel_sections(); - - Result get_mapping(void* physicalAddress, int flags = MAP_READ_WRITE); - void release_mapping(void* mapping); - - Result get_unaligned_mapping(void* physicalAddress, int flags = MAP_READ_WRITE); - Result get_unaligned_mappings(void* physicalAddress, uint64_t count, int flags = MAP_READ_WRITE); - void release_unaligned_mapping(void* mapping); - void release_unaligned_mappings(void* mapping, uint64_t count); - - Result get_page(int flags = MAP_READ_WRITE); - Result get_pages(uint64_t count, int flags = MAP_READ_WRITE); - - Result get_page_at(uint64_t addr, int flags = MAP_READ_WRITE); - Result get_pages_at(uint64_t addr, uint64_t count, int flags = MAP_READ_WRITE); - - void release_page(void* page); - void release_pages(void* pages, uint64_t count); - - void protect(void* page, uint64_t count, int flags); - - void map_several_pages(uint64_t physicalAddress, uint64_t virtualAddress, uint64_t count, - int flags = MAP_READ_WRITE); -} \ No newline at end of file diff --git a/kernel/include/memory/MemoryMap.h b/kernel/include/memory/MemoryMap.h deleted file mode 100644 index c2714dc1..00000000 --- a/kernel/include/memory/MemoryMap.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace Memory -{ - void walk_memory_map(); -} \ No newline at end of file diff --git a/kernel/include/memory/PMM.h b/kernel/include/memory/PMM.h deleted file mode 100644 index 83d4482b..00000000 --- a/kernel/include/memory/PMM.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "utils/Result.h" -#include - -namespace PMM -{ - void init(); - - Result request_page(); - Result request_pages(uint64_t count); - - void free_page(void* address); - void free_pages(void* address, uint64_t count); - - void lock_page(void* address); - void lock_pages(void* address, uint64_t count); - - uint64_t get_free(); - uint64_t get_used(); - uint64_t get_reserved(); - - uint64_t get_bitmap_size(); - - void map_bitmap_to_virtual(); -}; diff --git a/kernel/include/memory/Paging.h b/kernel/include/memory/Paging.h deleted file mode 100644 index baedd9a3..00000000 --- a/kernel/include/memory/Paging.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include - -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - -struct PageDirectoryEntry -{ - bool present : 1; - bool read_write : 1; - bool user : 1; - bool write_through : 1; - bool cache_disabled : 1; - bool accessed : 1; - bool ignore0 : 1; - bool larger_pages : 1; - bool ignore1 : 1; - uint8_t available : 3; - uint64_t address : 48; - bool owned_by_task : 1; // Part of the available for OS use bits. - uint8_t available2 : 2; - bool no_execute : 1; - - void set_address(uint64_t addr); - uint64_t get_address(); -} __attribute__((packed)); - -struct PageTable -{ - PageDirectoryEntry entries[512]; -} __attribute__((aligned(PAGE_SIZE))); - -static_assert(sizeof(PageDirectoryEntry) == 8UL); \ No newline at end of file diff --git a/kernel/include/memory/UserHeap.h b/kernel/include/memory/UserHeap.h deleted file mode 100644 index 166c6a5c..00000000 --- a/kernel/include/memory/UserHeap.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include - -struct UserHeap -{ - bool init(); - - uint64_t request_virtual_page(); - uint64_t request_virtual_pages(uint64_t count); - - void free_virtual_page(uint64_t address); - void free_virtual_pages(uint64_t address, uint64_t count); - - void free(); - - bool inherit(UserHeap& other); - - private: - uint8_t* bitmap = nullptr; - uint64_t bitmap_size = 0; - uint64_t start_index = 0; - bool bitmap_read(uint64_t index); - void bitmap_set(uint64_t index, bool value); - - bool try_expand(); - bool try_expand_size(uint64_t size); -}; \ No newline at end of file diff --git a/kernel/include/memory/VMM.h b/kernel/include/memory/VMM.h deleted file mode 100644 index ceb44ea2..00000000 --- a/kernel/include/memory/VMM.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include "memory/AddressSpace.h" -#include "memory/Paging.h" - -enum Flags -{ - ReadWrite = 1 << 0, - User = 1 << 1, - Execute = 1 << 2, - OwnedByTask = 1 << 3, -}; -namespace VMM -{ - void init(); // Fetch page table from cr3 - - void switch_to_user_address_space(AddressSpace& space); - void switch_to_previous_user_address_space(); - void switch_back_to_kernel_address_space(); - - void enter_syscall_context(); - void exit_syscall_context(); - - void apply_address_space(); - - bool is_using_kernel_address_space(); - - void map(uint64_t vaddr, uint64_t paddr, int flags); - void remap(uint64_t vaddr, int flags); - void unmap(uint64_t vaddr); - uint64_t get_physical(uint64_t vaddr); - uint64_t get_flags(uint64_t vaddr); - - PageDirectoryEntry* find_pde(PageTable* root, uint64_t vaddr); - PageDirectoryEntry* create_pde_if_not_exists(PageTable* root, uint64_t vaddr); - - void propagate_read_write(PageTable* root, uint64_t vaddr); - void propagate_no_execute(PageTable* root, uint64_t vaddr); - void propagate_user(PageTable* root, uint64_t vaddr); - - void flush_tlb(uint64_t addr); - void flush_tlb_full(); - - void decompose_vaddr(uint64_t vaddr, uint64_t& page_index, uint64_t& pt_index, uint64_t& pd_index, - uint64_t& pdp_index); - uint64_t recompose_vaddr(uint64_t page_index, uint64_t pt_index, uint64_t pd_index, uint64_t pdp_index); - - void install_kernel_page_directory_into_address_space(AddressSpace& space); -}; \ No newline at end of file diff --git a/kernel/include/memory/liballoc/liballoc.h b/kernel/include/memory/liballoc/liballoc.h deleted file mode 100644 index 0ad6274d..00000000 --- a/kernel/include/memory/liballoc/liballoc.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _LIBALLOC_H -#define _LIBALLOC_H - -#include - -/** \defgroup ALLOCHOOKS liballoc hooks - * - * These are the OS specific functions which need to - * be implemented on any platform that the library - * is expected to work on. - */ - -/** @{ */ - -// If we are told to not define our own size_t, then we skip the define. -//#define _HAVE_UINTPTR_T -// typedef unsigned long uintptr_t; - -// This lets you prefix malloc and friends -#define PREFIX(func) k##func - -#ifdef __cplusplus -extern "C" -{ -#endif -#ifndef __skip_bindings - /** This function is supposed to lock the memory data structures. It - * could be as simple as disabling interrupts or acquiring a spinlock. - * It's up to you to decide. - * - * \return 0 if the lock was acquired successfully. Anything else is - * failure. - */ - extern int liballoc_lock(); - - /** This function unlocks what was previously locked by the liballoc_lock - * function. If it disabled interrupts, it enables interrupts. If it - * had acquiried a spinlock, it releases the spinlock. etc. - * - * \return 0 if the lock was successfully released. - */ - extern int liballoc_unlock(); - - /** This is the hook into the local system which allocates pages. It - * accepts an integer parameter which is the number of pages - * required. The page size was set up in the liballoc_init function. - * - * \return NULL if the pages were not allocated. - * \return A pointer to the allocated memory. - */ - extern void* liballoc_alloc(size_t); - - /** This frees previously allocated memory. The void* parameter passed - * to the function is the exact same value returned from a previous - * liballoc_alloc call. - * - * The integer value is the number of pages to free. - * - * \return 0 if the memory was successfully freed. - */ - extern int liballoc_free(void*, size_t); -#endif - - extern void* PREFIX(malloc)(size_t); ///< The standard function. - extern void* PREFIX(realloc)(void*, size_t); ///< The standard function. - extern void* PREFIX(calloc)(size_t, size_t); ///< The standard function. - extern void PREFIX(free)(void*); ///< The standard function. - -#ifdef __cplusplus -} -#endif - -/** @} */ - -#endif \ No newline at end of file diff --git a/kernel/include/misc/MSR.h b/kernel/include/misc/MSR.h deleted file mode 100644 index 1c7ae4db..00000000 --- a/kernel/include/misc/MSR.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include - -#define IA32_EFER_MSR 0xC0000080 - -struct MSR -{ - void write(uint64_t value); - uint64_t read(); - - MSR(uint32_t msr_num); - - static void write_to(uint32_t msr_num, uint64_t value); - static uint64_t read_from(uint32_t msr_num); - - static void with_value_of(uint32_t msr_num, void (*callback)(uint64_t&)); - void with_value(void (*callback)(uint64_t&)); - - private: - uint32_t m_msr_num; -}; \ No newline at end of file diff --git a/kernel/include/misc/PCITypes.h b/kernel/include/misc/PCITypes.h deleted file mode 100644 index 4a537bf6..00000000 --- a/kernel/include/misc/PCITypes.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "io/PCI.h" - -const char* pci_type_name(PCI::DeviceType type); \ No newline at end of file diff --git a/kernel/include/misc/Scancodes.h b/kernel/include/misc/Scancodes.h deleted file mode 100644 index 439b2678..00000000 --- a/kernel/include/misc/Scancodes.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -// This should only be used for a keyboard TTY interface. Userspace should translate keyboard scancodes by themselves. -char translate_scancode(unsigned char scancode, bool* ignore); - -bool scancode_filter_released(unsigned char* scancode); \ No newline at end of file diff --git a/kernel/include/misc/hang.h b/kernel/include/misc/hang.h deleted file mode 100644 index 105c03a6..00000000 --- a/kernel/include/misc/hang.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -[[noreturn]] void hang(); -void halt(); \ No newline at end of file diff --git a/kernel/include/misc/reboot.h b/kernel/include/misc/reboot.h deleted file mode 100644 index e7de0de8..00000000 --- a/kernel/include/misc/reboot.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -[[noreturn]] void reboot(); \ No newline at end of file diff --git a/kernel/include/misc/shutdown.h b/kernel/include/misc/shutdown.h deleted file mode 100644 index 4c620652..00000000 --- a/kernel/include/misc/shutdown.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -[[noreturn]] void shutdown(); \ No newline at end of file diff --git a/kernel/include/misc/utils.h b/kernel/include/misc/utils.h deleted file mode 100644 index cc8974e5..00000000 --- a/kernel/include/misc/utils.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include - -namespace Utilities -{ - inline uint64_t get_blocks_from_size(uint64_t blocksize, uint64_t size) - { - return (size + (blocksize - 1)) / blocksize; - } -} \ No newline at end of file diff --git a/kernel/include/panic/Panic.h b/kernel/include/panic/Panic.h deleted file mode 100644 index 5c66799d..00000000 --- a/kernel/include/panic/Panic.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "interrupts/Context.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - [[noreturn]] bool __do_int_panic(Context* context, const char* file, int line, const char* message); - [[noreturn]] bool __do_panic(const char* file, int line, const char* message); -#ifdef __cplusplus -} -#endif - -#define panic(message) __do_panic(__FILE__, __LINE__, message) -#define int_panic(context, message) __do_int_panic(context, __FILE__, __LINE__, message) \ No newline at end of file diff --git a/kernel/include/rand/Init.h b/kernel/include/rand/Init.h deleted file mode 100644 index d0b91c70..00000000 --- a/kernel/include/rand/Init.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace Mersenne -{ - void init(); - void reseed(); -} \ No newline at end of file diff --git a/kernel/include/rand/Mersenne.h b/kernel/include/rand/Mersenne.h deleted file mode 100644 index 791b4500..00000000 --- a/kernel/include/rand/Mersenne.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include - -namespace Mersenne -{ - void seed(uint64_t); - uint64_t get(); -} \ No newline at end of file diff --git a/kernel/include/render/Color.h b/kernel/include/render/Color.h deleted file mode 100644 index 93b2bf76..00000000 --- a/kernel/include/render/Color.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include - -struct Color -{ - uint8_t blue; - uint8_t green; - uint8_t red; - uint8_t alpha; - - static Color White; - static Color Black; - static Color Red; - static Color Green; - static Color Blue; - static Color Yellow; - static Color Cyan; - static Color Magenta; - static Color Gray; - - static Color from_integer(uint32_t source); -} __attribute__((packed)); // to reinterpret this as a uint32_t AARRGGBB (in reversed order here because endianness) \ No newline at end of file diff --git a/kernel/include/render/Framebuffer.h b/kernel/include/render/Framebuffer.h deleted file mode 100644 index c8b53fe2..00000000 --- a/kernel/include/render/Framebuffer.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include "render/Color.h" - -class Framebuffer -{ - public: - void init(void* fb_address, int fb_type, int fb_scanline, int fb_width, int fb_height); - void set_pixel(uint32_t x, uint32_t y, Color color); - Color get_pixel(uint32_t x, uint32_t y); - void paint_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, Color color); - void paint_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, Color* colors); - void clear(Color color); - int width() - { - return m_fb_width; - } - int height() - { - return m_fb_height; - } - - private: - void* m_fb_address; - int m_fb_type; - int m_fb_scanline; - int m_fb_width; - int m_fb_height; -}; - -extern Framebuffer framebuffer0; \ No newline at end of file diff --git a/kernel/include/render/TextRenderer.h b/kernel/include/render/TextRenderer.h deleted file mode 100644 index cc7db7d0..00000000 --- a/kernel/include/render/TextRenderer.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "render/Color.h" -#include - -namespace TextRenderer -{ - void putchar(char chr); - void write(const char* str, size_t size); - void reset(); -} \ No newline at end of file diff --git a/kernel/include/std/ensure.h b/kernel/include/std/ensure.h deleted file mode 100644 index 8e90db85..00000000 --- a/kernel/include/std/ensure.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "panic/Panic.h" - -#define STRINGIZE(x) #x -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) - -// clang-format off -#define ensure(expr) (bool)(expr) || panic("Check failed at " __FILE__ ", line " STRINGIZE_VALUE_OF(__LINE__) ": " #expr) -// clang-format on \ No newline at end of file diff --git a/kernel/include/std/errno.h b/kernel/include/std/errno.h deleted file mode 100644 index be1713a3..00000000 --- a/kernel/include/std/errno.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#define EPERM 1 -#define ENOENT 2 -#define ESRCH 3 -#define EINTR 4 -#define E2BIG 7 -#define ENOEXEC 8 -#define EBADF 9 -#define ECHILD 10 -#define EAGAIN 11 -#define ENOMEM 12 -#define EACCES 13 -#define EFAULT 14 -#define EEXIST 17 -#define ENOTDIR 20 -#define EISDIR 21 -#define EINVAL 22 -#define EMFILE 24 -#define ENOTTY 25 -#define ENOSPC 28 -#define ERANGE 36 -#define ENOSYS 38 -#define ENOTSUP 95 \ No newline at end of file diff --git a/kernel/include/std/libgen.h b/kernel/include/std/libgen.h deleted file mode 100644 index 1a3a0e4d..00000000 --- a/kernel/include/std/libgen.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -char* basename(char* path); -char* dirname(char* path); - -char* better_basename(const char* path); -char* better_dirname(const char* path); \ No newline at end of file diff --git a/kernel/include/std/stdio.h b/kernel/include/std/stdio.h deleted file mode 100644 index ffe7e14e..00000000 --- a/kernel/include/std/stdio.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include -#include - -#define PRINTF_LIKE(n, m) __attribute__((format(printf, n, m))) - -int printf(const char* fmt, ...) PRINTF_LIKE(1, 2); // Outputs to serial. -int sprintf(char* __s, const char* fmt, ...) PRINTF_LIKE(2, 3); -int snprintf(char* __s, size_t max, const char* fmt, ...) PRINTF_LIKE(3, 4); -int vprintf(const char* fmt, va_list ap); -int vsprintf(char* __s, const char* fmt, va_list ap); -int vsnprintf(char* __s, size_t max, const char* fmt, va_list ap); -int kprintf(const char* fmt, ...) PRINTF_LIKE(1, 2); // Outputs to text console. -int vkprintf(const char* fmt, va_list ap); \ No newline at end of file diff --git a/kernel/include/std/stdlib.h b/kernel/include/std/stdlib.h deleted file mode 100644 index e11f9469..00000000 --- a/kernel/include/std/stdlib.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include - -char* itoa(int32_t number, char* arr, int base); -char* utoa(uint32_t number, char* arr, int base); - -char* ltoa(int64_t number, char* arr, int base); -char* ultoa(uint64_t number, char* arr, int base); - -void sleep(uint64_t ms); - -#define __skip_bindings -#include "memory/liballoc/liballoc.h" -#undef __skip_bindings \ No newline at end of file diff --git a/kernel/include/std/string.h b/kernel/include/std/string.h deleted file mode 100644 index 8725a94e..00000000 --- a/kernel/include/std/string.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include - -size_t strlen(const char* __s); - -__attribute__((deprecated)) char* strcpy(char* dest, const char* src); -__attribute__((deprecated)) int strcmp(const char* a, const char* b); -__attribute__((deprecated)) char* strcat(char* dest, const char* src); - -char* strncpy(char* dest, const char* src, size_t n); -size_t strlcpy(char* dest, const char* src, size_t size); -int strncmp(const char* a, const char* b, size_t n); -char* strncat(char* dest, const char* src, size_t n); - -char* strstr(char* haystack, const char* needle); - -void* memcpy(void* dest, const void* src, size_t n); -void* memset(void* dest, int c, size_t n); -int memcmp(const void* a, const void* b, size_t n); -void* memmove(void* dest, const void* src, size_t n); - -char* strdup(const char* src); -char* strrchr(const char* str, int c); \ No newline at end of file diff --git a/kernel/include/sys/Syscall.h b/kernel/include/sys/Syscall.h deleted file mode 100644 index 8a929696..00000000 --- a/kernel/include/sys/Syscall.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include "interrupts/Context.h" -#include -#include - -#define SYS_exit 0 -#define SYS_yield 1 -#define SYS_sleep 2 -#define SYS_write 3 -#define SYS_getprocid 4 -#define SYS_mmap 5 -#define SYS_munmap 6 -#define SYS_open 7 -#define SYS_read 8 -#define SYS_close 9 -#define SYS_seek 10 -#define SYS_execv 11 -#define SYS_fcntl 12 -#define SYS_mprotect 13 -#define SYS_clock_gettime 14 -#define SYS_mkdir 15 -#define SYS_fork 16 -#define SYS_waitpid 17 -#define SYS_access 18 -#define SYS_fstat 19 -#define SYS_pstat 20 -#define SYS_getdents 21 -#define SYS_stat 22 -#define SYS_dup2 23 -#define SYS_setuid 24 -#define SYS_setgid 25 -#define SYS_umask 26 -#define SYS_ioctl 27 -#define SYS_seteuid 28 -#define SYS_setegid 29 - -struct stat; -struct pstat; -struct luna_dirent; -struct timespec; - -namespace Syscall -{ - void entry(Context* context); -} - -void sys_exit(Context* context, int status); -void sys_yield(Context* context); -void sys_sleep(Context* context, uint64_t ms); -void sys_write(Context* context, int fd, size_t size, const char* addr); -void sys_getprocid(Context* context, int field); -void sys_mmap(Context* context, void* address, size_t size, int prot, int fd, off_t offset); -void sys_munmap(Context* context, void* address, size_t size); -void sys_open(Context* context, const char* filename, int flags, mode_t mode); -void sys_read(Context* context, int fd, size_t size, char* buffer); -void sys_close(Context* context, int fd); -void sys_seek(Context* context, int fd, long offset, int whence); -void sys_execv(Context* context, const char* pathname, char** argv); -void sys_fcntl(Context* context, int fd, int command, uintptr_t arg); -void sys_mprotect(Context* context, void* address, size_t size, int prot); -void sys_clock_gettime(Context* context, int clock_id, struct timespec* tp); -void sys_mkdir(Context* context, const char* filename, mode_t mode); -void sys_fork(Context* context); -void sys_waitpid(Context* context, long pid, int* wstatus, int options); -void sys_access(Context* context, const char* path, int amode); -void sys_fstat(Context* context, int fd, struct stat* buf); -void sys_pstat(Context* context, long pid, struct pstat* buf); -void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t count); -void sys_stat(Context* context, const char* path, struct stat* buf); -void sys_dup2(Context* context, int fd, int fd2); -void sys_setuid(Context* context, uid_t uid); -void sys_setgid(Context* context, gid_t gid); -void sys_umask(Context* context, mode_t cmask); -void sys_ioctl(Context* context, int fd, int request, uintptr_t arg); -void sys_seteuid(Context* context, uid_t euid); -void sys_setegid(Context* context, gid_t egid); \ No newline at end of file diff --git a/kernel/include/sys/UserMemory.h b/kernel/include/sys/UserMemory.h deleted file mode 100644 index fca1c034..00000000 --- a/kernel/include/sys/UserMemory.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#ifndef MODULE -#define MODULE "mem" -#endif - -#include "log/Log.h" -#include "memory/MemoryManager.h" -#include "memory/VMM.h" -#include "misc/utils.h" -#include - -Result strdup_from_user(const char* user_string); -bool validate_user_readable_page(uintptr_t address); -bool validate_user_writable_page(uintptr_t address); -bool validate_user_read(uintptr_t address, size_t size); -bool validate_user_write(uintptr_t address, size_t size); - -bool copy_from_user(const void* user_ptr, void* ptr, size_t size); -bool copy_to_user(void* user_ptr, const void* ptr, size_t size); - -template bool copy_typed_from_user(const T* user_ptr, T* ptr) -{ - return copy_from_user(user_ptr, ptr, sizeof(T)); -} - -template bool copy_typed_to_user(T* user_ptr, const T* ptr) -{ - return copy_to_user(user_ptr, ptr, sizeof(T)); -} \ No newline at end of file diff --git a/kernel/include/sys/elf/ELF.h b/kernel/include/sys/elf/ELF.h deleted file mode 100644 index 711bd3bd..00000000 --- a/kernel/include/sys/elf/ELF.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#define ELFMAG "\177ELF" -#define SELFMAG 4 -#define EI_CLASS 4 /* File class byte index */ -#define ELFCLASS64 2 /* 64-bit objects */ -#define EI_DATA 5 /* Data encoding byte index */ -#define ELFDATA2LSB 1 /* 2's complement, little endian */ -#define ET_EXEC 2 /* Executable file */ -#define PT_LOAD 1 /* Loadable program segment */ -#ifdef __x86_64__ -#define EM_MACH 62 /* AMD x86-64 architecture */ -#endif -#ifdef __aarch64__ -#define EM_MACH 183 /* ARM aarch64 architecture */ -#endif - -#include - -typedef struct -{ - uint8_t e_ident[16]; /* Magic number and other info */ - uint16_t e_type; /* Object file type */ - uint16_t e_machine; /* Architecture */ - uint32_t e_version; /* Object file version */ - uint64_t e_entry; /* Entry point virtual address */ - uint64_t e_phoff; /* Program header table file offset */ - uint64_t e_shoff; /* Section header table file offset */ - uint32_t e_flags; /* Processor-specific flags */ - uint16_t e_ehsize; /* ELF header size in bytes */ - uint16_t e_phentsize; /* Program header table entry size */ - uint16_t e_phnum; /* Program header table entry count */ - uint16_t e_shentsize; /* Section header table entry size */ - uint16_t e_shnum; /* Section header table entry count */ - uint16_t e_shstrndx; /* Section header string table index */ -} Elf64_Ehdr; - -typedef struct -{ - uint32_t p_type; /* Segment type */ - uint32_t p_flags; /* Segment flags */ - uint64_t p_offset; /* Segment file offset */ - uint64_t p_vaddr; /* Segment virtual address */ - uint64_t p_paddr; /* Segment physical address */ - uint64_t p_filesz; /* Segment size in file */ - uint64_t p_memsz; /* Segment size in memory */ - uint64_t p_align; /* Segment alignment */ -} Elf64_Phdr; \ No newline at end of file diff --git a/kernel/include/sys/elf/ELFLoader.h b/kernel/include/sys/elf/ELFLoader.h deleted file mode 100644 index 26b869e0..00000000 --- a/kernel/include/sys/elf/ELFLoader.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "fs/VFS.h" -#include "sys/elf/Image.h" -#include - -namespace ELFLoader -{ - ELFImage* load_elf_from_vfs(VFS::Node* node); // This function assumes check_elf_image has been called first. - ELFImage* load_elf_from_filesystem(const char* filename); - void release_elf_image(ELFImage* image); - long check_elf_image(VFS::Node* node); - long check_elf_image_from_filesystem(const char* filename); -} \ No newline at end of file diff --git a/kernel/include/sys/elf/Image.h b/kernel/include/sys/elf/Image.h deleted file mode 100644 index 552b00e4..00000000 --- a/kernel/include/sys/elf/Image.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include - -struct ELFSection -{ - uintptr_t base; - uint64_t pages; -}; - -struct ELFImage -{ - uintptr_t entry; - uint64_t section_count; - ELFSection sections[1]; -}; \ No newline at end of file diff --git a/kernel/include/thread/PIT.h b/kernel/include/thread/PIT.h deleted file mode 100644 index 9151508f..00000000 --- a/kernel/include/thread/PIT.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include - -namespace PIT -{ - extern volatile uint64_t ms_since_boot; - const uint64_t base_frequency = 1193182; - void initialize(uint64_t frequency); - uint64_t frequency(); - void tick(); -} diff --git a/kernel/include/thread/Scheduler.h b/kernel/include/thread/Scheduler.h deleted file mode 100644 index 24ab7789..00000000 --- a/kernel/include/thread/Scheduler.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "thread/Task.h" - -#define TASK_PAGES_IN_STACK 4 - -namespace Scheduler -{ - void init(); - void yield(); - void exit(int status); - void sleep(unsigned long ms); - void add_kernel_task(const char* taskname, void (*task)(void)); - - Task* create_user_task(); - - long load_user_task(const char* filename); - - void task_exit(Context* context, int64_t status); - void task_misbehave(Context* context, int64_t status); - - Task* current_task(); - - void task_yield(Context* context); - void task_tick(Context* context); - - void reap_task(Task* task); - void reap_tasks(); - - void reset_task(Task* task, ELFImage* new_image); - - void append_task(Task* task); - - Task* find_by_pid(uint64_t pid); -} \ No newline at end of file diff --git a/kernel/include/thread/Spinlock.h b/kernel/include/thread/Spinlock.h deleted file mode 100644 index 8678e69a..00000000 --- a/kernel/include/thread/Spinlock.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include - -struct Spinlock -{ - public: - void acquire(); - void release(); - bool locked(); - - private: - volatile uint64_t m_lock = 0; -}; - -void lock(Spinlock& lock, void (*action)(void)); \ No newline at end of file diff --git a/kernel/include/thread/Task.h b/kernel/include/thread/Task.h deleted file mode 100644 index 2238343a..00000000 --- a/kernel/include/thread/Task.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once -#include "fs/FileDescriptor.h" -#include "interrupts/Context.h" -#include "memory/AddressSpace.h" -#include "memory/UserHeap.h" -#include "sys/elf/Image.h" -#include - -#define TASK_MAX_FDS 32 - -enum class BlockReason -{ - None, - Reading, - Waiting, -}; - -// FIXME: To make this struct more C++-styled, maybe we could make a lot of these variables private and add -// getters/setters? - -struct Task -{ - enum TaskState - { - Idle, - Running, - Sleeping, - Dying, - Blocking, - Exited - }; - - uint64_t id; - uint64_t ppid; - Context regs; - - int64_t task_sleep = 0; - - int64_t exit_status; - - int64_t task_time = 0; - - uid_t uid; - uid_t euid; - gid_t gid; - gid_t egid; - - Task* next_task = nullptr; - Task* prev_task = nullptr; - - uint64_t allocated_stack = 0; - - TaskState state; - - uint64_t cpu_time = 0; - - char floating_region[512] __attribute__((aligned(16))); - bool floating_saved = false; - - bool user_task = true; - - bool is_user_task(); - - ELFImage* image = nullptr; // FIXME: we probably don't need to keep track of this anymore since the ELF sections are - // freed automatically when calling destroy() or clear() on the address space. - - Descriptor files[TASK_MAX_FDS]; - - AddressSpace address_space; - - UserHeap allocator; - - int alloc_fd(); - - int alloc_fd_greater_than_or_equal(int base_fd); - - void save_context(Context* context); - void restore_context(Context* context); - - void save_floating(); - void restore_floating(); - - void switch_to_address_space(); - - bool has_died(); - - char name[128]; - - mode_t umask; - - BlockReason block_reason; - - union { - struct - { - size_t size; - int fd; - char* buf; - } blocking_read_info; - struct - { - int64_t pid; - int* wstatus; - } blocking_wait_info; - }; - - void resume(); - - bool is_still_blocking(); - - // FIXME: These two functions are a bit clunky. - Descriptor* open_descriptor_from_fd(int fd, int& error); - Descriptor* descriptor_from_fd(int fd, int& error); - - bool is_superuser(); - - private: - void resume_read(); - void resume_wait(); - - bool is_read_still_blocking(); - bool is_wait_still_blocking(); -}; \ No newline at end of file diff --git a/kernel/include/trace/Resolve.h b/kernel/include/trace/Resolve.h deleted file mode 100644 index f54f0b29..00000000 --- a/kernel/include/trace/Resolve.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include -#include - -void get_symbol_name(uintptr_t address, char* buffer, size_t size); \ No newline at end of file diff --git a/kernel/include/trace/StackTracer.h b/kernel/include/trace/StackTracer.h deleted file mode 100644 index b82234f2..00000000 --- a/kernel/include/trace/StackTracer.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include - -struct StackTracer -{ - StackTracer(); - StackTracer(uintptr_t base_pointer); - void trace(); - void trace_with_ip(uintptr_t ip); - - private: - uintptr_t m_base_pointer; -}; - -bool stack_trace_contains(uintptr_t address); \ No newline at end of file diff --git a/kernel/include/utils/Addresses.h b/kernel/include/utils/Addresses.h deleted file mode 100644 index 23752357..00000000 --- a/kernel/include/utils/Addresses.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include - -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - -inline uintptr_t get_top_of_stack(uintptr_t bottom, size_t stack_pages) -{ - return bottom + (stack_pages * PAGE_SIZE) - sizeof(uintptr_t); -} - -inline uintptr_t round_down_to_nearest_page(uintptr_t addr) -{ - return addr - (addr % PAGE_SIZE); -} - -inline uintptr_t round_up_to_nearest_page(uintptr_t addr) -{ - if (addr % PAGE_SIZE) return addr + (PAGE_SIZE - (addr % PAGE_SIZE)); - return addr; -} \ No newline at end of file diff --git a/kernel/include/utils/Dynamic.h b/kernel/include/utils/Dynamic.h deleted file mode 100644 index 6a2fd496..00000000 --- a/kernel/include/utils/Dynamic.h +++ /dev/null @@ -1,167 +0,0 @@ -#pragma once -#include "log/Log.h" -#include "std/ensure.h" -#include "std/stdlib.h" -#include "std/string.h" -#include "utils/new.h" - -#define __noinline __attribute__((noinline)) - -template struct Dynamic -{ - Dynamic() - { - set_expand_rate(16); - ensure(expand_fixed()); - } - - Dynamic(size_t capacity) - { - set_expand_rate(16); - ensure(expand_fixed()); - } - - Dynamic(const Dynamic& other) - { - set_expand_rate(other.m_expand_rate); - ensure_capacity(other.capacity()); - m_size = other.size(); - memcpy(m_buf, other.data(), m_capacity * sizeof(T)); - } - - Dynamic(Dynamic&& other) - { - set_expand_rate(other.m_expand_rate); - m_buf = other.release_data(); - m_capacity = other.capacity(); - m_size = other.size(); - } - - Dynamic& operator=(const Dynamic& other) - { - if (this == &other) return *this; - - if (m_buf) - { - while (m_size) pop(); // destroy all objects - kfree(m_buf); - } - - set_expand_rate(other.m_expand_rate); - ensure_capacity(other.capacity()); - m_size = other.size(); - memcpy(m_buf, other.data(), m_capacity * sizeof(T)); - - return *this; - } - - ~Dynamic() - { - if (m_buf) - { - while (m_size) pop(); // destroy all objects - kfree(m_buf); - } - } - - T& at(size_t index) - { - ensure(index < m_size); - return m_buf[index]; - } - - const T& at(size_t index) const - { - ensure(index < m_size); - return m_buf[index]; - } - - T& operator[](size_t index) - { - return at(index); - } - - const T& operator[](size_t index) const - { - return at(index); - } - - bool expand_capacity(size_t capacity) - { - return expand(capacity); - } - - void ensure_capacity(size_t capacity) - { - ensure(expand(capacity)); - } - - void set_expand_rate(size_t rate) - { - if (!rate) return; - m_expand_rate = rate; - } - - __noinline bool push(const T& item) - { - if (m_size == m_capacity) - if (!expand_fixed()) return false; - m_size++; - T* loc = ptr_at(m_size - 1); - new (loc) T(item); - return true; - } - - void pop() - { - at(m_size - 1).~T(); - m_size--; - } - - size_t capacity() const - { - return m_capacity; - } - - size_t size() const - { - return m_size; - } - - const T* data() const - { - return m_buf; - } - - T* release_data() - { - T* result = m_buf; - m_buf = nullptr; - return result; - } - - private: - T* m_buf = nullptr; - size_t m_capacity = 0; - size_t m_size = 0; - size_t m_expand_rate = 16; - - bool expand(size_t new_capacity) - { - m_buf = (T*)krealloc(m_buf, new_capacity * sizeof(T)); - if (!m_buf) return false; - m_capacity = new_capacity; - return true; - } - - bool expand_fixed() - { - ensure(m_expand_rate != 0); - return expand(m_capacity + m_expand_rate); - } - - T* ptr_at(size_t index) - { - return (T*)((char*)m_buf + index * sizeof(T)); - } -}; \ No newline at end of file diff --git a/kernel/include/utils/PageFaultReason.h b/kernel/include/utils/PageFaultReason.h deleted file mode 100644 index 7f9d88da..00000000 --- a/kernel/include/utils/PageFaultReason.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include - -void determine_user_page_fault_reason(uintptr_t faulting_address); \ No newline at end of file diff --git a/kernel/include/utils/Registers.h b/kernel/include/utils/Registers.h deleted file mode 100644 index 944a0ea0..00000000 --- a/kernel/include/utils/Registers.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include - -extern "C" uintptr_t asm_get_rflags(); -extern "C" void asm_set_rflags(uintptr_t); - -inline uintptr_t read_rflags() -{ - return asm_get_rflags(); -} - -inline void write_rflags(uintptr_t value) -{ - asm_set_rflags(value); -} - -inline uintptr_t read_cr0() -{ - uintptr_t value; - asm volatile("mov %%cr0, %0" : "=r"(value)); - return value; -} - -inline uintptr_t read_cr3() -{ - uintptr_t value; - asm volatile("mov %%cr3, %0" : "=r"(value)); - return value; -} - -inline uintptr_t read_cr4() -{ - uintptr_t value; - asm volatile("mov %%cr4, %0" : "=r"(value)); - return value; -} - -template inline void write_cr0(T value) -{ - asm volatile("mov %0, %%cr0" : : "r"(value)); -} - -template inline void write_cr3(T value) -{ - asm volatile("mov %0, %%cr3" : : "r"(value)); -} - -template inline void write_cr4(T value) -{ - asm volatile("mov %0, %%cr4" : : "r"(value)); -} \ No newline at end of file diff --git a/kernel/include/utils/Result.h b/kernel/include/utils/Result.h deleted file mode 100644 index 6abb0f8a..00000000 --- a/kernel/include/utils/Result.h +++ /dev/null @@ -1,153 +0,0 @@ -#pragma once -#include "std/ensure.h" -#include "std/errno.h" -#include "std/string.h" -#include "utils/move.h" -#include "utils/new.h" - -struct Error -{ - Error(int err) - { - error = err; - } - - int error; -}; - -template class Result -{ - public: - Result(const T& value) - { - m_storage.store_reference(value); - m_has_value = true; - m_has_error = false; - } - - Result(T&& value) - { - m_storage.store_movable_reference(move(value)); - m_has_value = true; - m_has_error = false; - } - - Result(const Result& other) - { - m_storage.store_reference(other.m_storage.fetch_reference()); - m_has_value = true; - m_has_error = false; - } - - Result(Result&& other) - { - m_storage.store_movable_reference(move(other.m_storage.fetch_reference())); - m_has_value = true; - m_has_error = false; - } - - Result(const Error& err) - { - m_error = err.error; - m_has_error = true; - m_has_value = false; - } - - bool has_error() - { - return m_has_error; - } - - bool has_value() - { - return m_has_value; - } - - int error() - { - ensure(has_error()); - return m_error; - } - - Error release_error() - { - ensure(has_error()); - return {m_error}; - } - - T value() - { - ensure(has_value()); - return m_storage.fetch_reference(); - } - - T value_or(T other) - { - if (has_value()) return m_storage.fetch_reference(); - return other; - } - - T release_value() - { - ensure(has_value()); - T item = m_storage.fetch_reference(); - m_has_value = false; - m_storage.destroy(); - return move(item); - } - - ~Result() - { - if (has_value()) m_storage.destroy(); - } - - private: - struct Storage - { - unsigned char buffer[sizeof(T)]; - - T* fetch_ptr() - { - return (T*)buffer; - } - - T& fetch_reference() - { - return *fetch_ptr(); - } - - const T* fetch_ptr() const - { - return (const T*)buffer; - } - - const T& fetch_reference() const - { - return *fetch_ptr(); - } - - void store_ptr(T* ptr) - { - new (buffer) T(*ptr); - } - - void store_reference(const T& ref) - { - new (buffer) T(ref); - } - - void store_movable_reference(T&& ref) - { - new (buffer) T(ref); - } - - void destroy() - { - fetch_reference().~T(); - } - }; - Storage m_storage; - int m_error; - bool m_has_error; - bool m_has_value; -}; \ No newline at end of file diff --git a/kernel/include/utils/StringParsing.h b/kernel/include/utils/StringParsing.h deleted file mode 100644 index 264644f6..00000000 --- a/kernel/include/utils/StringParsing.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -long parse_decimal(const char* str); -long parse_octal(const char* str); \ No newline at end of file diff --git a/kernel/include/utils/Time.h b/kernel/include/utils/Time.h deleted file mode 100644 index 3e06716f..00000000 --- a/kernel/include/utils/Time.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include - -int make_yday(int year, int month); - -uint64_t broken_down_to_unix(uint64_t year, uint64_t yday, uint64_t hour, uint64_t min, uint64_t sec); - -uint64_t unix_boottime(uint8_t boottime[8]); \ No newline at end of file diff --git a/kernel/include/utils/move.h b/kernel/include/utils/move.h deleted file mode 100644 index 9006d68a..00000000 --- a/kernel/include/utils/move.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -template inline T&& move(T& lvalue) -{ - return (T &&) lvalue; -} \ No newline at end of file diff --git a/kernel/include/utils/new.h b/kernel/include/utils/new.h deleted file mode 100644 index 1e6afcd1..00000000 --- a/kernel/include/utils/new.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include - -inline void* operator new(size_t, void* p) noexcept -{ - return p; -} -inline void* operator new[](size_t, void* p) noexcept -{ - return p; -} -inline void operator delete(void*, void*) noexcept {}; -inline void operator delete[](void*, void*) noexcept {}; \ No newline at end of file diff --git a/kernel/moon.ld b/kernel/moon.ld index e2dd402a..8445665d 100644 --- a/kernel/moon.ld +++ b/kernel/moon.ld @@ -1,4 +1,4 @@ -ENTRY(_main) +ENTRY(_start) OUTPUT_FORMAT(elf64-x86-64) mmio = 0xfffffffff8000000; /* these are configurable for level 2 loaders */ @@ -32,5 +32,4 @@ SECTIONS kernel_end = .; /DISCARD/ : { *(.eh_frame) *(.comment) } -} - +} \ No newline at end of file diff --git a/kernel/src/acpi/RSDT.cpp b/kernel/src/acpi/RSDT.cpp deleted file mode 100644 index 98f78afc..00000000 --- a/kernel/src/acpi/RSDT.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#define MODULE "acpi" - -#include "acpi/RSDT.h" -#include "bootboot.h" -#include "log/Log.h" -#include "memory/MemoryManager.h" -#include "misc/utils.h" -#include "std/stdio.h" -#include "std/string.h" - -extern BOOTBOOT bootboot; - -// FIXME: Propagate errors. - -ACPI::SDTHeader* ACPI::get_rsdt_or_xsdt() -{ - static SDTHeader* cache = nullptr; - if (cache) return cache; - - kdbgln("First time accessing the RSDT/XSDT, mapping it into memory"); - void* physical = (void*)bootboot.arch.x86_64.acpi_ptr; - kdbgln("RSDT/XSDT physical address: %p", physical); - - SDTHeader* rsdt = (SDTHeader*)MemoryManager::get_unaligned_mapping(physical).release_value(); - - uint64_t offset = (uint64_t)physical % PAGE_SIZE; - uint64_t rsdt_pages = Utilities::get_blocks_from_size(PAGE_SIZE, (offset + rsdt->Length)); - - if (rsdt_pages > 1) - { - MemoryManager::release_unaligned_mapping(rsdt); - rsdt = (SDTHeader*)MemoryManager::get_unaligned_mappings(cache, rsdt_pages).release_value(); - } - - kdbgln("Mapped RSDT/XSDT to virtual address %p, uses %ld pages", (void*)rsdt, rsdt_pages); - cache = rsdt; - return rsdt; -} - -bool ACPI::validate_rsdt_or_xsdt(ACPI::SDTHeader* root_sdt) -{ - if (!validate_sdt_header(root_sdt)) return false; - if (strncmp(root_sdt->Signature, "XSDT", 4) == 0) return true; - if (strncmp(root_sdt->Signature, "RSDT", 4) == 0) return true; - return false; -} - -bool ACPI::is_xsdt() -{ - static bool cached = false; - static bool cache = false; - if (cached) return cache; - SDTHeader* rootSDT = get_rsdt_or_xsdt(); - cache = (strncmp(rootSDT->Signature, "XSDT", 4) == 0); - cached = true; - return cache; -} - -void* ACPI::find_table(ACPI::SDTHeader* root_sdt, const char* signature) -{ - bool isXSDT = is_xsdt(); - uint64_t entries = (root_sdt->Length - sizeof(SDTHeader)) / (isXSDT ? 8 : 4); - kdbgln("Searching for table %s in the %s at %p (table contains %ld entries)", signature, isXSDT ? "XSDT" : "RSDT", - (void*)root_sdt, entries); - - for (uint64_t i = 0; i < entries; i++) - { - kdbgln("Testing for table %s in entry %ld", signature, i); - SDTHeader* h; - if (isXSDT) - { - uint64_t reversedAddress = (uint64_t)((XSDT*)root_sdt)->other_sdt[i]; - uint64_t correctAddress = reversedAddress >> 32 | reversedAddress << 32; - h = (SDTHeader*)correctAddress; - } - else - { - uint32_t entry = ((RSDT*)root_sdt)->other_sdt[i]; - h = (SDTHeader*)(uint64_t)entry; - } - if (!h) - { - kwarnln("Entry %ld in the %s points to null", i, isXSDT ? "XSDT" : "RSDT"); - continue; - } - kdbgln("Physical address of entry: %p", (void*)h); - SDTHeader* realHeader = (SDTHeader*)MemoryManager::get_unaligned_mapping(h).release_value(); - kdbgln("Mapped entry to virtual address %p", (void*)realHeader); - if (!validate_sdt_header(realHeader)) - { - kwarnln("Header of entry %ld is not valid, skipping this entry", i); - MemoryManager::release_unaligned_mapping(realHeader); - continue; - } - char tableSignature[5]; - memcpy(tableSignature, h->Signature, 4); - tableSignature[4] = 0; - kdbgln("Comparing target signature (%s) to signature of entry (%s)", signature, tableSignature); - if (strncmp(h->Signature, signature, 4) == 0) - { - kdbgln("Found table %s", signature); - return (void*)realHeader; - } - kdbgln("Signatures do not match, unmapping entry and continuing"); - MemoryManager::release_unaligned_mapping(realHeader); - } - - return NULL; -} \ No newline at end of file diff --git a/kernel/src/acpi/SDT.cpp b/kernel/src/acpi/SDT.cpp deleted file mode 100644 index 9b861ab6..00000000 --- a/kernel/src/acpi/SDT.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "acpi/SDT.h" - -#pragma GCC push_options -#pragma GCC diagnostic ignored "-Wconversion" - -bool ACPI::validate_sdt_header(ACPI::SDTHeader* header) -{ - uint8_t sum = 0; - - for (uint32_t i = 0; i < header->Length; i++) { sum += ((char*)header)[i]; } - - return sum == 0; -} - -#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/cpu/CPU.cpp b/kernel/src/cpu/CPU.cpp deleted file mode 100644 index f686a009..00000000 --- a/kernel/src/cpu/CPU.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#define MODULE "cpuid" - -#include "cpu/CPU.h" -#include "log/Log.h" -#include -#include - -const char* CPU::get_vendor_string() -{ - static bool cached = false; - static char vendor[13]; - if (cached) { return vendor; } - else - { - unsigned int unused, ebx, ecx, edx; - __get_cpuid(0, &unused, &ebx, &ecx, &edx); - memcpy(vendor, &ebx, 4); - memcpy(&vendor[4], &edx, 4); - memcpy(&vendor[8], &ecx, 4); - vendor[12] = 0; - cached = true; - return vendor; - } -} - -const char* CPU::get_brand_string() -{ - static bool cached = false; - static char brand[49]; - if (cached) { return brand; } - else - { - unsigned int eax, ebx, ecx, edx; - __get_cpuid(0x80000002, &eax, &ebx, &ecx, &edx); - memcpy(brand, &eax, 4); - memcpy(&brand[4], &ebx, 4); - memcpy(&brand[8], &ecx, 4); - memcpy(&brand[12], &edx, 4); - __get_cpuid(0x80000003, &eax, &ebx, &ecx, &edx); - memcpy(&brand[16], &eax, 4); - memcpy(&brand[16 + 4], &ebx, 4); - memcpy(&brand[16 + 8], &ecx, 4); - memcpy(&brand[16 + 12], &edx, 4); - __get_cpuid(0x80000004, &eax, &ebx, &ecx, &edx); - memcpy(&brand[32], &eax, 4); - memcpy(&brand[32 + 4], &ebx, 4); - memcpy(&brand[32 + 8], &ecx, 4); - memcpy(&brand[32 + 12], &edx, 4); - brand[48] = 0; - cached = true; - return brand; - } -} - -uint64_t CPU::get_feature_bitmask() -{ - static uint64_t bitmask = 0; - static bool cached = false; - if (cached) return bitmask; - unsigned int unused; - unsigned int ecx = 0; - unsigned int edx = 0; - __get_cpuid(1, &unused, &unused, &ecx, &edx); - bitmask = ((uint64_t)ecx << 32) | (uint64_t)edx; - cached = true; - return bitmask; -} - -bool CPU::has_nx() -{ - unsigned int unused; - unsigned int edx; - __get_cpuid(0x80000001, &unused, &unused, &unused, &edx); - return edx & (1 << 20); -} - -static bool _has_feature(int feature) -{ - return (CPU::get_feature_bitmask() & (uint64_t)(1UL << feature)) > 0; -} - -bool CPU::has_feature(CPU::Features feature) -{ - return _has_feature((int)feature); -} - -uint64_t CPU::get_initial_apic_id() -{ - unsigned int unused; - unsigned int ebx = 0; - __get_cpuid(1, &unused, &ebx, &unused, &unused); - return ebx >> 24; -} - -void CPU::log_cpu_information() -{ - kinfoln("CPU vendor: %s", get_vendor_string()); - kinfoln("CPU brand: %s", get_brand_string()); -} diff --git a/kernel/src/fs/FileDescriptor.cpp b/kernel/src/fs/FileDescriptor.cpp deleted file mode 100644 index 26dee2bc..00000000 --- a/kernel/src/fs/FileDescriptor.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "fs/FileDescriptor.h" -#include "std/errno.h" -#include "std/stdlib.h" -#include "sys/UserMemory.h" - -Descriptor::Descriptor() : m_is_open(false) -{ -} - -Descriptor::Descriptor(const Descriptor& other) - : m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write), - m_able_to_block(other.m_able_to_block), m_close_on_exec(other.m_close_on_exec), m_node(other.m_node), - m_offset(other.m_offset) -{ -} - -void Descriptor::open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec) -{ - m_can_read = can_read; - m_can_write = can_write; - m_able_to_block = able_to_block; - m_close_on_exec = close_on_exec; - m_node = node; - m_offset = 0; - m_is_open = true; -} - -ssize_t Descriptor::read(size_t size, char* buffer) -{ - ssize_t result = VFS::read(m_node, m_offset, size, buffer); - m_offset += result; - return result; -} - -ssize_t Descriptor::write(size_t size, const char* buffer) -{ - ssize_t result = VFS::write(m_node, m_offset, size, buffer); - m_offset += result; - return result; -} - -ssize_t Descriptor::user_read(size_t size, char* buffer) -{ - char* buf = (char*)kmalloc(size); - if (!buf) return -ENOMEM; - ssize_t result = read(size, buf); - if (!copy_to_user(buffer, buf, size)) result = -EFAULT; - kfree(buf); - return result; -} - -ssize_t Descriptor::user_write(size_t size, const char* buffer) -{ - char* buf = (char*)kmalloc(size); - if (!buf) return -ENOMEM; - ssize_t result; - if (!copy_from_user(buffer, buf, size)) result = -EFAULT; - else - result = write(size, buf); - kfree(buf); - return result; -} - -#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno) - -uintptr_t Descriptor::mmap(uintptr_t addr, size_t size, int prot, off_t offset) -{ - if (!m_node->mmap_func) return MAP_FAIL(ENOTSUP); - return m_node->mmap_func(m_node, addr, size, prot, offset); -} - -long Descriptor::ioctl(int cmd, uintptr_t arg) -{ - if (!m_node->ioctl_func) return MAP_FAIL(ENOTSUP); - return m_node->ioctl_func(m_node, cmd, arg); -} - -int Descriptor::seek(long offset) -{ - if (m_node->type == VFS_FILE && (uint64_t)offset > m_node->length) - return -EINVAL; // FIXME: Support seeking beyond the current file's length. - m_offset = (uint64_t)offset; - return 0; -} - -const Descriptor& Descriptor::operator=(const Descriptor& other) -{ - m_is_open = other.m_is_open; - m_can_read = other.m_can_read; - m_can_write = other.m_can_write; - m_offset = other.m_offset; - m_node = other.m_node; - m_able_to_block = other.m_able_to_block; - m_close_on_exec = other.m_close_on_exec; - return other; -} \ No newline at end of file diff --git a/kernel/src/fs/InitRD.cpp b/kernel/src/fs/InitRD.cpp deleted file mode 100644 index bb664610..00000000 --- a/kernel/src/fs/InitRD.cpp +++ /dev/null @@ -1,424 +0,0 @@ -#define MODULE "initrd" - -#include "fs/InitRD.h" -#include "bootboot.h" -#include "fs/VFS.h" -#include "io/Serial.h" -#include "log/Log.h" -#include "memory/MemoryManager.h" -#include "misc/utils.h" -#include "std/errno.h" -#include "std/stdlib.h" -#include "std/string.h" -#include "utils/StringParsing.h" - -// FIXME: A lot of this code was written before the VFS was created and thus is quite messy and assumes other stuff. - -extern BOOTBOOT bootboot; - -static void* initrd_base; -static bool initrd_initialized = false; - -static VFS::Node initrd_root; - -extern uint64_t clock_boot(); // defined in sys/clock.cpp -extern uint64_t clock_now(); - -bool InitRD::is_initialized() -{ - return initrd_initialized; -} - -static inline uint64_t get_file_size_in_blocks(InitRD::File f) -{ - return f.size_in_blocks; -} - -inline uint64_t InitRD::get_total_blocks() -{ - return bootboot.initrd_size / TAR_BLOCKSIZE; -} - -inline InitRD::TarHeader* InitRD::get_block(uint64_t block_index) -{ - return (TarHeader*)((uintptr_t)initrd_base + block_index * TAR_BLOCKSIZE); -} - -inline bool InitRD::is_valid_header(TarHeader* header) -{ - return strncmp(header->magic, TAR_MAGIC, 5) == 0; -} - -uint64_t InitRD::get_file_physical_address(InitRD::File& file) -{ - return (uint64_t)file.addr - (uint64_t)initrd_base + (uint64_t)bootboot.initrd_ptr; -} - -InitRD::File InitRD::get_file(TarHeader* header) -{ - File result; - char null_terminated_size[13]; - memcpy(null_terminated_size, header->size, 12); - null_terminated_size[12] = 0; - result.size = parse_octal(null_terminated_size); - memcpy(result.name, header->name, 100); - result.addr = (void*)((uint64_t)header + TAR_BLOCKSIZE); - result.size_in_blocks = Utilities::get_blocks_from_size(TAR_BLOCKSIZE, result.size); - result.mode = (mode_t)parse_octal(header->mode); - return result; -} - -InitRD::File InitRD::open(const char* filename) -{ - uint64_t block = 0; - uint64_t total_blocks = get_total_blocks(); - while (block < total_blocks) - { - TarHeader* hdr = (TarHeader*)get_block(block); - if (hdr->typeflag == 53) - { - block++; - continue; - } - if (!is_valid_header(hdr)) - { - block++; - continue; - } - auto f = get_file(hdr); - if (strncmp(hdr->name, filename, strlen(filename)) == 0) { return f; } - block += get_file_size_in_blocks(f) + 1; - } - File nullFile; - nullFile.addr = 0; - nullFile.size = 0; - memcpy(nullFile.name, "NULL", 5); - return nullFile; -} - -void InitRD::for_each(void (*callback)(File& f)) -{ - uint64_t block = 0; - uint64_t total_blocks = get_total_blocks(); - while (block < total_blocks) - { - TarHeader* hdr = (TarHeader*)get_block(block); - if (hdr->typeflag == 53) - { - block++; - continue; - } - if (!is_valid_header(hdr)) - { - block++; - continue; - } - auto f = get_file(hdr); - block += get_file_size_in_blocks(f) + 1; - callback(f); - } -} - -#define INITRD_MAX_FILES_IN_DIR 32 -#define INITRD_MAX_FILES 64 - -namespace InitRD -{ - struct Directory - { - char name[64]; - int entries = 0; - VFS::Node* files[INITRD_MAX_FILES_IN_DIR]; - }; -} - -void initrd_for_each_dir(void (*callback)(InitRD::Directory& f)) -{ - uint64_t block = 0; - uint64_t total_blocks = InitRD::get_total_blocks(); - while (block < total_blocks) - { - InitRD::TarHeader* hdr = (InitRD::TarHeader*)InitRD::get_block(block); - if (!InitRD::is_valid_header(hdr)) - { - block++; - continue; - } - if (hdr->typeflag == 53) - { - InitRD::Directory dir; - strncpy(dir.name, hdr->name, sizeof(dir.name)); - callback(dir); - block++; - continue; - } - auto f = get_file(hdr); - block += get_file_size_in_blocks(f) + 1; - } -} - -static InitRD::File files[INITRD_MAX_FILES]; -static uint32_t total_files = 0; - -static InitRD::Directory dirs[INITRD_MAX_FILES]; -static uint32_t total_dirs = 0; - -static VFS::Node nodes[INITRD_MAX_FILES + (INITRD_MAX_FILES - 1)]; // One of the dirs is the initrd_root -static uint32_t total_nodes = 0; - -ssize_t initrd_read(VFS::Node* node, size_t offset, size_t length, char* buffer) -{ - if (!node) return -1; - if (node->inode >= total_files) return -1; - InitRD::File& file = files[node->inode]; - if (offset > file.size) return -1; - if (offset + length > file.size) { length = file.size - offset; } - memcpy(buffer, (void*)((uintptr_t)file.addr + offset), length); - return length; -} - -VFS::Node* initrd_scan_dir(VFS::Node* node, const char* filename) -{ - if (!node) return 0; - if (node->inode >= total_dirs) return 0; - InitRD::Directory dir = dirs[node->inode]; - for (int i = 0; i < dir.entries; i++) - { - if (strncmp(dir.files[i]->name, filename, sizeof(VFS::Node::name)) == 0) { return dir.files[i]; } - } - return 0; -} - -VFS::Node* initrd_read_dir(VFS::Node* node, long offset) -{ - if (!node) return 0; - if (node->inode >= total_dirs) return 0; - InitRD::Directory dir = dirs[node->inode]; - if (offset >= dir.entries) return 0; - return dir.files[offset]; -} - -int initrd_mkdir(VFS::Node* node, const char* name, mode_t mode) // FIXME: Return proper error numbers. -{ - if (total_dirs >= 32) - { - kwarnln("mkdir() failed: too many directories"); - return -ENOSPC; - } - if (node->inode > total_dirs) - { - kwarnln("mkdir() failed: invalid node"); - return -EINVAL; - } - if (!(node->type & VFS_DIRECTORY)) - { - kwarnln("mkdir() failed: not a directory"); - return -ENOTDIR; - } - InitRD::Directory& parent = dirs[node->inode]; - if (parent.entries == INITRD_MAX_FILES_IN_DIR) - { - kwarnln("mkdir() failed: parent is full"); - return -ENOSPC; - } - uint64_t inode = total_dirs; - VFS::Node& new_node = nodes[total_nodes++]; - new_node.inode = inode; - new_node.find_func = initrd_scan_dir; - new_node.mkdir_func = initrd_mkdir; - new_node.readdir_func = initrd_read_dir; - new_node.length = 0; - new_node.type = VFS_DIRECTORY; - new_node.mode = mode; - new_node.uid = new_node.gid = 0; - new_node.atime = new_node.ctime = new_node.mtime = clock_now(); - strncpy(new_node.name, name, sizeof(new_node.name)); - InitRD::Directory dir; - strncpy(dir.name, name, sizeof(dir.name)); - dir.entries = 0; - dirs[total_dirs++] = dir; // FIXME: Right now this isn't of worry, but there is a possibility for a TOCTOU bug here. - // Should use a spinlock or something. - node->length++; - parent.files[parent.entries++] = &new_node; - return 0; -} - -static bool initrd_register_dir(InitRD::Directory& dir, uint64_t inode) -{ - const char* filename = dir.name; - VFS::Node* current_node = &initrd_root; - while (true) - { - while (*filename == '/') { filename++; } - if (*filename == 0) { return false; } - - size_t path_section_size = 0; - while (filename[path_section_size] && filename[path_section_size] != '/') { path_section_size++; } - - if (filename[path_section_size]) // We are in a '/' - { - char* buffer = (char*)kmalloc(path_section_size + 1); - memcpy(buffer, filename, path_section_size); - buffer[path_section_size] = 0; - if (!current_node->find_func) { return false; } - VFS::Node* child = current_node->find_func(current_node, buffer); - if (!child) { return false; } - current_node = child; - kfree(buffer); - } - else - { - if (strncmp(filename, ".", path_section_size) != 0) // The current path section is not '.' - { - if (strncmp(filename, "..", path_section_size) == 0) { return false; } - - if (!current_node->find_func) { return false; } - - InitRD::Directory& parent = dirs[current_node->inode]; - if (parent.entries == INITRD_MAX_FILES_IN_DIR) { return false; } - - char* buffer = (char*)kmalloc(path_section_size + 1); - memcpy(buffer, filename, path_section_size); - buffer[path_section_size] = 0; - - VFS::Node& node = nodes[total_nodes++]; - node.inode = inode; - node.find_func = initrd_scan_dir; - node.length = 0; - node.type = VFS_DIRECTORY; - node.mkdir_func = initrd_mkdir; - node.readdir_func = initrd_read_dir; - node.length = 0; - node.mode = 0755; - node.uid = node.gid = 0; - node.atime = node.ctime = node.mtime = clock_boot(); - strncpy(node.name, buffer, sizeof(node.name)); - strncpy(dir.name, buffer, sizeof(dir.name)); - - parent.files[parent.entries++] = &node; - current_node->length++; - - kfree(buffer); - return true; - } - else { return false; } - } - - filename += path_section_size; - } -} - -static bool initrd_register_file(InitRD::File& f, uint64_t inode) -{ - const char* filename = f.name; - VFS::Node* current_node = &initrd_root; - while (true) - { - while (*filename == '/') { filename++; } - if (*filename == 0) { return false; } - - size_t path_section_size = 0; - while (filename[path_section_size] && filename[path_section_size] != '/') { path_section_size++; } - - if (filename[path_section_size]) // We are in a '/' - { - char* buffer = (char*)kmalloc(path_section_size + 1); - memcpy(buffer, filename, path_section_size); - buffer[path_section_size] = 0; - if (!current_node->find_func) { return false; } - VFS::Node* child = current_node->find_func(current_node, buffer); - if (!child) { return false; } - current_node = child; - kfree(buffer); - } - else - { - if (strncmp(filename, ".", path_section_size) != 0) // The current path section is not '.' - { - if (strncmp(filename, "..", path_section_size) == 0) { return false; } - - if (!current_node->find_func) { return false; } - - InitRD::Directory& parent = dirs[current_node->inode]; - if (parent.entries == INITRD_MAX_FILES_IN_DIR) { return false; } - - char* buffer = (char*)kmalloc(path_section_size + 1); - memcpy(buffer, filename, path_section_size); - buffer[path_section_size] = 0; - - VFS::Node& node = nodes[total_nodes++]; - node.inode = inode; - node.read_func = initrd_read; - node.length = f.size; - node.type = VFS_FILE; - node.mode = f.mode & 07555; // don't allow writing - node.uid = node.gid = 0; - node.atime = node.ctime = node.mtime = clock_boot(); - strncpy(node.name, buffer, sizeof(node.name)); - strncpy(f.name, buffer, sizeof(f.name)); - - parent.files[parent.entries++] = &node; - current_node->length++; - kfree(buffer); - return true; - } - else { return false; } - } - - filename += path_section_size; - } -} - -static void initrd_scan() -{ - initrd_for_each_dir([](InitRD::Directory& dir) { - if (total_dirs >= INITRD_MAX_FILES) - { - kwarnln("Failed to register directory %s: Too many directories in initrd", dir.name); - return; - } - uint64_t inode = total_dirs; - if (initrd_register_dir(dir, inode)) dirs[total_dirs++] = dir; - }); - InitRD::for_each([](InitRD::File& f) { - if (total_files >= INITRD_MAX_FILES) - { - kwarnln("Failed to register file %s: Too many files in initrd", f.name); - return; - } - uint64_t inode = total_files; - if (initrd_register_file(f, inode)) files[total_files++] = f; - }); -} - -static void initrd_initialize_root() -{ - initrd_root.length = 0; - initrd_root.inode = 0; - initrd_root.type |= VFS_DIRECTORY; - initrd_root.mode = 0755; - initrd_root.uid = initrd_root.gid = 0; - initrd_root.atime = initrd_root.ctime = initrd_root.mtime = clock_boot(); - InitRD::Directory& root = dirs[0]; - total_dirs++; - strncpy(initrd_root.name, "initrd", sizeof(initrd_root.name)); - strncpy(root.name, "initrd", sizeof(root.name)); - initrd_root.find_func = initrd_scan_dir; - initrd_root.mkdir_func = initrd_mkdir; - initrd_root.readdir_func = initrd_read_dir; -} - -void InitRD::init() -{ - initrd_base = MemoryManager::get_unaligned_mappings( - (void*)bootboot.initrd_ptr, Utilities::get_blocks_from_size(PAGE_SIZE, bootboot.initrd_size)) - .release_value(); // FIXME: Propagate errors. - kdbgln("physical base at %lx, size %lx, mapped to %p", bootboot.initrd_ptr, bootboot.initrd_size, initrd_base); - kdbgln("total blocks: %ld", get_total_blocks()); - void* leak = kmalloc(4); // leak some memory so that kmalloc doesn't continously allocate and free pages - initrd_initialize_root(); - initrd_scan(); - VFS::mount_root(&initrd_root); - initrd_initialized = true; - kfree(leak); -} \ No newline at end of file diff --git a/kernel/src/fs/TmpFS.cpp b/kernel/src/fs/TmpFS.cpp deleted file mode 100644 index e4e5fccb..00000000 --- a/kernel/src/fs/TmpFS.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#define MODULE "tmpfs" - -#include "fs/TmpFS.h" -#include "log/Log.h" -#include "memory/MemoryManager.h" -#include "misc/utils.h" -#include "std/errno.h" -#include "std/string.h" -#include "utils/Dynamic.h" -#include "utils/move.h" - -namespace TmpFS -{ - struct File - { - void* ptr; - uint64_t pages; - uint64_t length; - }; - - struct Directory - { - Dynamic files; - }; -} - -VFS::Node* tmpfs_root = nullptr; - -Dynamic tmpfs_dirs; -Dynamic tmpfs_files; - -extern uint64_t clock_now(); - -static bool resize_file(TmpFS::File& file, size_t new_size) -{ - size_t pages = Utilities::get_blocks_from_size(PAGE_SIZE, new_size); - if (pages > file.pages) // resize only if we need a bigger chunk of memory - { - auto rc = MemoryManager::get_pages(pages, MAP_READ_WRITE); - if (rc.has_error()) return false; - void* new_ptr = rc.release_value(); - if (file.ptr) - { - memcpy(new_ptr, file.ptr, file.length); - MemoryManager::release_pages(file.ptr, file.pages); - } - file.pages = pages; - file.ptr = new_ptr; - } - file.length = new_size; - return true; -} - -VFS::Node* TmpFS::get() -{ - if (tmpfs_root) return tmpfs_root; - kinfoln("initializing tmpfs instance"); - tmpfs_root = new VFS::Node; - tmpfs_root->length = 0; - tmpfs_root->inode = 0; - tmpfs_root->type = VFS_DIRECTORY; - tmpfs_root->find_func = TmpFS::finddir; - tmpfs_root->readdir_func = TmpFS::readdir; - tmpfs_root->mkdir_func = TmpFS::mkdir; - tmpfs_root->create_func = TmpFS::create; - tmpfs_root->mode = 0777; - tmpfs_root->uid = tmpfs_root->gid = 0; - tmpfs_root->atime = tmpfs_root->ctime = tmpfs_root->mtime = clock_now(); - strncpy(tmpfs_root->name, "tmpfs", sizeof(tmpfs_root->name)); - tmpfs_dirs.ensure_capacity(16); - tmpfs_files.ensure_capacity(16); - tmpfs_dirs.set_expand_rate(16); - tmpfs_files.set_expand_rate(16); - ensure(tmpfs_dirs.push({{}})); - return tmpfs_root; -} - -VFS::Node* TmpFS::finddir(VFS::Node* node, const char* filename) -{ - if (!node) return nullptr; - if (node->inode >= tmpfs_dirs.size()) return nullptr; - auto& dir = tmpfs_dirs[node->inode]; - kdbgln("searching for '%s' in '%s'", filename, node->name); - for (size_t i = 0; i < dir.files.size(); i++) - { - if (!strncmp(dir.files[i]->name, filename, sizeof(dir.files[i]->name))) return dir.files[i]; - } - return nullptr; -} - -VFS::Node* TmpFS::readdir(VFS::Node* node, long offset) -{ - if (!node) return nullptr; - if (node->inode >= tmpfs_dirs.size()) return nullptr; - auto& dir = tmpfs_dirs[node->inode]; - if (offset < 0) return nullptr; - if ((size_t)offset >= dir.files.size()) return nullptr; - kdbgln("reading offset %ld in '%s'", offset, node->name); - return dir.files[offset]; -} - -int TmpFS::mkdir(VFS::Node* node, const char* name, mode_t mode) -{ - if (node->inode >= tmpfs_dirs.size()) return -EINVAL; - if (!(node->type & VFS_DIRECTORY)) return -ENOTDIR; - auto& parent = tmpfs_dirs[node->inode]; - VFS::Node* new_node = new VFS::Node; - new_node->inode = tmpfs_dirs.size(); - new_node->find_func = TmpFS::finddir; - new_node->readdir_func = TmpFS::readdir; - new_node->mkdir_func = TmpFS::mkdir; - new_node->create_func = TmpFS::create; - new_node->length = 0; - new_node->type = VFS_DIRECTORY; - new_node->mode = mode; - new_node->uid = new_node->gid = 0; - new_node->atime = new_node->ctime = new_node->mtime = clock_now(); - strncpy(new_node->name, name, sizeof(new_node->name)); - ensure(parent.files.push( - new_node)); // We have to push the new node to the parent BEFORE we push the directory object to the list of - // tmpfs directories. This is crucial, since pushing to the list of tmpfs directories could relocate - // said list, where the parent object is stored, while we would still be using the old parent - // object. Thus our changes to the parent would be erased as soon as we exit this function. - ensure(tmpfs_dirs.push({{}})); // FIXME: Handle OOM instead of panicking - node->length++; - kdbgln("created directory '%s' in '%s' (which now has %lu entries), mode %o", name, node->name, node->length, mode); - return 0; -} - -VFS::Node* TmpFS::create(VFS::Node* node, const char* name, mode_t mode, uid_t uid, gid_t gid) -{ - if (node->inode >= tmpfs_dirs.size()) return nullptr; - if (!(node->type & VFS_DIRECTORY)) return nullptr; - auto& parent = tmpfs_dirs[node->inode]; - VFS::Node* new_node = new VFS::Node; - new_node->inode = tmpfs_files.size(); - new_node->length = 0; - new_node->read_func = TmpFS::read; - new_node->write_func = TmpFS::write; - new_node->type = VFS_FILE; - new_node->mode = mode; - new_node->uid = uid; - new_node->gid = gid; - new_node->atime = new_node->ctime = new_node->mtime = clock_now(); - strncpy(new_node->name, name, sizeof(new_node->name)); - ensure(parent.files.push( - new_node)); // We have to push the new node to the parent BEFORE we push the directory object to the list of - // tmpfs directories. This is crucial, since pushing to the list of tmpfs directories could relocate - // said list, where the parent object is stored, while we would still be using the old parent - // object. Thus our changes to the parent would be erased as soon as we exit this function. - ensure(tmpfs_files.push({nullptr, 0, 0})); // FIXME: Handle OOM instead of panicking - node->length++; - kdbgln("created file '%s' in '%s' (which now has %lu entries), mode %o", name, node->name, node->length, mode); - return 0; -} - -ssize_t TmpFS::read(VFS::Node* node, size_t offset, size_t length, char* buffer) -{ - kdbgln("got to read()"); - if (!node) return -1; - if (node->inode >= tmpfs_files.size()) return -1; - File& file = tmpfs_files[node->inode]; - size_t old_len = length; - if (offset > file.length) return -1; - if (offset + length > file.length) { length = file.length - offset; } - kdbgln("reading %zu bytes from '%s' at offset %zu (requested length was %zu)", length, node->name, offset, old_len); - memcpy(buffer, (void*)((uintptr_t)file.ptr + offset), length); - return length; -} - -ssize_t TmpFS::write(VFS::Node* node, size_t offset, size_t length, const char* buffer) -{ - if (!node) return -1; - if (node->inode >= tmpfs_files.size()) return -1; - File& file = tmpfs_files[node->inode]; - size_t new_length = file.length; - if (offset + length > file.length) new_length = offset + length; - if (new_length != file.length) - { - if (!resize_file(file, new_length)) return -ENOMEM; - node->length = new_length; - } - kdbgln("writing %zu bytes to '%s' at offset %zu", length, node->name, offset); - memcpy((void*)((uintptr_t)file.ptr + offset), buffer, length); - return length; -} \ No newline at end of file diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp deleted file mode 100644 index 0d186efa..00000000 --- a/kernel/src/fs/VFS.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#define MODULE "vfs" - -#include "fs/VFS.h" -#include "log/Log.h" -#include "std/errno.h" -#include "std/libgen.h" -#include "std/stdlib.h" -#include "std/string.h" - -static VFS::Node* vfs_root; - -int VFS::would_block(Node* node) -{ - if (!node) { return 0; } - if (!node->block_func) { return 0; } - return node->block_func(node); -} - -ssize_t VFS::read(Node* node, size_t offset, size_t length, char* buffer) -{ - if (!node) - { - kwarnln("read() failed: trying to read from nullptr"); - return -1; - } - if (node->type == VFS_DIRECTORY) - { - kwarnln("read() failed: is a directory"); - return -EISDIR; - } - if (!node->read_func) - { - kwarnln("read() failed: the chosen node doesn't support reading"); - return -1; - } - - return node->read_func(node, offset, length, buffer); -} - -ssize_t VFS::write(Node* node, size_t offset, size_t length, const char* buffer) -{ - if (!node) - { - kwarnln("write() failed: trying to write to nullptr"); - return -1; - } - if (node->type == VFS_DIRECTORY) - { - kwarnln("write() failed: is a directory"); - return -EISDIR; - } - if (!node->write_func) - { - kwarnln("write() failed: the chosen node doesn't support writing"); - return -1; - } - - return node->write_func(node, offset, length, buffer); -} - -void VFS::mount_root(Node* root) -{ - if (!root) - { - kwarnln("mount_root() failed: attempted to mount nullptr"); - return; - } - if (vfs_root) - { - kwarnln("mount_root() failed: root filesystem already mounted"); - return; - } - kinfoln("mounting node '%s' as vfs root", root->name); - vfs_root = root; -} - -VFS::Node* VFS::root() -{ - return vfs_root; -} - -VFS::Node* VFS::resolve_path(const char* filename, Node* root) -{ - if (!root) root = vfs_root; - - if (strlen(filename) == 0) return 0; - if (*filename == '/') // Absolute path. - { - filename++; - root = vfs_root; - } - - Node* current_node = root; - - while (true) - { - while (*filename == '/') { filename++; } - if (*filename == 0) { return current_node; } - - size_t path_section_size = 0; - while (filename[path_section_size] && filename[path_section_size] != '/') { path_section_size++; } - - if (strncmp(filename, ".", path_section_size) != 0) // The current path section is not '.' - { - char* buffer = (char*)kmalloc(path_section_size + 1); - memcpy(buffer, filename, path_section_size); - buffer[path_section_size] = 0; - if (!current_node->find_func) - { - kwarnln("Current node has no way to find child nodes"); - return 0; - } - Node* child = current_node->find_func(current_node, buffer); - if (!child) { return 0; } - if (child->flags & VFS_MOUNTPOINT) - { - if (!child->link) - { - kwarnln("Current node's link is null"); - return 0; - } - child = child->link; - } - current_node = child; - kfree(buffer); - } - - filename += path_section_size; - } -} - -VFS::Node* VFS::resolve_parent(const char* filename, Node* root) -{ - char* dir = better_dirname(filename); - auto* result = resolve_path(dir, root); - kfree(dir); - return result; -} - -int VFS::mkdir(const char* path, const char* name) -{ - Node* node = resolve_path(path, vfs_root); - if (!node) - { - kwarnln("Attempting to mkdir in %s, which does not exist", path); - return -ENOENT; - } - if (node->type != VFS_DIRECTORY) - { - kwarnln("Attempting to mkdir in %s, which is not a directory!!", path); - return -ENOTDIR; - } - if (!node->mkdir_func) - { - kwarnln("Chosen node does not support mkdir()"); - return -ENOTSUP; - } - if (!node->find_func) - { - kwarnln("Chosen node does not support finddir()"); - return -ENOTSUP; - } - if (!strncmp(name, ".", strlen(name)) || !strncmp(name, "..", strlen(name))) - { - kwarnln("Attempted to mkdir . or .., which already exist"); - return -EEXIST; - } - if (node->find_func(node, name) != nullptr) - { - kwarnln("Already exists"); - return -EEXIST; - } - return node->mkdir_func(node, name, 0755); -} - -int VFS::do_mkdir(const char* path, const char* name, int uid, int gid, mode_t mode) -{ - Node* node = resolve_path(path, vfs_root); - if (!node) - { - kwarnln("Attempting to mkdir in %s, which does not exist", path); - return -ENOENT; - } - if (node->type != VFS_DIRECTORY) - { - kwarnln("Attempting to mkdir in %s, which is not a directory!!", path); - return -ENOTDIR; - } - if (!node->mkdir_func) - { - kwarnln("Chosen node does not support mkdir()"); - return -ENOTSUP; - } - if (!node->find_func) - { - kwarnln("Chosen node does not support finddir()"); - return -ENOTSUP; - } - if (!strncmp(name, ".", strlen(name)) || !strncmp(name, "..", strlen(name))) - { - kwarnln("Attempted to mkdir . or .., which already exist"); - return -EEXIST; - } - if (node->find_func(node, name) != nullptr) - { - kwarnln("Already exists"); - return -EEXIST; - } - if (!can_write(node, uid, gid)) - { - kwarnln("Not enough permissions"); - return -EACCES; - } - return node->mkdir_func(node, name, mode); -} - -int VFS::mkdir(const char* pathname) -{ - char* base = better_basename(pathname); - char* dir = better_dirname(pathname); - - kdbgln("mkdir(): creating %s in directory %s", base, dir); - - int result = mkdir(dir, base); - - kfree(base); - kfree(dir); - - return result; -} - -int VFS::do_mkdir(const char* pathname, int uid, int gid, mode_t mode) -{ - char* base = better_basename(pathname); - char* dir = better_dirname(pathname); - - kdbgln("mkdir(): creating %s in directory %s", base, dir); - - int result = do_mkdir(dir, base, uid, gid, mode); - - kfree(base); - kfree(dir); - - return result; -} - -Result VFS::create(const char* pathname, mode_t mode, uid_t uid, gid_t gid) -{ - VFS::Node* parent = VFS::resolve_parent(pathname); - if (!parent) return {ENOENT}; - if (parent->type != VFS_DIRECTORY) - { - kwarnln("Attempting to create %s, parent is not a directory", pathname); - return {ENOTDIR}; - } - if (!parent->create_func) - { - kwarnln("Chosen node does not support create()"); - return {ENOTSUP}; // FIXME: Probably EROFS. - } - if (!parent->find_func) - { - kwarnln("Chosen node does not support finddir()"); - return {ENOTSUP}; - } - if (!can_write(parent, uid, gid)) return {EACCES}; - char* child = better_basename(pathname); - if (parent->find_func(parent, child)) - { - kwarnln("Already exists"); - kfree(child); - return {EEXIST}; - } - VFS::Node* child_node = parent->create_func(parent, child, mode, uid, gid); - kfree(child); - return child_node; -} - -bool VFS::exists(const char* pathname) -{ - return resolve_path(pathname) != nullptr; -} - -void VFS::mount(Node* mountpoint, Node* mounted) -{ - if (!mountpoint || !mounted) return; - if (mountpoint->flags & VFS_MOUNTPOINT || mounted->flags & VFS_MOUNTPOINT) return; - mountpoint->link = mounted; - mountpoint->flags |= VFS_MOUNTPOINT; -} - -void VFS::mount(const char* pathname, Node* mounted) -{ - return mount(resolve_path(pathname), mounted); -} - -void VFS::unmount(Node* mountpoint) -{ - if (!mountpoint) return; - if (!(mountpoint->flags & VFS_MOUNTPOINT)) return; - mountpoint->flags &= ~VFS_MOUNTPOINT; -} - -VFS::Node* VFS::readdir(VFS::Node* dir, long offset) -{ - if (!dir) return 0; - if (!dir->readdir_func) return 0; - return dir->readdir_func(dir, offset); -} - -bool VFS::can_execute(VFS::Node* node, int uid, int gid) -{ - if (uid == node->uid) return node->mode & 0100; - if (gid == node->gid) return node->mode & 0010; - return node->mode & 0001; -} - -bool VFS::can_write(VFS::Node* node, int uid, int gid) -{ - if (uid == node->uid) return node->mode & 0200; - if (gid == node->gid) return node->mode & 0020; - return node->mode & 0002; -} - -bool VFS::can_read(VFS::Node* node, int uid, int gid) -{ - if (uid == node->uid) return node->mode & 0400; - if (gid == node->gid) return node->mode & 0040; - return node->mode & 0004; -} - -bool VFS::is_setuid(VFS::Node* node) -{ - return node->mode & 04000; -} - -bool VFS::is_setgid(VFS::Node* node) -{ - return node->mode & 02000; -} \ No newline at end of file diff --git a/kernel/src/fs/devices/Console.cpp b/kernel/src/fs/devices/Console.cpp deleted file mode 100644 index 2eaeafc2..00000000 --- a/kernel/src/fs/devices/Console.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "fs/devices/Console.h" -#include "config.h" -#include "render/TextRenderer.h" -#include "std/stdio.h" -#include "std/stdlib.h" -#include "std/string.h" - -char* conin_buffer = nullptr; -uint64_t conin_bufsize = 0; - -int ConsoleDevice::would_block(VFS::Node*) -{ - return conin_bufsize == 0; -} - -extern uint64_t clock_now(); - -VFS::Node* ConsoleDevice::create_new(const char* devname) -{ - VFS::Node* dev = new VFS::Node; - dev->write_func = ConsoleDevice::write; - dev->read_func = ConsoleDevice::read; - dev->block_func = ConsoleDevice::would_block; - dev->inode = 0; - dev->length = 0; - dev->type = VFS_DEVICE; - dev->flags = 0; - dev->tty = 1; - dev->uid = dev->gid = 0; - dev->mode = 0666; - dev->atime = dev->ctime = dev->mtime = clock_now(); - strncpy(dev->name, devname, sizeof(dev->name)); - return dev; -} - -ssize_t ConsoleDevice::write(VFS::Node* node, size_t, size_t size, const char* buffer) -{ - if (!node) return -1; - TextRenderer::write(buffer, size); - return (ssize_t)size; -} - -ssize_t ConsoleDevice::read(VFS::Node* node, size_t, size_t size, char* buffer) -{ - if (!node) return -1; - if (!conin_buffer) return 0; - if (size > conin_bufsize) size = conin_bufsize; - memcpy(buffer, conin_buffer, size); - memmove(conin_buffer, conin_buffer + size, conin_bufsize - size); - conin_bufsize -= size; - conin_buffer = (char*)krealloc(conin_buffer, conin_bufsize); - return (ssize_t)size; -} - -void ConsoleDevice::append(char c) -{ - conin_bufsize++; - conin_buffer = (char*)krealloc( - conin_buffer, conin_bufsize); // FIXME: We should probably not be calling realloc every time a key is pressed. - conin_buffer[conin_bufsize - 1] = c; -} \ No newline at end of file diff --git a/kernel/src/fs/devices/DeviceFS.cpp b/kernel/src/fs/devices/DeviceFS.cpp deleted file mode 100644 index d98cb00f..00000000 --- a/kernel/src/fs/devices/DeviceFS.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "fs/devices/DeviceFS.h" -#include "fs/devices/Console.h" -#include "fs/devices/Framebuffer.h" -#include "fs/devices/Keyboard.h" -#include "fs/devices/NullDevice.h" -#include "fs/devices/Random.h" -#include "fs/devices/Serial.h" -#include "fs/devices/Version.h" -#include "std/stdlib.h" -#include "std/string.h" - -#define DEVFS_MAX_FILES 32 - -VFS::Node* devfs_root = nullptr; - -VFS::Node* devfs_files[DEVFS_MAX_FILES]; -int devfs_file_count = 0; - -extern uint64_t clock_boot(); - -VFS::Node* DeviceFS::get() -{ - if (devfs_root) return devfs_root; - devfs_root = new VFS::Node; - devfs_root->length = 0; - devfs_root->inode = 0; - devfs_root->type = VFS_DIRECTORY; - devfs_root->find_func = DeviceFS::finddir; - devfs_root->readdir_func = DeviceFS::readdir; - devfs_root->mode = 0755; - devfs_root->uid = devfs_root->gid = 0; - devfs_root->atime = devfs_root->ctime = devfs_root->mtime = clock_boot(); - strncpy(devfs_root->name, "dev", sizeof(devfs_root->name)); - - devfs_files[devfs_file_count++] = VersionDevice::create_new("version"); - devfs_files[devfs_file_count++] = ConsoleDevice::create_new("console"); - devfs_files[devfs_file_count++] = SerialDevice::create_new("serial"); - devfs_files[devfs_file_count++] = RandomDevice::create_new("random"); - devfs_files[devfs_file_count++] = KeyboardDevice::create_new("kbd"); - devfs_files[devfs_file_count++] = NullDevice::create_new("null"); - devfs_files[devfs_file_count++] = FramebufferDevice::create_new("fb0"); - devfs_root->length = devfs_file_count; - return devfs_root; -} - -VFS::Node* DeviceFS::finddir(VFS::Node* node, const char* filename) -{ - if (!node) return 0; - for (int i = 0; i < devfs_file_count; i++) - { - if (strncmp(devfs_files[i]->name, filename, sizeof(VFS::Node::name)) == 0) { return devfs_files[i]; } - } - return 0; -} - -VFS::Node* DeviceFS::readdir(VFS::Node* node, long offset) -{ - if (!node) return 0; - if (offset >= devfs_file_count) return 0; - return devfs_files[offset]; -} \ No newline at end of file diff --git a/kernel/src/fs/devices/Framebuffer.cpp b/kernel/src/fs/devices/Framebuffer.cpp deleted file mode 100644 index b6175650..00000000 --- a/kernel/src/fs/devices/Framebuffer.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "fs/devices/Framebuffer.h" -#include "bootboot.h" -#include "memory/MemoryManager.h" -#include "misc/utils.h" -#include "std/errno.h" -#include "std/stdio.h" -#include "std/stdlib.h" -#include "std/string.h" -#include "utils/Addresses.h" - -extern BOOTBOOT bootboot; -extern char fb[1]; - -#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno) - -extern uint64_t clock_now(); - -VFS::Node* FramebufferDevice::create_new(const char* devname) -{ - VFS::Node* dev = new VFS::Node; - dev->write_func = FramebufferDevice::write; - dev->mmap_func = FramebufferDevice::mmap; - dev->ioctl_func = FramebufferDevice::ioctl; - dev->inode = 0; - dev->length = 0; - dev->type = VFS_DEVICE; - dev->flags = 0; - dev->uid = dev->gid = 0; - dev->mode = 0222; - dev->atime = dev->ctime = dev->mtime = clock_now(); - strncpy(dev->name, devname, sizeof(dev->name)); - return dev; -} - -uintptr_t FramebufferDevice::mmap(VFS::Node* node, uintptr_t addr, size_t size, int prot, off_t offset) -{ - if (!node) return -1; - int real_prot = prot & ~(MAP_AS_OWNED_BY_TASK); - if (round_down_to_nearest_page(offset) != (uintptr_t)offset) { return MAP_FAIL(EINVAL); } - if ((size + offset) > bootboot.fb_size) - { - return MAP_FAIL(ERANGE); // FIXME: Should probably be EOVERFLOW. - } - MemoryManager::map_several_pages(bootboot.fb_ptr + offset, addr, Utilities::get_blocks_from_size(PAGE_SIZE, size), - real_prot); - return addr; -} - -ssize_t FramebufferDevice::write(VFS::Node* node, size_t offset, size_t size, const char* buffer) -{ - if (!node) return -1; - if ((size + offset) > (uint64_t)bootboot.fb_size) { size = (uint64_t)bootboot.fb_size - offset; } - memcpy(fb + offset, buffer, size); - return (ssize_t)size; -} - -#define FB_GET_WIDTH 0 -#define FB_GET_HEIGHT 1 -#define FB_GET_SCANLINE 2 - -long FramebufferDevice::ioctl(VFS::Node* node, int cmd, uintptr_t) -{ - if (!node) return -1; - switch (cmd) - { - case FB_GET_WIDTH: return (long)bootboot.fb_width; - case FB_GET_HEIGHT: return (long)bootboot.fb_height; - case FB_GET_SCANLINE: return (long)bootboot.fb_scanline; - default: return -EINVAL; - } -} \ No newline at end of file diff --git a/kernel/src/fs/devices/Keyboard.cpp b/kernel/src/fs/devices/Keyboard.cpp deleted file mode 100644 index 8a1813d4..00000000 --- a/kernel/src/fs/devices/Keyboard.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#define MODULE "kbd" - -#include "fs/devices/Keyboard.h" -#include "config.h" -#include "log/Log.h" -#include "render/TextRenderer.h" -#include "std/stdio.h" -#include "std/stdlib.h" -#include "std/string.h" - -char* kbd_buffer = nullptr; -uint64_t kbd_bufsize = 0; - -int KeyboardDevice::would_block(VFS::Node*) -{ - return kbd_bufsize == 0; -} - -extern uint64_t clock_boot(); - -VFS::Node* KeyboardDevice::create_new(const char* devname) -{ - VFS::Node* dev = new VFS::Node; - dev->read_func = KeyboardDevice::read; - dev->block_func = KeyboardDevice::would_block; - dev->inode = 0; - dev->length = 0; - dev->type = VFS_DEVICE; - dev->flags = 0; - dev->tty = 1; - dev->uid = dev->gid = 0; - dev->mode = 0444; - dev->atime = dev->ctime = dev->mtime = clock_boot(); - strncpy(dev->name, devname, sizeof(dev->name)); - return dev; -} - -ssize_t KeyboardDevice::read(VFS::Node* node, size_t, size_t size, char* buffer) -{ - if (!node) return -1; - if (!kbd_buffer) return 0; - if (size > kbd_bufsize) size = kbd_bufsize; - memcpy(buffer, kbd_buffer, size); - memmove(kbd_buffer, kbd_buffer + size, kbd_bufsize - size); - kbd_bufsize -= size; - kbd_buffer = (char*)krealloc(kbd_buffer, kbd_bufsize); - return (ssize_t)size; -} - -void KeyboardDevice::append(char c) -{ - kbd_bufsize++; - kbd_buffer = (char*)krealloc( - kbd_buffer, kbd_bufsize); // FIXME: We should probably not be calling realloc every time a key is pressed. - kbd_buffer[kbd_bufsize - 1] = c; -} \ No newline at end of file diff --git a/kernel/src/fs/devices/NullDevice.cpp b/kernel/src/fs/devices/NullDevice.cpp deleted file mode 100644 index b49b578c..00000000 --- a/kernel/src/fs/devices/NullDevice.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "fs/devices/NullDevice.h" -#include "std/stdio.h" -#include "std/stdlib.h" -#include "std/string.h" - -extern uint64_t clock_boot(); - -VFS::Node* NullDevice::create_new(const char* devname) -{ - VFS::Node* dev = new VFS::Node; - dev->write_func = NullDevice::write; - dev->read_func = NullDevice::read; - dev->inode = 0; - dev->length = 0; - dev->type = VFS_DEVICE; - dev->flags = 0; - dev->uid = dev->gid = 0; - dev->mode = 0666; - dev->atime = dev->ctime = dev->mtime = clock_boot(); - strncpy(dev->name, devname, sizeof(dev->name)); - return dev; -} - -ssize_t NullDevice::write(VFS::Node* node, size_t, size_t size, const char*) -{ - if (!node) return -1; - return (ssize_t)size; -} - -ssize_t NullDevice::read(VFS::Node* node, size_t, size_t, char*) -{ - if (!node) return -1; - return 0; -} \ No newline at end of file diff --git a/kernel/src/fs/devices/Random.cpp b/kernel/src/fs/devices/Random.cpp deleted file mode 100644 index 0cc8c27b..00000000 --- a/kernel/src/fs/devices/Random.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "fs/devices/Random.h" -#include "config.h" -#include "rand/Mersenne.h" -#include "render/TextRenderer.h" -#include "std/stdio.h" -#include "std/stdlib.h" -#include "std/string.h" - -extern uint64_t clock_boot(); - -VFS::Node* RandomDevice::create_new(const char* devname) -{ - VFS::Node* dev = new VFS::Node; - dev->read_func = RandomDevice::read; - dev->inode = 0; - dev->length = 0; - dev->type = VFS_DEVICE; - dev->flags = 0; - dev->uid = dev->gid = 0; - dev->mode = 0444; - dev->atime = dev->ctime = dev->mtime = clock_boot(); - strncpy(dev->name, devname, sizeof(dev->name)); - return dev; -} - -ssize_t RandomDevice::read(VFS::Node* node, size_t, size_t size, char* buffer) -{ - if (!node) return -1; - size_t nread = size; - while (size >= sizeof(uint64_t)) - { - *(uint64_t*)buffer = Mersenne::get(); - size -= sizeof(uint64_t); - buffer += sizeof(uint64_t); - } - while (size) - { - *buffer = (char)(Mersenne::get() & 0xFF); - size--; - buffer++; - } - return (ssize_t)nread; -} \ No newline at end of file diff --git a/kernel/src/fs/devices/Serial.cpp b/kernel/src/fs/devices/Serial.cpp deleted file mode 100644 index b8675fff..00000000 --- a/kernel/src/fs/devices/Serial.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "io/Serial.h" -#include "config.h" -#include "fs/devices/Serial.h" -#include "std/stdio.h" -#include "std/stdlib.h" -#include "std/string.h" - -extern uint64_t clock_boot(); - -VFS::Node* SerialDevice::create_new(const char* devname) -{ - VFS::Node* dev = new VFS::Node; - dev->write_func = SerialDevice::write; - dev->inode = 0; - dev->length = 0; - dev->type = VFS_DEVICE; - dev->flags = 0; - dev->uid = dev->gid = 0; - dev->mode = 0222; - dev->atime = dev->ctime = dev->mtime = clock_boot(); - strncpy(dev->name, devname, sizeof(dev->name)); - return dev; -} - -ssize_t SerialDevice::write(VFS::Node* node, size_t, size_t size, const char* buffer) -{ - if (!node) return -1; - Serial::write(buffer, size); - return (ssize_t)size; -} \ No newline at end of file diff --git a/kernel/src/fs/devices/Version.cpp b/kernel/src/fs/devices/Version.cpp deleted file mode 100644 index 0a1ac394..00000000 --- a/kernel/src/fs/devices/Version.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "fs/devices/Version.h" -#include "config.h" -#include "std/stdio.h" -#include "std/stdlib.h" -#include "std/string.h" - -extern uint64_t clock_boot(); - -VFS::Node* VersionDevice::create_new(const char* devname) -{ - VFS::Node* dev = new VFS::Node; - dev->read_func = VersionDevice::read; - dev->inode = 0; - dev->length = strlen(moon_version()) + 5; - dev->type = VFS_DEVICE; - dev->flags = 0; - dev->uid = dev->gid = 0; - dev->mode = 0444; - dev->atime = dev->ctime = dev->mtime = clock_boot(); - strncpy(dev->name, devname, sizeof(dev->name)); - return dev; -} - -ssize_t VersionDevice::read(VFS::Node* node, size_t offset, size_t size, char* buffer) -{ - if (!node) return -1; - if (offset > 0) return 0; // EOF after first read (FIXME: Should be only if everything was read) - snprintf(buffer, size + 1, "moon %s", moon_version()); // FIXME: Support offseting this read - return (ssize_t)size; -} \ No newline at end of file diff --git a/kernel/src/gdt/GDT.asm b/kernel/src/gdt/GDT.asm deleted file mode 100644 index 171debdb..00000000 --- a/kernel/src/gdt/GDT.asm +++ /dev/null @@ -1,21 +0,0 @@ -global load_gdt -load_gdt: - cli - lgdt [rdi] - mov ax, 0x10 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax - push 0x08 - lea rax, [rel .reload_CS] - push rax - retfq -.reload_CS: - ret -global load_tr -load_tr: - mov rax, rdi - ltr ax - ret \ No newline at end of file diff --git a/kernel/src/gdt/GDT.cpp b/kernel/src/gdt/GDT.cpp deleted file mode 100644 index 0c2ecca4..00000000 --- a/kernel/src/gdt/GDT.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#define MODULE "gdt" - -#include "gdt/GDT.h" -#include "log/Log.h" -#include "memory/MemoryManager.h" -#include "std/ensure.h" -#include "std/string.h" -#include "utils/Addresses.h" -#include - -struct GDTR -{ - uint16_t size; - uint64_t offset; -} __attribute__((packed)); - -struct GDTEntry -{ - uint16_t limit0; - uint16_t base0; - uint8_t base1; - uint8_t access; - uint8_t limit1_flags; - uint8_t base2; -} __attribute__((packed)); - -struct HighGDTEntry -{ - uint32_t base_high; - uint32_t reserved; -} __attribute__((packed)); - -struct TSS -{ - uint32_t reserved0; - uint64_t rsp[3]; - uint64_t reserved1; - uint64_t ist[7]; - uint64_t reserved2; - uint16_t reserved3; - uint16_t iomap_base; -} __attribute__((packed)); - -struct InternalGDT -{ - GDTEntry null; - GDTEntry kernel_code; - GDTEntry kernel_data; - GDTEntry user_code; - GDTEntry user_data; - GDTEntry tss; - HighGDTEntry tss2; -} __attribute__((packed)) __attribute((aligned(PAGE_SIZE))); - -__attribute__((aligned(PAGE_SIZE))) static InternalGDT internal_gdt = {{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00}, - {0xffff, 0x0000, 0x00, 0x9a, 0xaf, 0x00}, - {0xffff, 0x0000, 0x00, 0x92, 0xcf, 0x00}, - {0xffff, 0x0000, 0x00, 0xfa, 0xaf, 0x00}, - {0xffff, 0x0000, 0x00, 0xf2, 0xcf, 0x00}, - {0x0000, 0x0000, 0x00, 0xe9, 0x0f, 0x00}, - {0x00000000, 0x00000000}}; - -static TSS main_tss; - -extern "C" void load_gdt(GDTR* gdtr); -extern "C" void load_tr(int segment); - -static void set_base(GDTEntry* entry, uint32_t base) -{ - entry->base0 = (base & 0xFFFF); - entry->base1 = (base >> 16) & 0xFF; - entry->base2 = (uint8_t)((base >> 24) & 0xFF); -} - -static void set_limit(GDTEntry* entry, uint32_t limit) -{ - ensure(limit <= 0xFFFFF); - entry->limit0 = limit & 0xFFFF; - entry->limit1_flags = (entry->limit1_flags & 0xF0) | ((limit >> 16) & 0xF); -} - -static void set_tss_base(GDTEntry* tss1, HighGDTEntry* tss2, uint64_t addr) -{ - set_base(tss1, addr & 0xffffffff); - tss2->base_high = (uint32_t)(addr >> 32); -} - -static void setup_tss() -{ - memset(&main_tss, 0, sizeof(TSS)); - main_tss.rsp[0] = get_top_of_stack((uint64_t)MemoryManager::get_pages(4).release_value(), - 4); // FIXME: Propagate errors, we should use 1 kernel stack - // per task, and it probably shouldn't be so big. - main_tss.iomap_base = sizeof(TSS); - set_tss_base(&internal_gdt.tss, &internal_gdt.tss2, (uint64_t)&main_tss); - set_limit(&internal_gdt.tss, sizeof(TSS) - 1); -} - -static void load_tss() -{ - kdbgln("Loading TR (GDT entry 0x2b)"); - load_tr(0x2b); -} - -void GDT::load() -{ - static GDTR gdtr; - gdtr.offset = (uint64_t)&internal_gdt; - gdtr.size = sizeof(InternalGDT); - setup_tss(); - kdbgln("Loading GDT at offset %lx, size %d", gdtr.offset, gdtr.size); - load_gdt(&gdtr); - load_tss(); -} \ No newline at end of file diff --git a/kernel/src/init/Init.cpp b/kernel/src/init/Init.cpp deleted file mode 100644 index 15ba82c1..00000000 --- a/kernel/src/init/Init.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#define MODULE "init" - -#include "init/Init.h" -#include "bootboot.h" -#include "cpu/CPU.h" -#include "fs/InitRD.h" -#include "interrupts/Interrupts.h" -#include "io/Serial.h" -#include "log/Log.h" -#include "memory/MemoryManager.h" -#include "memory/PMM.h" -#include "memory/VMM.h" -#include "misc/MSR.h" -#include "misc/hang.h" -#include "rand/Init.h" -#include "rand/Mersenne.h" -#include "render/Framebuffer.h" -#include "render/TextRenderer.h" -#include "std/ensure.h" -#include "std/string.h" -#include "utils/Time.h" - -extern BOOTBOOT bootboot; -extern "C" char environment[4096]; -extern uintptr_t fb; - -uintptr_t __stack_chk_guard = 0xfeff34; - -void Init::check_magic() -{ - if (strncmp((char*)bootboot.magic, BOOTBOOT_MAGIC, 4) != 0) hang(); -} - -void Init::disable_smp() -{ - if (CPU::get_initial_apic_id() != bootboot.bspid) { hang(); } - return; -} - -extern "C" void asm_enable_sse(); -extern void clock_init(); - -extern void panic_prepare_keyboard_triple_fault(); - -#define NO_EXECUTE_ENABLED (1 << 11) - -static void check_and_enable_nx() -{ - if (!CPU::has_nx()) - { - kerrorln("This machine does not support the NX feature, which is required to continue booting."); - kerrorln("On most cases, this means your machine is too old and not supported."); - - kinfoln("Press any key to restart and select an OS that is suitable for your CPU."); - - panic_prepare_keyboard_triple_fault(); - - while (1) halt(); - } - - kdbgln("nx supported"); - - MSR efer(IA32_EFER_MSR); - - uint64_t value = efer.read(); - - if (value & NO_EXECUTE_ENABLED) - { - kdbgln("nx already enabled"); - return; - } - - kdbgln("nx not enabled, enabling it"); - - efer.write(value | NO_EXECUTE_ENABLED); -} - -void Init::early_init() -{ - Interrupts::disable(); - asm volatile("cld"); - - asm_enable_sse(); - - framebuffer0.init((void*)&fb, bootboot.fb_type, bootboot.fb_scanline, bootboot.fb_width, bootboot.fb_height); - - check_and_enable_nx(); - - MemoryManager::init(); - - MemoryManager::protect_kernel_sections(); - - if (strstr(environment, "quiet=1")) - { - KernelLog::toggle_log_level(LogLevel::DEBUG); - KernelLog::toggle_log_level(LogLevel::INFO); - } - else if (!strstr(environment, "verbose=1")) { KernelLog::toggle_log_level(LogLevel::DEBUG); } - - clock_init(); - - InitRD::init(); - - Mersenne::init(); - - kdbgln("Page bitmap uses %ld bytes of memory", PMM::get_bitmap_size()); - - __stack_chk_guard = Mersenne::get(); -} - -void Init::finish_kernel_boot() -{ - KernelLog::toggle_log_backend(Backend::Console); - framebuffer0.clear(Color::Black); - TextRenderer::reset(); -} \ No newline at end of file diff --git a/kernel/src/interrupts/Entry.cpp b/kernel/src/interrupts/Entry.cpp deleted file mode 100644 index d69750e6..00000000 --- a/kernel/src/interrupts/Entry.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#define MODULE "isr" - -#include "interrupts/Context.h" -#include "interrupts/IRQ.h" -#include "interrupts/Interrupts.h" -#include "io/Serial.h" -#include "log/Log.h" -#include "memory/VMM.h" -#include "misc/hang.h" -#include "panic/Panic.h" -#include "std/ensure.h" -#include "std/stdio.h" -#include "sys/Syscall.h" -#include "thread/Scheduler.h" -#include "trace/StackTracer.h" -#include "utils/PageFaultReason.h" - -extern "C" void common_handler(Context* context) -{ - ensure(Interrupts::is_in_handler()); - if (context->number >= 0x20 && context->number < 0x30) - { - IRQ::interrupt_handler(context); - return; - } - if (context->number == 13) - { - Interrupts::disable(); - - if (context->cs == 0x8) { int_panic(context, "GPF in kernel task"); } - else - { - VMM::enter_syscall_context(); - - kerrorln("General protection fault at RIP %lx, cs %ld, ss %ld, RSP %lx, error code %ld", context->rip, - context->cs, context->ss, context->rsp, context->error_code); - kinfoln("Stack trace:"); - - StackTracer tracer(context->rbp); - tracer.trace_with_ip(context->rip); - Scheduler::task_misbehave(context, -2); - } - } - if (context->number == 14) - { - Interrupts::disable(); - - if (context->cs == 0x8) { int_panic(context, "Page fault in kernel task"); } - else - { - VMM::enter_syscall_context(); - - kerrorln("Page fault in ring 3 (RIP %lx), while trying to access %lx, error code %ld", context->rip, - context->cr2, context->error_code); - kinfoln("Stack trace:"); - - StackTracer tracer(context->rbp); - tracer.trace_with_ip(context->rip); - - determine_user_page_fault_reason(context->cr2); - - Scheduler::task_misbehave(context, -3); - } - } - if (context->number == 8) { int_panic(context, "Double fault, halting"); } - if (context->number == 66) { Syscall::entry(context); } - if (context->number == 256) { kwarnln("Unused interrupt"); } - return; -} \ No newline at end of file diff --git a/kernel/src/interrupts/IDT.cpp b/kernel/src/interrupts/IDT.cpp deleted file mode 100644 index 4fba0569..00000000 --- a/kernel/src/interrupts/IDT.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#define MODULE "idt" - -#include "interrupts/IDT.h" -#include "log/Log.h" -#include "std/ensure.h" - -struct IDTEntry -{ - uint16_t offset0; - uint16_t selector; - uint8_t ist; - uint8_t type_attr; - uint16_t offset1; - uint32_t offset2; - uint32_t ignore; - void set_offset(uint64_t offset); - uint64_t get_offset(); -}; - -static IDTEntry entries[256]; - -void IDTEntry::set_offset(uint64_t offset) -{ - offset0 = (uint16_t)(offset & 0x000000000000ffff); - offset1 = (uint16_t)((offset & 0x00000000ffff0000) >> 16); - offset2 = (uint32_t)((offset & 0xffffffff00000000) >> 32); -} - -uint64_t IDTEntry::get_offset() -{ - uint64_t offset = 0; - offset |= (uint64_t)offset0; - offset |= (uint64_t)offset1 << 16; - offset |= (uint64_t)offset2 << 32; - return offset; -} - -void IDT::add_handler(short interrupt_number, void* handler, uint8_t type_attr) -{ - ensure(handler != nullptr); - ensure(interrupt_number < 256); - IDTEntry* entry_for_handler = &entries[interrupt_number]; - entry_for_handler->selector = 0x08; - entry_for_handler->type_attr = type_attr; - entry_for_handler->set_offset((uint64_t)handler); -} - -IDTR idtr; -void IDT::load() -{ - idtr.limit = 0x0FFF; - idtr.offset = (uint64_t)entries; - kdbgln("Loading IDT at offset %lx, limit %d", idtr.offset, idtr.limit); - asm("lidt %0" : : "m"(idtr)); -} \ No newline at end of file diff --git a/kernel/src/interrupts/IRQ.cpp b/kernel/src/interrupts/IRQ.cpp deleted file mode 100644 index 5dcf7d21..00000000 --- a/kernel/src/interrupts/IRQ.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#define MODULE "irq" - -#include "interrupts/IRQ.h" -#include "fs/devices/Console.h" -#include "fs/devices/Keyboard.h" -#include "io/IO.h" -#include "io/PIC.h" -#include "log/Log.h" -#include "misc/Scancodes.h" -#include "rand/Init.h" -#include "std/stdio.h" -#include "thread/PIT.h" -#include "thread/Scheduler.h" - -void IRQ::interrupt_handler(Context* context) -{ - switch (context->irq_number) - { - case 0: - PIT::tick(); - Scheduler::task_tick(context); - break; - case 1: { - unsigned char scancode = IO::inb(0x60); - KeyboardDevice::append((char)scancode); - bool ignore = false; - char key = translate_scancode(scancode, &ignore); - if (ignore) break; - ConsoleDevice::append(key); - break; - } - default: kwarnln("Unhandled IRQ: %ld", context->irq_number); break; - } - Mersenne::reseed(); - PIC::send_eoi((unsigned char)(context->irq_number & 0xFF)); - return; -} \ No newline at end of file diff --git a/kernel/src/interrupts/Install.cpp b/kernel/src/interrupts/Install.cpp deleted file mode 100644 index 2025af3a..00000000 --- a/kernel/src/interrupts/Install.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "interrupts/Install.h" -#include "interrupts/IDT.h" -#include "log/Log.h" - -extern "C" -{ - void unused(); - void isr0(); - void isr1(); - void isr2(); - void isr3(); - void isr4(); - void isr5(); - void isr6(); - void isr7(); - void isr8(); - void isr10(); - void isr11(); - void isr12(); - void isr13(); - void isr14(); - void isr16(); - void isr17(); - void isr18(); - void isr19(); - void isr20(); - void isr21(); - void isr28(); - void isr29(); - void isr30(); - void isr31(); - void isr32(); - void isr33(); - void isr34(); - void isr35(); - void isr36(); - void isr37(); - void isr38(); - void isr39(); - void isr40(); - void isr41(); - void isr42(); - void isr43(); - void isr44(); - void isr45(); - void isr46(); - void isr47(); - void isr66(); -} - -#define INSTALL_TRAP(x) IDT::add_handler(x, (void*)&isr##x, IDT_TA_TrapGate) -#define INSTALL_UNUSED(x) IDT::add_handler(x, (void*)&unused, IDT_TA_InterruptGate) -#define INSTALL_ISR(x) IDT::add_handler(x, (void*)&isr##x, IDT_TA_InterruptGate) -#define INSTALL_USER_ISR(x) IDT::add_handler(x, (void*)&isr##x, IDT_TA_InterruptGateUser) - -void Interrupts::install() -{ - kdbgln("Installing handler stubs for exceptions (ISRs 0-31)"); - INSTALL_TRAP(0); - INSTALL_TRAP(1); - INSTALL_TRAP(2); - INSTALL_TRAP(3); - INSTALL_TRAP(4); - INSTALL_TRAP(5); - INSTALL_TRAP(6); - INSTALL_TRAP(7); - INSTALL_TRAP(8); - INSTALL_UNUSED(9); - INSTALL_TRAP(10); - INSTALL_TRAP(11); - INSTALL_TRAP(12); - INSTALL_TRAP(13); - INSTALL_TRAP(14); - INSTALL_UNUSED(15); - INSTALL_TRAP(16); - INSTALL_TRAP(17); - INSTALL_TRAP(18); - INSTALL_TRAP(19); - INSTALL_TRAP(20); - INSTALL_TRAP(21); - INSTALL_UNUSED(22); - INSTALL_UNUSED(23); - INSTALL_UNUSED(24); - INSTALL_UNUSED(25); - INSTALL_UNUSED(26); - INSTALL_UNUSED(27); - INSTALL_TRAP(28); - INSTALL_TRAP(29); - INSTALL_TRAP(30); - INSTALL_UNUSED(31); - kdbgln("Installing handler stubs for IRQs (ISRs 32-47)"); - INSTALL_ISR(32); - INSTALL_ISR(33); - INSTALL_ISR(34); - INSTALL_ISR(35); - INSTALL_ISR(36); - INSTALL_ISR(37); - INSTALL_ISR(38); - INSTALL_ISR(39); - INSTALL_ISR(40); - INSTALL_ISR(41); - INSTALL_ISR(42); - INSTALL_ISR(43); - INSTALL_ISR(44); - INSTALL_ISR(45); - INSTALL_ISR(46); - INSTALL_ISR(47); - kdbgln("Installing unused handler stubs for the rest of the IDT"); - for (short i = 48; i < 256; i++) { INSTALL_UNUSED(i); } - kdbgln("Installing syscall handler stub"); - INSTALL_USER_ISR(66); -} \ No newline at end of file diff --git a/kernel/src/interrupts/InterruptEntry.asm b/kernel/src/interrupts/InterruptEntry.asm deleted file mode 100644 index 7ee280e0..00000000 --- a/kernel/src/interrupts/InterruptEntry.asm +++ /dev/null @@ -1,136 +0,0 @@ -%macro ISR 1 - global isr%1 - isr%1: - push byte 0 - push byte %1 - jmp asm_common -%endmacro - -%macro ISR_ERROR 1 - global isr%1 - isr%1: - push byte %1 - jmp asm_common -%endmacro - -%macro IRQ 2 - global isr%1 - isr%1: - push byte %2 - push byte %1 - jmp asm_common -%endmacro - -%macro SOFT 1 - global isr%1 - isr%1: - push byte 0 - push byte %1 - jmp asm_common -%endmacro - -global unused -unused: - push byte 0 - push 256 - jmp asm_common - -extern common_handler - -section .text -global asm_common -asm_common: - cld - push rax - push rbx - push rcx - push rdx - push rbp - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - push r12 - push r13 - push r14 - push r15 - - mov ax, ds - push rax - - mov r8, cr2 - push r8 - - mov rdi, rsp - - call common_handler - -global _asm_interrupt_exit -_asm_interrupt_exit: - - add rsp, 8 - - pop rax - mov ds, ax - mov es, ax - - pop r15 - pop r14 - pop r13 - pop r12 - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rbp - pop rdx - pop rcx - pop rbx - pop rax - add rsp, 16 - iretq - -ISR 0 -ISR 1 -ISR 2 -ISR 3 -ISR 4 -ISR 5 -ISR 6 -ISR 7 -ISR_ERROR 8 -ISR_ERROR 10 -ISR_ERROR 11 -ISR_ERROR 12 -ISR_ERROR 13 -ISR_ERROR 14 -ISR 16 -ISR_ERROR 17 -ISR 18 -ISR 19 -ISR 20 -ISR_ERROR 21 -ISR 28 -ISR_ERROR 29 -ISR_ERROR 30 -IRQ 32, 0 -IRQ 33, 1 -IRQ 34, 2 -IRQ 35, 3 -IRQ 36, 4 -IRQ 37, 5 -IRQ 38, 6 -IRQ 39, 7 -IRQ 40, 8 -IRQ 41, 9 -IRQ 42, 10 -IRQ 43, 11 -IRQ 44, 12 -IRQ 45, 13 -IRQ 46, 14 -IRQ 47, 15 -SOFT 66 \ No newline at end of file diff --git a/kernel/src/interrupts/Interrupts.cpp b/kernel/src/interrupts/Interrupts.cpp deleted file mode 100644 index b57420d8..00000000 --- a/kernel/src/interrupts/Interrupts.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "interrupts/Interrupts.h" -#include "trace/StackTracer.h" -#include "utils/Registers.h" - -void Interrupts::disable() -{ - asm volatile("cli"); -} - -void Interrupts::enable() -{ - asm volatile("sti"); -} - -extern int _asm_interrupt_exit; - -bool Interrupts::is_in_handler() -{ - return stack_trace_contains((uintptr_t)&_asm_interrupt_exit); -} - -void Interrupts::return_from_handler(Context* context) -{ - asm volatile("mov %0, %%rsp\n" - "jmp _asm_interrupt_exit" - : - : "r"(context)); -} - -bool Interrupts::are_enabled() -{ - return (read_rflags() & 0x200) > 0; -} - -static bool saved_interrupt_state; - -void Interrupts::push_and_disable() -{ - saved_interrupt_state = are_enabled(); - disable(); -} - -void Interrupts::push_and_enable() -{ - saved_interrupt_state = are_enabled(); - enable(); -} - -void Interrupts::pop() -{ - if (saved_interrupt_state && !are_enabled()) enable(); - else if (!saved_interrupt_state && are_enabled()) - disable(); -} - -bool Interrupts::were_enabled() -{ - return saved_interrupt_state; -} \ No newline at end of file diff --git a/kernel/src/io/IO.cpp b/kernel/src/io/IO.cpp deleted file mode 100644 index 5eb75688..00000000 --- a/kernel/src/io/IO.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "io/IO.h" - -uint8_t IO::inb(uint16_t port) -{ - uint8_t result; - asm volatile("inb %1, %0" : "=a"(result) : "Nd"(port)); - return result; -} - -void IO::outb(uint16_t port, uint8_t value) -{ - asm volatile("outb %0, %1" : : "a"(value), "Nd"(port)); -} - -uint16_t IO::inw(uint16_t port) -{ - uint16_t result; - asm volatile("inw %1, %0" : "=a"(result) : "Nd"(port)); - return result; -} - -void IO::outw(uint16_t port, uint16_t value) -{ - asm volatile("outw %0, %1" : : "a"(value), "Nd"(port)); -} - -uint32_t IO::inl(uint16_t port) -{ - uint32_t result; - asm volatile("inl %1, %0" : "=a"(result) : "Nd"(port)); - return result; -} - -void IO::outl(uint16_t port, uint32_t value) -{ - asm volatile("outl %0, %1" : : "a"(value), "Nd"(port)); -} - -void IO::delay() -{ - asm volatile("outb %%al, $0x80" : : "a"(0)); -} \ No newline at end of file diff --git a/kernel/src/io/PCI.cpp b/kernel/src/io/PCI.cpp deleted file mode 100644 index f53ee653..00000000 --- a/kernel/src/io/PCI.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#define MODULE "pci" - -#include "io/PCI.h" -#include "io/IO.h" -#include "log/Log.h" -#include "thread/Spinlock.h" - -#define PCI_ADDRESS 0xCF8 -#define PCI_VALUE 0xCFC - -Spinlock pci_lock; - -uint32_t PCI::raw_address(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset) -{ - return 0x80000000 | (bus << 16) | (slot << 11) | (function << 8) | ((offset)&0xFC); -} - -void PCI::raw_write8(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint8_t value) -{ - IO::outl(PCI_ADDRESS, raw_address(bus, slot, function, offset)); - IO::outl(PCI_VALUE, (uint32_t)value); -} - -void PCI::raw_write16(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint16_t value) -{ - IO::outl(PCI_ADDRESS, raw_address(bus, slot, function, offset)); - IO::outl(PCI_VALUE, (uint32_t)value); -} - -void PCI::raw_write32(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint32_t value) -{ - IO::outl(PCI_ADDRESS, raw_address(bus, slot, function, offset)); - IO::outl(PCI_VALUE, value); -} - -uint8_t PCI::raw_read8(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset) -{ - IO::outl(PCI_ADDRESS, raw_address(bus, slot, function, offset)); - return (uint8_t)(IO::inl(PCI_VALUE + (offset & 3)) & 0xFF); -} - -uint16_t PCI::raw_read16(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset) -{ - IO::outl(PCI_ADDRESS, raw_address(bus, slot, function, offset)); - return (uint16_t)(IO::inl(PCI_VALUE + (offset & 2)) & 0xFFFF); -} - -uint32_t PCI::raw_read32(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset) -{ - IO::outl(PCI_ADDRESS, raw_address(bus, slot, function, offset)); - return IO::inl(PCI_VALUE); -} - -PCI::DeviceID PCI::get_device_id(uint32_t bus, uint32_t slot, uint32_t function) -{ - uint16_t vendor = PCI::raw_read16(bus, slot, function, PCI_VENDOR_FIELD); - uint16_t device = PCI::raw_read16(bus, slot, function, PCI_DEVICE_FIELD); - return {vendor, device}; -} - -PCI::DeviceType PCI::get_device_type(uint32_t bus, uint32_t slot, uint32_t function) -{ - uint8_t dev_subclass = PCI::raw_read8(bus, slot, function, PCI_SUBCLASS_FIELD); - uint8_t dev_class = PCI::raw_read8(bus, slot, function, PCI_CLASS_FIELD); - uint8_t prog_if = PCI::raw_read8(bus, slot, function, PCI_PROG_IF_FIELD); - uint8_t revision = PCI::raw_read8(bus, slot, function, PCI_REVISION_ID_FIELD); - return {dev_class, dev_subclass, prog_if, revision}; -} - -static void pci_scan_bus(uint8_t bus, void (*callback)(PCI::Device&)) -{ - for (uint8_t slot = 0; slot < 32; slot++) - { - uint8_t num_functions = 1; - for (uint8_t function = 0; function < num_functions; function++) - { - PCI::DeviceID device_id = PCI::get_device_id(bus, slot, function); - if (device_id.vendor == 0xFFFF || device_id.device == 0xFFFF) continue; - PCI::DeviceType device_type = PCI::get_device_type(bus, slot, function); - uint8_t header = PCI::raw_read8(bus, slot, function, PCI_HEADER_TYPE_FIELD); - if (header & 0x80) // multi function device - { - num_functions = 8; - } - if ((header & 0x7F) == 1) - { - uint8_t sub_bus = PCI::raw_read8(bus, slot, function, PCI_SECONDARY_BUS_NUMBER_FIELD); - pci_scan_bus(sub_bus, callback); - } - PCI::Device device{device_id, device_type, bus, slot, function}; - pci_lock.release(); - callback(device); - pci_lock.acquire(); - } - } -} - -void PCI::scan(void (*callback)(PCI::Device&)) -{ - pci_lock.acquire(); - uint8_t function; - uint8_t bus; - - uint8_t header_type = PCI::raw_read8(0, 0, 0, PCI_HEADER_TYPE_FIELD); - if ((header_type & 0x80) == 0) - { - // Single PCI host controller - pci_scan_bus(0, callback); - } - else - { - // Multiple PCI host controllers - for (function = 0; function < 8; function++) - { - if (get_device_id(0, 0, function).vendor == 0xFFFF) break; - bus = function; - pci_scan_bus(bus, callback); - } - } - pci_lock.release(); -} - -PCI::Device::Device(const Device& other) - : m_id(other.m_id), m_type(other.m_type), m_bus(other.m_bus), m_slot(other.m_slot), m_function(other.m_function) -{ -} - -PCI::Device::Device(uint8_t bus, uint8_t slot, uint8_t function) : m_bus(bus), m_slot(slot), m_function(function) -{ - m_id = get_device_id(m_bus, m_slot, m_function); - m_type = get_device_type(m_bus, m_slot, m_function); -} - -PCI::Device::Device(DeviceID id, DeviceType type, uint8_t bus, uint8_t slot, uint8_t function) - : m_id(id), m_type(type), m_bus(bus), m_slot(slot), m_function(function) -{ -} - -void PCI::Device::write8(int32_t offset, uint8_t value) -{ - PCI::raw_write8(m_bus, m_slot, m_function, offset, value); -} - -void PCI::Device::write16(int32_t offset, uint16_t value) -{ - PCI::raw_write16(m_bus, m_slot, m_function, offset, value); -} - -void PCI::Device::write32(int32_t offset, uint32_t value) -{ - PCI::raw_write32(m_bus, m_slot, m_function, offset, value); -} - -uint8_t PCI::Device::read8(int32_t offset) -{ - return PCI::raw_read8(m_bus, m_slot, m_function, offset); -} - -uint16_t PCI::Device::read16(int32_t offset) -{ - return PCI::raw_read16(m_bus, m_slot, m_function, offset); -} - -uint32_t PCI::Device::read32(int32_t offset) -{ - return PCI::raw_read32(m_bus, m_slot, m_function, offset); -} - -uint32_t PCI::Device::getBAR0() -{ - return read32(PCI_BAR0_FIELD); -} - -uint32_t PCI::Device::getBAR1() -{ - return read32(PCI_BAR1_FIELD); -} - -uint32_t PCI::Device::getBAR2() -{ - return read32(PCI_BAR2_FIELD); -} - -uint32_t PCI::Device::getBAR3() -{ - return read32(PCI_BAR3_FIELD); -} - -uint32_t PCI::Device::getBAR4() -{ - return read32(PCI_BAR4_FIELD); -} - -uint32_t PCI::Device::getBAR5() -{ - return read32(PCI_BAR5_FIELD); -} \ No newline at end of file diff --git a/kernel/src/io/PIC.cpp b/kernel/src/io/PIC.cpp deleted file mode 100644 index 2aa553c6..00000000 --- a/kernel/src/io/PIC.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#define MODULE "pic" - -#include "io/PIC.h" -#include "io/IO.h" -#include "log/Log.h" - -#define PIC1_COMMAND 0x20 -#define PIC1_DATA 0x21 -#define PIC2_COMMAND 0xA0 -#define PIC2_DATA 0xA1 -#define PIC_EOI 0x20 - -#define ICW1_INIT 0x10 -#define ICW1_ICW4 0x01 -#define ICW4_8086 0x01 - -void PIC::remap() -{ - kdbgln("Remapping PIC"); - uint8_t a1, a2; - - a1 = IO::inb(PIC1_DATA); - IO::delay(); - a2 = IO::inb(PIC2_DATA); - IO::delay(); - - IO::outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); - IO::delay(); - IO::outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); - IO::delay(); - - kdbgln("Remapping master PIC to ISRs 32-39"); - IO::outb(PIC1_DATA, 0x20); - IO::delay(); - kdbgln("Remapping slave PIC to ISRs 40-47"); - IO::outb(PIC2_DATA, 0x28); - IO::delay(); - - IO::outb(PIC1_DATA, 4); - IO::delay(); - IO::outb(PIC2_DATA, 2); - IO::delay(); - - IO::outb(PIC1_DATA, ICW4_8086); - IO::delay(); - IO::outb(PIC2_DATA, ICW4_8086); - IO::delay(); - - IO::outb(PIC1_DATA, a1); - IO::delay(); - IO::outb(PIC2_DATA, a2); -} - -void PIC::enable_master(uint8_t mask) -{ - kdbgln("Setting mask of master PIC to 0x%x", mask); - IO::outb(PIC1_DATA, mask); -} - -void PIC::enable_slave(uint8_t mask) -{ - kdbgln("Setting mask of slave PIC to 0x%x", mask); - IO::outb(PIC2_DATA, mask); -} - -void PIC::end_master() -{ - IO::outb(PIC1_COMMAND, PIC_EOI); -} - -void PIC::end_slave() -{ - IO::outb(PIC2_COMMAND, PIC_EOI); - IO::outb(PIC1_COMMAND, PIC_EOI); -} - -void PIC::send_eoi(unsigned char irq) -{ - if (irq >= 8) end_slave(); - else - end_master(); -} \ No newline at end of file diff --git a/kernel/src/io/Serial.cpp b/kernel/src/io/Serial.cpp deleted file mode 100644 index 753d368a..00000000 --- a/kernel/src/io/Serial.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "io/Serial.h" -#include "io/IO.h" -#include -#include - -#define COM1 0x3f8 - -void Serial::wait() -{ - while (!(IO::inb(COM1 + 5) & 0x20)) { asm volatile("pause"); } -} - -void Serial::write(const char* string, size_t size) -{ - for (size_t i = 0; i < size; i++) - { - wait(); - IO::outb(COM1, *(string + i)); - } -} - -void Serial::print(const char* string) -{ - Serial::write(string, strlen(string)); -} - -void Serial::println(const char* string) -{ - Serial::write(string, strlen(string)); - wait(); - IO::outb(COM1, '\n'); -} - -static const char* format_color(Color& color) -{ - static char output[20]; - snprintf(output, sizeof(output), "\x1b[38;2;%d;%d;%dm", color.red, color.green, color.blue); - return output; -} - -void Serial::set_color(Color& color) -{ - Serial::print(format_color(color)); -} - -void Serial::reset_color() -{ - Serial::print("\x1b[0m"); -} \ No newline at end of file diff --git a/kernel/src/log/CLog.cpp b/kernel/src/log/CLog.cpp deleted file mode 100644 index 7c62e565..00000000 --- a/kernel/src/log/CLog.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "log/CLog.h" -#include "std/stdio.h" -#include - -enum class LogLevel -{ - DEBUG, - INFO, - WARN, - ERROR -}; - -enum class Backend -{ - Serial, - Console -}; - -namespace KernelLog -{ - void log(const char* function, LogLevel level, const char* message, ...) PRINTF_LIKE(3, 4); - void logln(const char* function, LogLevel level, const char* message, ...) PRINTF_LIKE(3, 4); -} - -void log_backend_serial(const char* function, LogLevel level, const char* message, va_list origin); -void log_backend_console(const char* function, LogLevel level, const char* message, va_list origin); -bool log_level_enabled(LogLevel level); -bool log_backend_enabled(Backend backend); - -extern "C" void clog_log(const char* function, enum log_level level, const char* message, ...) -{ - if (!log_level_enabled((LogLevel)level)) return; - va_list ap; - va_start(ap, message); - if (log_backend_enabled(Backend::Serial)) log_backend_serial(function, (LogLevel)level, message, ap); - if (log_backend_enabled(Backend::Console)) log_backend_console(function, (LogLevel)level, message, ap); - va_end(ap); -} - -extern "C" void clog_logln(const char* function, enum log_level level, const char* message, ...) -{ - if (!log_level_enabled((LogLevel)level)) return; - va_list ap; - va_start(ap, message); - if (log_backend_enabled(Backend::Serial)) - { - log_backend_serial(function, (LogLevel)level, message, ap); - printf("\n"); - } - if (log_backend_enabled(Backend::Console)) - { - log_backend_console(function, (LogLevel)level, message, ap); - kprintf("\n"); - } - va_end(ap); -} \ No newline at end of file diff --git a/kernel/src/log/Log.cpp b/kernel/src/log/Log.cpp deleted file mode 100644 index 13df22ea..00000000 --- a/kernel/src/log/Log.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "log/Log.h" -#include "io/Serial.h" -#include "std/stdio.h" -#include "thread/PIT.h" -#include "thread/Scheduler.h" -#include - -static int level_mask = 15; -static int backend_mask = 3; - -bool log_level_enabled(LogLevel level) -{ - return level_mask & (1 << (int)level); -} - -bool log_backend_enabled(Backend backend) -{ - return backend_mask & (1 << (int)backend); -} - -void log_backend_serial(const char* function, LogLevel level, const char* message, va_list origin) -{ - va_list ap; - va_copy(ap, origin); - Serial::reset_color(); - if (Scheduler::current_task() && Scheduler::current_task()->id) - { - Task* current_task = Scheduler::current_task(); - printf("[%ld.%ld] (%s %ld) %s: ", PIT::ms_since_boot / 1000, PIT::ms_since_boot % 1000, current_task->name, - current_task->id, function); - } - else { printf("[%ld.%ld] (kernel) %s: ", PIT::ms_since_boot / 1000, PIT::ms_since_boot % 1000, function); } - switch (level) - { - case LogLevel::WARN: Serial::set_color(Color::Yellow); break; - case LogLevel::ERROR: Serial::set_color(Color::Red); break; - default: break; - } - vprintf(message, ap); - Serial::reset_color(); - va_end(ap); -} - -void log_backend_console(const char* function, [[maybe_unused]] LogLevel level, const char* message, va_list origin) -{ - va_list ap; - va_copy(ap, origin); - kprintf("%s: ", function); - vkprintf(message, ap); - va_end(ap); -} - -void KernelLog::log(const char* function, LogLevel level, const char* message, ...) -{ - if (!log_level_enabled(level)) return; - va_list ap; - va_start(ap, message); - if (log_backend_enabled(Backend::Serial)) log_backend_serial(function, level, message, ap); - if (log_backend_enabled(Backend::Console)) log_backend_console(function, level, message, ap); - va_end(ap); -} - -void KernelLog::logln(const char* function, LogLevel level, const char* message, ...) -{ - if (!log_level_enabled(level)) return; - va_list ap; - va_start(ap, message); - if (log_backend_enabled(Backend::Serial)) - { - log_backend_serial(function, level, message, ap); - printf("\n"); - } - if (log_backend_enabled(Backend::Console)) - { - log_backend_console(function, level, message, ap); - kprintf("\n"); - } - va_end(ap); -} - -void KernelLog::toggle_log_level(LogLevel level) -{ - level_mask ^= (1 << (int)level); -} - -void KernelLog::toggle_log_backend(Backend backend) -{ - backend_mask ^= (1 << (int)backend); -} - -void KernelLog::enable_log_backend(Backend backend) -{ - backend_mask |= (1 << (int)backend); -} \ No newline at end of file diff --git a/kernel/src/main.asm b/kernel/src/main.asm deleted file mode 100644 index 4593a076..00000000 --- a/kernel/src/main.asm +++ /dev/null @@ -1,40 +0,0 @@ -global _main -extern _start - -_main: - xor rbp, rbp - call _start - cli -.hang: - hlt - jmp .hang - -global idle_task_function -idle_task_function: - sti -.idle: - hlt - jmp .idle - -global asm_enable_sse -asm_enable_sse: - mov rax, cr0 - and ax, 0xFFFB - or ax, 0x2 - mov cr0, rax - mov rax, cr4 - or ax, 3 << 9 - mov cr4, rax - ret - -global asm_get_rflags -asm_get_rflags: - pushfq - pop rax - ret - -global asm_set_rflags -asm_set_rflags: - push rdi - popfq - ret \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index f12e9e7c..abf41426 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,80 +1,7 @@ -#define MODULE "main" - -#include "config.h" -#include "cpu/CPU.h" -#include "fs/TmpFS.h" -#include "fs/devices/DeviceFS.h" -#include "gdt/GDT.h" -#include "init/Init.h" -#include "interrupts/IDT.h" -#include "interrupts/Install.h" -#include "interrupts/Interrupts.h" -#include "io/PIC.h" -#include "log/Log.h" -#include "memory/Memory.h" -#include "memory/MemoryMap.h" -#include "misc/hang.h" -#include "std/ensure.h" -#include "std/stdlib.h" -#include "thread/PIT.h" -#include "thread/Scheduler.h" - -#define STRINGIZE(x) #x -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) +#include extern "C" void _start() { - Init::disable_smp(); // Put all other cores except the bootstrap one in an infinite loop - Init::check_magic(); - Init::early_init(); - - kinfoln("Starting Moon %s", moon_version()); - - CPU::log_cpu_information(); - - Memory::walk_memory_map(); - - GDT::load(); - - Interrupts::install(); - - IDT::load(); - - PIT::initialize(1000); // 1000 times per second - - Scheduler::init(); - -#ifdef RUN_TEST_AS_INIT - ensure(Scheduler::load_user_task(STRINGIZE_VALUE_OF(RUN_TEST_AS_INIT)) > 0); -#else - ensure(Scheduler::load_user_task("/bin/init") > 0); -#endif - - Scheduler::add_kernel_task("[reaper]", []() { - while (1) - { - sleep(400); - Scheduler::reap_tasks(); - } - }); - - ensure(VFS::mkdir("/dev") == 0); - ensure(VFS::mkdir("/tmp") == 0); - VFS::mount("/dev", DeviceFS::get()); - VFS::mount("/tmp", TmpFS::get()); - - Init::finish_kernel_boot(); - - PIC::remap(); - PIC::enable_master(0b11111100); - PIC::enable_slave(0b11111111); - - Interrupts::enable(); - - while (1) - halt(); // As soon as the first timer interrupt arrives, this idle loop is gone, since the main function is not - // registered as a task and thus the scheduler will never schedule this again. We still have to do - // something while waiting for a timer interrupt to arrive, though. In fact, in most cases, calling - // halt() once would be enough, since that function halts the CPU until the next interrupt (most likely - // the timer one) arrives. But we have to guarantee this function never returns. + for (;;) + ; } \ No newline at end of file diff --git a/kernel/src/memory/AddressSpace.cpp b/kernel/src/memory/AddressSpace.cpp deleted file mode 100644 index 7a0e7473..00000000 --- a/kernel/src/memory/AddressSpace.cpp +++ /dev/null @@ -1,284 +0,0 @@ -#define MODULE "vmm" - -#include "memory/AddressSpace.h" -#include "log/Log.h" -#include "memory/PMM.h" -#include "memory/VMM.h" -#include "std/errno.h" -#include "std/stdlib.h" -#include "std/string.h" -#include "utils/move.h" - -Result AddressSpace::create() -{ - AddressSpace result; - auto page = PMM::request_page(); - if (page.has_error()) return page.release_error(); - result.m_pml4 = (PageTable*)page.release_value(); - memset(result.m_pml4, 0, PAGE_SIZE); - VMM::install_kernel_page_directory_into_address_space(result); - return move(result); -} - -void AddressSpace::destroy() -{ - uint64_t pages_freed = 0; - for (int i = 0; i < 512; i++) - { - PageDirectoryEntry& pdp_pde = m_pml4->entries[i]; - if (!pdp_pde.present) continue; - if (pdp_pde.larger_pages) - { - if (pdp_pde.owned_by_task) - { - pages_freed++; - PMM::free_page((void*)pdp_pde.get_address()); - } - continue; - } - PageTable* pdp = (PageTable*)pdp_pde.get_address(); - for (int j = 0; j < 511; j++) // skip the last page directory, it's the kernel one - { - PageDirectoryEntry& pd_pde = pdp->entries[j]; - if (!pd_pde.present) continue; - if (pd_pde.larger_pages) - { - if (pd_pde.owned_by_task) - { - pages_freed++; - PMM::free_page((void*)pd_pde.get_address()); - } - continue; - } - PageTable* pd = (PageTable*)pd_pde.get_address(); - for (int k = 0; k < 512; k++) - { - PageDirectoryEntry& pt_pde = pd->entries[k]; - if (!pt_pde.present) continue; - if (pt_pde.larger_pages) - { - if (pt_pde.owned_by_task) - { - pages_freed++; - PMM::free_page((void*)pt_pde.get_address()); - } - continue; - } - PageTable* pt = (PageTable*)pt_pde.get_address(); - for (int l = 0; l < 512; l++) - { - PageDirectoryEntry& pde = pt->entries[l]; - if (!pde.present) continue; - if (!pde.owned_by_task) continue; - pages_freed++; - PMM::free_page((void*)pde.get_address()); - } - pages_freed++; - PMM::free_page(pt); - } - pages_freed++; - PMM::free_page(pd); - } - pages_freed++; - PMM::free_page(pdp); - } - pages_freed++; - PMM::free_page(m_pml4); - - kdbgln("Reclaimed %ld pages from address space!", pages_freed); -} - -void AddressSpace::clear() -{ - uint64_t pages_freed = 0; - for (int i = 0; i < 512; i++) - { - PageDirectoryEntry& pdp_pde = m_pml4->entries[i]; - if (!pdp_pde.present) continue; - if (pdp_pde.larger_pages) - { - if (pdp_pde.owned_by_task) - { - pages_freed++; - PMM::free_page((void*)pdp_pde.get_address()); - } - continue; - } - PageTable* pdp = (PageTable*)pdp_pde.get_address(); - for (int j = 0; j < 511; j++) // skip the last page directory, it's the kernel one - { - PageDirectoryEntry& pd_pde = pdp->entries[j]; - if (!pd_pde.present) continue; - if (pd_pde.larger_pages) - { - if (pd_pde.owned_by_task) - { - pages_freed++; - PMM::free_page((void*)pd_pde.get_address()); - } - continue; - } - PageTable* pd = (PageTable*)pd_pde.get_address(); - for (int k = 0; k < 512; k++) - { - PageDirectoryEntry& pt_pde = pd->entries[k]; - if (!pt_pde.present) continue; - if (pt_pde.larger_pages) - { - if (pt_pde.owned_by_task) - { - pages_freed++; - PMM::free_page((void*)pt_pde.get_address()); - } - continue; - } - PageTable* pt = (PageTable*)pt_pde.get_address(); - for (int l = 0; l < 512; l++) - { - PageDirectoryEntry& pde = pt->entries[l]; - if (!pde.present) continue; - if (!pde.owned_by_task) continue; - pages_freed++; - PMM::free_page((void*)pde.get_address()); - } - pages_freed++; - PMM::free_page(pt); - } - pages_freed++; - PMM::free_page(pd); - } - pages_freed++; - PMM::free_page(pdp); - } - memset(m_pml4, 0, PAGE_SIZE); - - VMM::install_kernel_page_directory_into_address_space(*this); - - kdbgln("Reclaimed %ld pages from address space!", pages_freed); -} - -static PageTable* try_clone_page_table(PageTable* source) -{ - auto page = PMM::request_page(); - if (page.has_error()) { return 0; } - PageTable* dst = (PageTable*)page.release_value(); - memcpy(dst, source, sizeof(PageTable)); - return dst; -} - -AddressSpace AddressSpace::clone() // FIXME: Add out-of-memory checks to this function. -{ - AddressSpace result; - result.m_pml4 = try_clone_page_table(m_pml4); - if (!result.m_pml4) return result; - for (int i = 0; i < 512; i++) - { - PageDirectoryEntry& pdp_pde = m_pml4->entries[i]; - PageDirectoryEntry& cloned_pdp_pde = result.m_pml4->entries[i]; - if (!pdp_pde.present) continue; - if (pdp_pde.larger_pages) - { - if (!pdp_pde.owned_by_task) - { - memcpy(&cloned_pdp_pde, &pdp_pde, sizeof(PageDirectoryEntry)); - continue; - } - void* cloned = try_clone_page_table((PageTable*)pdp_pde.get_address()); - if (!cloned) - { - cloned_pdp_pde.present = false; - continue; - } - cloned_pdp_pde.set_address((uint64_t)cloned); - continue; - } - PageTable* pdp = (PageTable*)pdp_pde.get_address(); - PageTable* cloned_pdp = try_clone_page_table(pdp); - if (!cloned_pdp) - { - cloned_pdp_pde.present = false; - continue; - } - cloned_pdp_pde.set_address((uint64_t)cloned_pdp); - for (int j = 0; j < 511; j++) // skip the last page directory, it's the kernel one - { - PageDirectoryEntry& pd_pde = pdp->entries[j]; - PageDirectoryEntry& cloned_pd_pde = cloned_pdp->entries[j]; - if (!pd_pde.present) continue; - if (pd_pde.larger_pages) - { - if (!pd_pde.owned_by_task) - { - memcpy(&cloned_pd_pde, &pd_pde, sizeof(PageDirectoryEntry)); - continue; - } - void* cloned = try_clone_page_table((PageTable*)pd_pde.get_address()); - if (!cloned) - { - cloned_pd_pde.present = false; - continue; - } - cloned_pd_pde.set_address((uint64_t)cloned); - continue; - } - PageTable* pd = (PageTable*)pd_pde.get_address(); - PageTable* cloned_pd = try_clone_page_table(pd); - if (!cloned_pd) - { - cloned_pd_pde.present = false; - continue; - } - cloned_pd_pde.set_address((uint64_t)cloned_pd); - for (int k = 0; k < 512; k++) - { - PageDirectoryEntry& pt_pde = pd->entries[k]; - PageDirectoryEntry& cloned_pt_pde = cloned_pd->entries[k]; - if (!pt_pde.present) continue; - if (pt_pde.larger_pages) - { - if (!pt_pde.owned_by_task) - { - memcpy(&cloned_pt_pde, &pt_pde, sizeof(PageDirectoryEntry)); - continue; - } - void* cloned = try_clone_page_table((PageTable*)pt_pde.get_address()); - if (!cloned) - { - cloned_pt_pde.present = false; - continue; - } - cloned_pt_pde.set_address((uint64_t)cloned); - continue; - } - PageTable* pt = (PageTable*)pt_pde.get_address(); - PageTable* cloned_pt = try_clone_page_table(pt); - if (!cloned_pt) - { - cloned_pt_pde.present = false; - continue; - } - cloned_pt_pde.set_address((uint64_t)cloned_pt); - for (int l = 0; l < 512; l++) - { - PageDirectoryEntry& pde = pt->entries[l]; - PageDirectoryEntry& cloned_pde = cloned_pt->entries[l]; - if (!pde.owned_by_task) - { - memcpy(&cloned_pde, &pde, sizeof(PageDirectoryEntry)); - continue; - } - if (!pde.present) continue; - void* cloned = try_clone_page_table((PageTable*)pde.get_address()); - if (!cloned) - { - cloned_pde.present = false; - continue; - } - cloned_pde.set_address((uint64_t)cloned); - continue; - } - } - } - } - return result; -} \ No newline at end of file diff --git a/kernel/src/memory/KernelHeap.cpp b/kernel/src/memory/KernelHeap.cpp deleted file mode 100644 index d42c520e..00000000 --- a/kernel/src/memory/KernelHeap.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#define MODULE "kheap" - -#include "memory/KernelHeap.h" -#include "assert.h" -#include "log/Log.h" -#include "std/string.h" - -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - -static uint8_t page_bitmap[2048]; - -static int64_t kheap_free = sizeof(page_bitmap) * 8 * PAGE_SIZE; -static int64_t kheap_used = 0; - -#define ALLOC_BASE 0xfffffffff8000000 -#define ALLOC_END 0xfffffffffc000000 - -// static uint64_t start_index = 0; - -static bool bitmap_read(uint64_t index) -{ - return (page_bitmap[index / 8] & (0b10000000 >> (index % 8))) > 0; -} - -static void bitmap_set(uint64_t index, bool value) -{ - uint64_t byteIndex = index / 8; - uint8_t bitIndexer = 0b10000000 >> (index % 8); - page_bitmap[byteIndex] &= ~bitIndexer; - if (value) { page_bitmap[byteIndex] |= bitIndexer; } -} - -void KernelHeap::clear() -{ - memset(page_bitmap, 0, sizeof(page_bitmap)); -} - -uint64_t KernelHeap::request_virtual_page() -{ - for (uint64_t index = 0; index < sizeof(page_bitmap) * 8; index++) - { - if (bitmap_read(index)) continue; - bitmap_set(index, true); - // start_index = index + 1; -#ifdef KHEAP_DEBUG - kinfoln("allocating one page for caller %p, returning %lx", __builtin_return_address(0), - ALLOC_BASE + (index * PAGE_SIZE)); -#endif - kheap_free -= PAGE_SIZE; - kheap_used += PAGE_SIZE; -#ifdef KHEAP_DEBUG - dump_usage(); -#endif - return ALLOC_BASE + (index * PAGE_SIZE); - } - - return 0; -} - -uint64_t KernelHeap::request_virtual_pages(uint64_t count) -{ - uint64_t contiguous = 0; - uint64_t contiguous_start = 0; - for (uint64_t index = 0; index < sizeof(page_bitmap) * 8; index++) - { - if (bitmap_read(index)) - { - contiguous = 0; - continue; - } - if (contiguous == 0) - { - contiguous_start = index; - contiguous++; - } - else - contiguous++; - if (contiguous == count) - { - for (uint64_t i = 0; i < count; i++) bitmap_set(contiguous_start + i, true); -#ifdef KHEAP_DEBUG - kinfoln("allocating %lu pages for caller %p, returning %lx", count, __builtin_return_address(0), - ALLOC_BASE + (contiguous_start * PAGE_SIZE)); -#endif - kheap_free -= (count * PAGE_SIZE); - kheap_used += (count * PAGE_SIZE); -#ifdef KHEAP_DEBUG - dump_usage(); -#endif - return ALLOC_BASE + (contiguous_start * PAGE_SIZE); - } - } - - return 0; -} - -void KernelHeap::free_virtual_page(uint64_t address) -{ - if (address < ALLOC_BASE || address >= ALLOC_END) return; - uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE; - bitmap_set(index, false); -#ifdef KHEAP_DEBUG - kinfoln("releasing one page for caller %p, %lx", __builtin_return_address(0), address); -#endif - kheap_free += PAGE_SIZE; - kheap_used -= PAGE_SIZE; -#ifdef KHEAP_DEBUG - dump_usage(); -#endif - // if (start_index > index) start_index = index; -} - -void KernelHeap::free_virtual_pages(uint64_t address, uint64_t count) -{ - if (address < ALLOC_BASE || address >= ALLOC_END) return; - uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE; - for (uint64_t i = 0; i < count; i++) { bitmap_set(index + i, false); } -#ifdef KHEAP_DEBUG - kinfoln("releasing %lu pages for caller %p, %lx", count, __builtin_return_address(0), address); -#endif - kheap_free += (count * PAGE_SIZE); - kheap_used -= (count * PAGE_SIZE); -#ifdef KHEAP_DEBUG - dump_usage(); -#endif - // if (start_index > index) start_index = index; -} - -void KernelHeap::dump_usage() -{ - kinfoln("Used: %ld KB", kheap_used / 1024); - kinfoln("Free: %ld KB", kheap_free / 1024); -} \ No newline at end of file diff --git a/kernel/src/memory/Memory.cpp b/kernel/src/memory/Memory.cpp deleted file mode 100644 index 6ff02898..00000000 --- a/kernel/src/memory/Memory.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "memory/Memory.h" -#include "bootboot.h" - -extern BOOTBOOT bootboot; - -uint64_t Memory::get_system() -{ - static uint64_t result = 0; - static bool cached = false; - - if (cached) return result; - - MMapEnt* ptr = &bootboot.mmap; - uint64_t mmap_entries = (bootboot.size - 128) / 16; - for (uint64_t i = 0; i < mmap_entries; i++) - { - result += MMapEnt_Size(ptr); - ptr++; - } - - cached = true; - - return result; -} - -uint64_t Memory::get_usable() -{ - static uint64_t result = 0; - static bool cached = false; - - if (cached) return result; - - MMapEnt* ptr = &bootboot.mmap; - uint64_t mmap_entries = (bootboot.size - 128) / 16; - for (uint64_t i = 0; i < mmap_entries; i++) - { - if (MMapEnt_IsFree(ptr)) result += MMapEnt_Size(ptr); - ptr++; - } - - cached = true; - - return result; -} - -bool Memory::is_kernel_address(uintptr_t address) -{ - return address >= 0xfffffffff8000000; -} - -bool Memory::is_user_address(uintptr_t address) -{ - return address && address < 0xfffffffff8000000; -} \ No newline at end of file diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp deleted file mode 100644 index b8bee795..00000000 --- a/kernel/src/memory/MemoryManager.cpp +++ /dev/null @@ -1,223 +0,0 @@ -#ifdef MM_DEBUG -#define MODULE "mm" -#include "log/Log.h" -#endif - -#include "memory/KernelHeap.h" -#include "memory/MemoryManager.h" -#include "memory/PMM.h" -#include "memory/VMM.h" -#include "misc/utils.h" -#include "std/ensure.h" - -// FIXME: Use Result in here. - -void MemoryManager::init() -{ - KernelHeap::clear(); - PMM::init(); - VMM::init(); - PMM::map_bitmap_to_virtual(); -} - -extern char start_of_kernel_rodata[1]; -extern char end_of_kernel_rodata[1]; -extern char start_of_kernel_data[1]; -extern char end_of_kernel_data[1]; - -void MemoryManager::protect_kernel_sections() -{ - protect(start_of_kernel_rodata, - Utilities::get_blocks_from_size(PAGE_SIZE, end_of_kernel_rodata - start_of_kernel_rodata), 0); - protect(start_of_kernel_data, Utilities::get_blocks_from_size(PAGE_SIZE, end_of_kernel_data - start_of_kernel_data), - MAP_READ_WRITE); -} - -Result MemoryManager::get_mapping(void* physicalAddress, int flags) -{ - uint64_t virtualAddress = KernelHeap::request_virtual_page(); - if (!virtualAddress) - { -#ifdef MM_DEBUG - kwarnln("No kernel heap space (virtual address space from -128M to -64M) left"); -#endif - KernelHeap::dump_usage(); - return {ENOMEM}; - } - VMM::map(virtualAddress, (uint64_t)physicalAddress, flags); - return (void*)virtualAddress; -} - -Result MemoryManager::get_unaligned_mapping(void* physicalAddress, int flags) -{ - uint64_t offset = (uint64_t)physicalAddress % PAGE_SIZE; - uint64_t virtualAddress = KernelHeap::request_virtual_page(); - if (!virtualAddress) - { -#ifdef MM_DEBUG - kwarnln("No kernel heap space (virtual address space from -128M to -64M) left"); -#endif - KernelHeap::dump_usage(); - return {ENOMEM}; - } - VMM::map(virtualAddress, (uint64_t)physicalAddress - offset, flags); - return (void*)(virtualAddress + offset); -} - -Result MemoryManager::get_unaligned_mappings(void* physicalAddress, uint64_t count, int flags) -{ - if (!count) return 0; - if (count == 1) return get_unaligned_mapping(physicalAddress, flags); - uint64_t offset = (uint64_t)physicalAddress % PAGE_SIZE; - uint64_t virtualAddress = KernelHeap::request_virtual_pages(count); - if (!virtualAddress) - { -#ifdef MM_DEBUG - kwarnln("Not enough contiguous pages (%ld) left in the kernel heap space (virtual address space from -128M to " - "-64M)", - count); -#endif - KernelHeap::dump_usage(); - return {ENOMEM}; - } - for (uint64_t i = 0; i < count; i++) - { - VMM::map(virtualAddress + (i * PAGE_SIZE), ((uint64_t)physicalAddress - offset) + (i * PAGE_SIZE), flags); - } - return (void*)(virtualAddress + offset); -} - -void MemoryManager::release_unaligned_mapping(void* mapping) -{ - uint64_t offset = (uint64_t)mapping % PAGE_SIZE; - VMM::unmap((uint64_t)mapping - offset); - KernelHeap::free_virtual_page((uint64_t)mapping - offset); -} - -void MemoryManager::release_unaligned_mappings(void* mapping, uint64_t count) -{ - if (!count) return; - if (count == 1) return release_unaligned_mapping(mapping); - uint64_t offset = (uint64_t)mapping % PAGE_SIZE; - KernelHeap::free_virtual_pages((uint64_t)mapping - offset, count); - for (uint64_t i = 0; i < count; i++) { VMM::unmap(((uint64_t)mapping - offset) + (i * PAGE_SIZE)); } -} - -void MemoryManager::release_mapping(void* mapping) -{ - VMM::unmap((uint64_t)mapping); - KernelHeap::free_virtual_page((uint64_t)mapping); -} - -Result MemoryManager::get_page(int flags) -{ - uint64_t virtualAddress = KernelHeap::request_virtual_page(); - if (!virtualAddress) - { -#ifdef MM_DEBUG - kwarnln("No kernel heap space (virtual address space from -128M to -64M) left"); -#endif - KernelHeap::dump_usage(); - return {ENOMEM}; - } - return get_page_at(virtualAddress, flags); -} - -Result MemoryManager::get_page_at(uint64_t addr, int flags) -{ - auto paddr = PMM::request_page(); - if (paddr.has_error()) - { -#ifdef MM_DEBUG - kwarnln("OOM while allocating one page of memory. this is not good..."); -#endif - return {ENOMEM}; - } - VMM::map(addr, (uint64_t)paddr.release_value(), flags); - return (void*)addr; -} - -void MemoryManager::release_page(void* page) -{ - uint64_t physicalAddress = VMM::get_physical((uint64_t)page); - ensure(physicalAddress != UINT64_MAX); // this address is not mapped in the virtual address space... - VMM::unmap((uint64_t)page); - PMM::free_page((void*)physicalAddress); -} - -Result MemoryManager::get_pages(uint64_t count, int flags) -{ - if (!count) return 0; - if (count == 1) return get_page(flags); -#ifdef MM_DEBUG - kdbgln("allocating several pages (%ld)", count); -#endif - uint64_t virtualAddress = KernelHeap::request_virtual_pages(count); - if (!virtualAddress) - { -#ifdef MM_DEBUG - kwarnln("No kernel heap space (virtual address space from -128M to -64M) left"); -#endif - KernelHeap::dump_usage(); - return {ENOMEM}; // Out of virtual address in the kernel heap range (-128M to -64M). This should be difficult to - // achieve... - } - return get_pages_at(virtualAddress, count, flags); -} - -Result MemoryManager::get_pages_at(uint64_t addr, uint64_t count, int flags) -{ - if (!count) return 0; - if (count == 1) return get_page_at(addr, flags); -#ifdef MM_DEBUG - kdbgln("allocating several pages (%ld), at address %lx", count, addr); -#endif - for (uint64_t i = 0; i < count; i++) - { - auto paddr = PMM::request_page(); - if (paddr.has_error()) // OOM: No physical memory available! Since this might be at the end of a - // long allocation, we should be able to recover most of it and allocate a - // smaller range, so this might not be fatal. - { -#ifdef MM_DEBUG - kwarnln("OOM while allocating page %ld of memory. this might be recoverable...", i); -#endif - // FIXME: Weren't we supposed to free all previously allocated pages, to avoid leaks when failing large - // allocations? - return {ENOMEM}; - } - VMM::map(addr + (i * PAGE_SIZE), (uint64_t)paddr.release_value(), flags); - } - return (void*)addr; -} - -void MemoryManager::release_pages(void* pages, uint64_t count) -{ - if (!count) return; - if (count == 1) return release_page(pages); -#ifdef MM_DEBUG - kdbgln("releasing several pages (%ld)", count); -#endif - for (uint64_t i = 0; i < count; i++) - { - void* page = (void*)((uint64_t)pages + (i * PAGE_SIZE)); - uint64_t physicalAddress = VMM::get_physical((uint64_t)page); - ensure(physicalAddress != UINT64_MAX); - VMM::unmap((uint64_t)page); - PMM::free_page((void*)physicalAddress); - } - KernelHeap::free_virtual_pages((uint64_t)pages, count); -} - -void MemoryManager::protect(void* page, uint64_t count, int flags) -{ - for (uint64_t i = 0; i < count; i++) { VMM::remap((uint64_t)page + (i * PAGE_SIZE), flags); } -} - -void MemoryManager::map_several_pages(uint64_t physicalAddress, uint64_t virtualAddress, uint64_t count, int flags) -{ - for (uint64_t i = 0; i < count; i++) - { - VMM::map(virtualAddress + (i * PAGE_SIZE), physicalAddress + (i * PAGE_SIZE), flags); - } -} \ No newline at end of file diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp deleted file mode 100644 index 9ae89bbe..00000000 --- a/kernel/src/memory/MemoryMap.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#define MODULE "mmap" - -#include "memory/MemoryMap.h" -#include "bootboot.h" -#include "log/Log.h" - -extern BOOTBOOT bootboot; - -void Memory::walk_memory_map() -{ - MMapEnt* ptr = &bootboot.mmap; - uint64_t mmap_entries = (bootboot.size - 128) / 16; - for (uint64_t i = 0; i < mmap_entries; i++) - { - switch (MMapEnt_Type(ptr)) - { - case MMAP_USED: - kinfoln("Used memory region starting at %lx, ends at %lx, size %lx", MMapEnt_Ptr(ptr), - MMapEnt_Ptr(ptr) + MMapEnt_Size(ptr) - 1, MMapEnt_Size(ptr)); - break; - case MMAP_ACPI: - kinfoln("ACPI memory region starting at %lx, ends at %lx, size %lx", MMapEnt_Ptr(ptr), - MMapEnt_Ptr(ptr) + MMapEnt_Size(ptr) - 1, MMapEnt_Size(ptr)); - break; - case MMAP_MMIO: - kinfoln("MMIO memory region starting at %lx, ends at %lx, size %lx", MMapEnt_Ptr(ptr), - MMapEnt_Ptr(ptr) + MMapEnt_Size(ptr) - 1, MMapEnt_Size(ptr)); - break; - case MMAP_FREE: - kinfoln("Free memory region starting at %lx, ends at %lx, size %lx", MMapEnt_Ptr(ptr), - MMapEnt_Ptr(ptr) + MMapEnt_Size(ptr) - 1, MMapEnt_Size(ptr)); - break; - default: kinfoln("Invalid memory map entry"); break; - } - ptr++; - } -} \ No newline at end of file diff --git a/kernel/src/memory/PMM.cpp b/kernel/src/memory/PMM.cpp deleted file mode 100644 index ec62deb0..00000000 --- a/kernel/src/memory/PMM.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#define MODULE "mem" - -#include "memory/PMM.h" -#include "bootboot.h" -#include "log/Log.h" -#include "memory/Memory.h" -#include "memory/MemoryManager.h" -#include "misc/utils.h" -#include "std/ensure.h" -#include "std/errno.h" -#include "std/string.h" - -extern BOOTBOOT bootboot; - -static bool bitmap_read(uint64_t index); -static void bitmap_set(uint64_t index, bool value); - -static uint64_t free_mem = 0; -static uint64_t used_mem = 0; -static uint64_t reserved_mem = 0; - -static char* bitmap_addr; -static char* virtual_bitmap_addr; -static uint64_t bitmap_size; - -static uint64_t start_index = 0; - -void PMM::init() -{ - uint64_t total_mem = Memory::get_system(); - - void* biggest_chunk = nullptr; - uint64_t biggest_chunk_size = 0; - - MMapEnt* ptr = &bootboot.mmap; - uint64_t mmap_entries = (bootboot.size - 128) / 16; - for (uint64_t i = 0; i < mmap_entries; i++) - { - if (!MMapEnt_IsFree(ptr)) - { - ptr++; - continue; - } - if (MMapEnt_Size(ptr) > biggest_chunk_size) - { - biggest_chunk = (void*)MMapEnt_Ptr(ptr); - biggest_chunk_size = MMapEnt_Size(ptr); - } - ptr++; - } - - bitmap_addr = (char*)biggest_chunk; - virtual_bitmap_addr = bitmap_addr; - ensure((total_mem / PAGE_SIZE / 8) < biggest_chunk_size); - bitmap_size = total_mem / PAGE_SIZE / 8 + 1; - memset(bitmap_addr, 0xFF, bitmap_size); - - ptr = &bootboot.mmap; - for (uint64_t i = 0; i < mmap_entries; i++) - { - uint64_t index = MMapEnt_Ptr(ptr) / PAGE_SIZE; - if (!MMapEnt_IsFree(ptr)) { reserved_mem += MMapEnt_Size(ptr); } - else - { - free_mem += MMapEnt_Size(ptr); - for (uint64_t j = 0; j < (MMapEnt_Size(ptr) / PAGE_SIZE); j++) { bitmap_set(index + j, false); } - } - ptr++; - } - - lock_pages(bitmap_addr, bitmap_size / PAGE_SIZE + 1); -} - -static bool bitmap_read(uint64_t index) -{ - return (virtual_bitmap_addr[index / 8] & (0b10000000 >> (index % 8))) > 0; -} - -static void bitmap_set(uint64_t index, bool value) -{ - uint64_t byteIndex = index / 8; - uint8_t bitIndexer = 0b10000000 >> (index % 8); - virtual_bitmap_addr[byteIndex] &= (uint8_t)(~bitIndexer); - if (value) { virtual_bitmap_addr[byteIndex] |= bitIndexer; } -} - -Result PMM::request_page() -{ - for (uint64_t index = start_index; index < (bitmap_size * 8); index++) - { - if (bitmap_read(index)) continue; - bitmap_set(index, true); - start_index = index + 1; - free_mem -= PAGE_SIZE; - used_mem += PAGE_SIZE; - return (void*)(index * PAGE_SIZE); - } - - return {ENOMEM}; -} - -Result PMM::request_pages(uint64_t count) -{ - uint64_t contiguous = 0; - uint64_t contiguous_start = 0; - for (uint64_t index = start_index; index < (bitmap_size * 8); index++) - { - if (bitmap_read(index)) - { - contiguous = 0; - continue; - } - if (contiguous == 0) - { - contiguous_start = index; - contiguous++; - } - else - contiguous++; - if (contiguous == count) - { - for (uint64_t i = 0; i < count; i++) bitmap_set(contiguous_start + i, true); - free_mem -= (count * PAGE_SIZE); - used_mem += (count * PAGE_SIZE); - return (void*)(contiguous_start * PAGE_SIZE); - } - } - - return {ENOMEM}; -} - -void PMM::free_page(void* address) -{ - uint64_t index = (uint64_t)address / PAGE_SIZE; - if (index > (bitmap_size * 8)) - { - kinfoln("attempt to free out-of-range address %p", address); - return; - } - if (!bitmap_read(index)) return; - bitmap_set(index, false); - used_mem -= PAGE_SIZE; - free_mem += PAGE_SIZE; - if (start_index > index) start_index = index; -} - -void PMM::free_pages(void* address, uint64_t count) -{ - for (uint64_t index = 0; index < count; index++) { free_page((void*)((uint64_t)address + index)); } -} - -void PMM::lock_page(void* address) -{ - uint64_t index = ((uint64_t)address) / PAGE_SIZE; - if (bitmap_read(index)) return; - bitmap_set(index, true); - used_mem += PAGE_SIZE; - free_mem -= PAGE_SIZE; -} - -void PMM::lock_pages(void* address, uint64_t count) -{ - for (uint64_t index = 0; index < count; index++) { lock_page((void*)((uint64_t)address + index)); } -} - -uint64_t PMM::get_free() -{ - return free_mem; -} - -uint64_t PMM::get_used() -{ - return used_mem; -} - -uint64_t PMM::get_reserved() -{ - return reserved_mem; -} - -uint64_t PMM::get_bitmap_size() -{ - return bitmap_size; -} - -void PMM::map_bitmap_to_virtual() -{ - virtual_bitmap_addr = (char*)MemoryManager::get_unaligned_mappings( - bitmap_addr, Utilities::get_blocks_from_size(PAGE_SIZE, bitmap_size)) - .release_value(); // If we can't do this, something has gone terribly wrong. -} \ No newline at end of file diff --git a/kernel/src/memory/Paging.cpp b/kernel/src/memory/Paging.cpp deleted file mode 100644 index 8bf7a7dc..00000000 --- a/kernel/src/memory/Paging.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "memory/Paging.h" - -#pragma GCC push_options -#pragma GCC diagnostic ignored "-Wconversion" - -void PageDirectoryEntry::set_address(uint64_t addr) -{ - this->address = (addr >> 12); -} - -uint64_t PageDirectoryEntry::get_address() -{ - return (uint64_t)this->address << 12; -} - -#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/memory/UserHeap.cpp b/kernel/src/memory/UserHeap.cpp deleted file mode 100644 index b9876a8c..00000000 --- a/kernel/src/memory/UserHeap.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#define MODULE "mem" - -#include "memory/UserHeap.h" -#include "log/Log.h" -#include "misc/utils.h" -#include "std/stdlib.h" -#include "std/string.h" - -#ifndef USER_HEAP_DEBUG -#undef kdbgln -#define kdbgln(...) -#endif - -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - -#define ALLOC_BASE 0xa00000 - -#define INITIAL_SIZE 0x2000 -#define EXPAND_SIZE 0x1000 - -bool UserHeap::init() -{ - bitmap = (uint8_t*)kmalloc(INITIAL_SIZE); - if (!bitmap) return false; - bitmap_size = INITIAL_SIZE; - memset(bitmap, 0, bitmap_size); - kdbgln("new user heap, bitmap at %p, size %ld", (void*)bitmap, bitmap_size); - return true; -} - -bool UserHeap::inherit(UserHeap& other) -{ - bitmap = (uint8_t*)kmalloc(other.bitmap_size); - if (!bitmap) return false; - bitmap_size = other.bitmap_size; - memcpy(bitmap, other.bitmap, bitmap_size); - kdbgln("child user heap, bitmap at %p, size %ld", (void*)bitmap, bitmap_size); - return true; -} - -void UserHeap::free() -{ - kdbgln("freeing user heap, bitmap at %p, size %ld", (void*)bitmap, bitmap_size); - kfree(bitmap); -} - -bool UserHeap::try_expand() -{ - kdbgln("attempting to expand user heap"); - void* new_bitmap = krealloc(bitmap, bitmap_size + EXPAND_SIZE); - if (!new_bitmap) - { - kdbgln("expansion failed"); - return false; - } - bitmap = (uint8_t*)new_bitmap; - memset(bitmap + bitmap_size, 0, EXPAND_SIZE); - bitmap_size += EXPAND_SIZE; - kdbgln("expanded user heap, bitmap at %p, size %ld", (void*)bitmap, bitmap_size); - return true; -} - -bool UserHeap::try_expand_size(uint64_t size) -{ - void* new_bitmap = krealloc(bitmap, bitmap_size + size); - if (!new_bitmap) - { - kdbgln("expansion failed"); - return false; - } - bitmap = (uint8_t*)new_bitmap; - memset(bitmap + bitmap_size, 0, size); - bitmap_size += size; - kdbgln("expanded user heap, bitmap at %p, size %ld", (void*)bitmap, bitmap_size); - return true; -} - -bool UserHeap::bitmap_read(uint64_t index) -{ - return (bitmap[index / 8] & (0b10000000 >> (index % 8))) > 0; -} - -void UserHeap::bitmap_set(uint64_t index, bool value) -{ - uint64_t byteIndex = index / 8; - uint8_t bitIndexer = 0b10000000 >> (index % 8); - bitmap[byteIndex] &= ~bitIndexer; - if (value) { bitmap[byteIndex] |= bitIndexer; } -} - -uint64_t UserHeap::request_virtual_page() -{ - uint64_t attempts = 0; -allocate: - for (uint64_t index = start_index; index < bitmap_size * 8; index++) - { - if (bitmap_read(index)) continue; - bitmap_set(index, true); - start_index = index + 1; - return ALLOC_BASE + (index * PAGE_SIZE); - } - - if (attempts == 0 && try_expand()) // We are allocating ONE PAGE, only one attempt should be necessary. - { - attempts++; - goto allocate; - } - - return 0; -} - -uint64_t UserHeap::request_virtual_pages(uint64_t count) -{ - uint64_t attempts = 0; -allocate: - uint64_t contiguous = 0; - uint64_t contiguous_start = 0; - for (uint64_t index = start_index; index < bitmap_size * 8; index++) - { - if (bitmap_read(index)) - { - contiguous = 0; - continue; - } - if (contiguous == 0) - { - contiguous_start = index; - contiguous++; - } - else - contiguous++; - if (contiguous == count) - { - for (uint64_t i = 0; i < count; i++) bitmap_set(contiguous_start + i, true); - return ALLOC_BASE + (contiguous_start * PAGE_SIZE); - } - } - - if (attempts == 0 && try_expand_size(Utilities::get_blocks_from_size(8, count) + 256)) - { - attempts++; - goto allocate; - } - - return 0; -} - -void UserHeap::free_virtual_page(uint64_t address) -{ - if (address < ALLOC_BASE || address >= (ALLOC_BASE + bitmap_size * 8 * PAGE_SIZE)) return; - uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE; - bitmap_set(index, false); - if (start_index > index) start_index = index; -} - -void UserHeap::free_virtual_pages(uint64_t address, uint64_t count) -{ - if (address < ALLOC_BASE || address >= (ALLOC_BASE + bitmap_size * 8 * PAGE_SIZE)) return; - uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE; - for (uint64_t i = 0; i < count; i++) { bitmap_set(index + i, false); } - if (start_index > index) start_index = index; -} \ No newline at end of file diff --git a/kernel/src/memory/VMM.cpp b/kernel/src/memory/VMM.cpp deleted file mode 100644 index b36c3b6a..00000000 --- a/kernel/src/memory/VMM.cpp +++ /dev/null @@ -1,362 +0,0 @@ -#define MODULE "vmm" - -#include "memory/VMM.h" -#include "log/Log.h" -#include "memory/PMM.h" -#include "misc/utils.h" -#include "std/ensure.h" -#include "std/string.h" -#include "utils/Addresses.h" -#include "utils/Registers.h" - -static PageTable* kernel_pml4; -static PageTable* current_pml4; -static AddressSpace* user_address_space; - -// FIXME: Switch to recursive paging instead of naively assuming the physical address space is identity mapped. - -void VMM::switch_back_to_kernel_address_space() -{ - if (current_pml4 != kernel_pml4) { current_pml4 = kernel_pml4; } -} - -void VMM::switch_to_user_address_space(AddressSpace& space) -{ - user_address_space = &space; - current_pml4 = user_address_space->get_pml4(); -} - -void VMM::switch_to_previous_user_address_space() -{ - current_pml4 = user_address_space->get_pml4(); -} - -void VMM::enter_syscall_context() -{ - if (current_pml4 != kernel_pml4) - { - current_pml4 = kernel_pml4; - apply_address_space(); - switch_to_previous_user_address_space(); - } -} - -void VMM::exit_syscall_context() -{ - if (current_pml4 != user_address_space->get_pml4()) { switch_to_previous_user_address_space(); } - apply_address_space(); -} - -void VMM::apply_address_space() -{ - write_cr3(current_pml4); -} - -bool VMM::is_using_kernel_address_space() -{ - return current_pml4 == kernel_pml4; -} - -void VMM::init() -{ - kernel_pml4 = (PageTable*)read_cr3(); - current_pml4 = kernel_pml4; - - // Set up recursive paging - PageDirectoryEntry& recursive_pde = kernel_pml4->entries[510]; - memset(&recursive_pde, 0, sizeof(PageDirectoryEntry)); - recursive_pde.present = true; - recursive_pde.read_write = true; - recursive_pde.larger_pages = false; - recursive_pde.no_execute = true; - recursive_pde.set_address((uint64_t)kernel_pml4); - flush_tlb_full(); -} - -void VMM::unmap(uint64_t vaddr) -{ - vaddr = round_down_to_nearest_page(vaddr); - - PageDirectoryEntry* pde = find_pde(current_pml4, vaddr); - if (!pde) return; // Already unmapped - - memset(pde, 0, sizeof(PageDirectoryEntry)); - flush_tlb(vaddr); -} - -void VMM::remap(uint64_t vaddr, int flags) -{ - vaddr = round_down_to_nearest_page(vaddr); - - PageDirectoryEntry* pde = find_pde(current_pml4, vaddr); - if (!pde) return; // Not mapped - - if (flags & User) propagate_user(current_pml4, vaddr); - else - pde->user = false; - if (flags & ReadWrite) propagate_read_write(current_pml4, vaddr); - else - pde->read_write = false; - if (flags & Execute) pde->no_execute = false; - else - pde->no_execute = true; - if (flags & OwnedByTask) pde->owned_by_task = true; - else - pde->owned_by_task = false; - flush_tlb(vaddr); -} - -uint64_t VMM::get_physical(uint64_t vaddr) -{ - PageDirectoryEntry* pde = find_pde(current_pml4, round_down_to_nearest_page(vaddr)); - if (!pde) return UINT64_MAX; // Not mapped - - return pde->get_address() | (vaddr % PAGE_SIZE); -} - -uint64_t VMM::get_flags(uint64_t vaddr) -{ - PageDirectoryEntry* pde = find_pde(current_pml4, round_down_to_nearest_page(vaddr)); - if (!pde) return (uint64_t)-1; // Not mapped - - uint64_t flags = 0; - if (pde->user) flags |= User; - if (pde->read_write) flags |= ReadWrite; - if (!pde->no_execute) flags |= Execute; - if (pde->owned_by_task) flags |= OwnedByTask; - return flags; -} - -void VMM::map(uint64_t vaddr, uint64_t paddr, int flags) -{ - vaddr = round_down_to_nearest_page(vaddr); - PageDirectoryEntry* pde = find_pde(current_pml4, vaddr); - bool will_flush_tlb = true; - if (!pde) - { - pde = create_pde_if_not_exists(current_pml4, vaddr); - will_flush_tlb = false; - } - else if (pde->larger_pages) - { - unmap(vaddr); - pde = create_pde_if_not_exists(current_pml4, vaddr); - will_flush_tlb = false; // unmap() already flushes the TLB for us - } - - pde->set_address(round_down_to_nearest_page(paddr)); - if (flags & User) propagate_user(current_pml4, vaddr); - else - pde->user = false; - if (flags & ReadWrite) propagate_read_write(current_pml4, vaddr); - else - pde->read_write = false; - if (flags & Execute) pde->no_execute = false; - else - pde->no_execute = true; - if (flags & OwnedByTask) pde->owned_by_task = true; - else - pde->owned_by_task = false; - if (will_flush_tlb) flush_tlb(vaddr); -} - -PageDirectoryEntry* VMM::find_pde(PageTable* root, uint64_t vaddr) -{ - uint64_t page_index; - PageDirectoryEntry* pde; - PageTable* pt = root; - - uint64_t indexes[3]; - - decompose_vaddr(vaddr, page_index, indexes[2], indexes[1], indexes[0]); - - for (int i = 0; i < 3; - i++) // Walk through the page map level 4, page directory pointer, and page directory to find the page table. - { - pde = &pt->entries[indexes[i]]; - if (!pde->present) return nullptr; - else if (pde->larger_pages) - return pde; - else { pt = (PageTable*)pde->get_address(); } - } - - pde = &pt->entries[page_index]; // PT - if (!pde->present) return nullptr; - return pde; -} - -PageDirectoryEntry* VMM::create_pde_if_not_exists(PageTable* root, uint64_t vaddr) -{ - uint64_t page_index; - PageDirectoryEntry* pde; - PageTable* pt = root; - - uint64_t indexes[3]; - - decompose_vaddr(vaddr, page_index, indexes[2], indexes[1], indexes[0]); - - auto pde_create_if_not_present = [&]() { - auto pt_or_error = PMM::request_page(); - ensure(pt_or_error.has_value()); - pt = (PageTable*)pt_or_error.release_value(); - memset(pt, 0, PAGE_SIZE); - pde->set_address((uint64_t)pt); - pde->present = true; - }; - - for (int i = 0; i < 3; i++) - { - pde = &pt->entries[indexes[i]]; - if (!pde->present) { pde_create_if_not_present(); } - else if (pde->larger_pages) - return pde; - else { pt = (PageTable*)pde->get_address(); } - } - - pde = &pt->entries[page_index]; - if (!pde->present) { pde->present = true; } - return pde; -} - -void VMM::propagate_read_write(PageTable* root, uint64_t vaddr) -{ - uint64_t page_index; - PageDirectoryEntry* pde; - PageTable* pt = root; - - uint64_t indexes[3]; - - decompose_vaddr(vaddr, page_index, indexes[2], indexes[1], indexes[0]); - - for (int i = 0; i < 3; i++) - { - pde = &pt->entries[indexes[i]]; - if (!pde->present) return; - else - { - pde->read_write = true; - if (pde->larger_pages) return; - pt = (PageTable*)pde->get_address(); - } - } - - pde = &pt->entries[page_index]; - if (!pde->present) return; - else - pde->read_write = true; -} - -void VMM::propagate_user(PageTable* root, uint64_t vaddr) -{ - uint64_t page_index; - PageDirectoryEntry* pde; - PageTable* pt = root; - - uint64_t indexes[3]; - - decompose_vaddr(vaddr, page_index, indexes[2], indexes[1], indexes[0]); - - for (int i = 0; i < 3; i++) - { - pde = &pt->entries[indexes[i]]; - if (!pde->present) return; - else - { - pde->user = true; - if (pde->larger_pages) return; - pt = (PageTable*)pde->get_address(); - } - } - - pde = &pt->entries[page_index]; - if (!pde->present) return; - else - pde->user = true; -} - -void VMM::propagate_no_execute(PageTable* root, uint64_t vaddr) -{ - uint64_t page_index; - PageDirectoryEntry* pde; - PageTable* pt = root; - - uint64_t indexes[3]; - - decompose_vaddr(vaddr, page_index, indexes[2], indexes[1], indexes[0]); - - for (int i = 0; i < 3; i++) - { - pde = &pt->entries[indexes[i]]; - if (!pde->present) return; - else - { - pde->no_execute = true; - if (pde->larger_pages) return; - pt = (PageTable*)pde->get_address(); - } - } - - pde = &pt->entries[page_index]; - if (!pde->present) return; - else - pde->no_execute = true; -} - -void VMM::flush_tlb(uint64_t addr) -{ - asm volatile("invlpg (%0)" : : "r"(addr) : "memory"); -} - -void VMM::flush_tlb_full() -{ - write_cr3(current_pml4); -} - -void VMM::decompose_vaddr(uint64_t vaddr, uint64_t& page_index, uint64_t& pt_index, uint64_t& pd_index, - uint64_t& pdp_index) -{ - vaddr >>= 12; - page_index = vaddr & 0x1ff; - vaddr >>= 9; - pt_index = vaddr & 0x1ff; - vaddr >>= 9; - pd_index = vaddr & 0x1ff; - vaddr >>= 9; - pdp_index = vaddr & 0x1ff; -} - -uint64_t VMM::recompose_vaddr(uint64_t page_index, uint64_t pt_index, uint64_t pd_index, uint64_t pdp_index) -{ - return pdp_index << 39 | pd_index << 30 | pt_index << 21 | page_index << 12; -} - -void VMM::install_kernel_page_directory_into_address_space(AddressSpace& space) -{ - PageTable* space_pml4 = space.get_pml4(); - PageTable* kernel_last_pdp = (PageTable*)kernel_pml4->entries[511].get_address(); - PageTable* kernel_last_pd = (PageTable*)kernel_last_pdp->entries[511].get_address(); - - PageDirectoryEntry& space_last_pdp_pde = space_pml4->entries[511]; - - PageTable* space_last_pdp; - - if (!space_last_pdp_pde.present) - { - auto result = PMM::request_page(); - ensure(result.has_value()); // FIXME: Propagate this error. - space_last_pdp = (PageTable*)result.release_value(); - - memset(space_last_pdp, 0, PAGE_SIZE); - - space_last_pdp_pde.present = true; - space_last_pdp_pde.read_write = true; - space_last_pdp_pde.set_address((uint64_t)space_last_pdp); - } - else { space_last_pdp = (PageTable*)space_last_pdp_pde.get_address(); } - - PageDirectoryEntry& space_last_pd_pde = space_last_pdp->entries[511]; - - space_last_pd_pde.present = true; - space_last_pd_pde.read_write = true; - space_last_pd_pde.set_address((uint64_t)kernel_last_pd); -} \ No newline at end of file diff --git a/kernel/src/memory/liballoc/bindings.cpp b/kernel/src/memory/liballoc/bindings.cpp deleted file mode 100644 index 91b53e54..00000000 --- a/kernel/src/memory/liballoc/bindings.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "memory/MemoryManager.h" -#include "thread/Spinlock.h" - -#include - -Spinlock alloc_lock; - -extern "C" int liballoc_lock() -{ - alloc_lock.acquire(); - return !alloc_lock.locked(); // Sanity check: the spinlock should be locked (return 0) -} - -extern "C" int liballoc_unlock() -{ - alloc_lock.release(); - return 0; // No sanity check this time because another thread could have acquired the lock the instant we let go of - // it. -} - -extern "C" void* liballoc_alloc(size_t count) -{ - return MemoryManager::get_pages(count).value_or(nullptr); -} - -extern "C" int liballoc_free(void* addr, size_t count) -{ - MemoryManager::release_pages(addr, count); - return 0; -} \ No newline at end of file diff --git a/kernel/src/memory/liballoc/liballoc.c b/kernel/src/memory/liballoc/liballoc.c deleted file mode 100644 index 6cc26933..00000000 --- a/kernel/src/memory/liballoc/liballoc.c +++ /dev/null @@ -1,721 +0,0 @@ -#define MODULE "alloc" - -#include "memory/liballoc/liballoc.h" -#include "log/CLog.h" - -#include - -#pragma GCC push_options -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" // FIXME: Actually solve these warnings. - -/** Durand's Amazing Super Duper Memory functions. */ - -#define VERSION "1.1" -#define ALIGNMENT \ - 16ul // 4ul ///< This is the byte alignment that memory must be allocated on. IMPORTANT for GTK and - // other stuff. - -#define ALIGN_TYPE char /// unsigned char[16] /// unsigned short -#define ALIGN_INFO \ - sizeof(ALIGN_TYPE) * 16 ///< Alignment information is stored right before the pointer. This is the number of bytes - ///< of information stored there. - -#define USE_CASE1 -#define USE_CASE2 -#define USE_CASE3 -#define USE_CASE4 -#define USE_CASE5 - -/** This macro will conveniently align our pointer upwards */ -#define ALIGN(ptr) \ - if (ALIGNMENT > 1) \ - { \ - uintptr_t align_diff; \ - ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \ - align_diff = (uintptr_t)ptr & (ALIGNMENT - 1); \ - if (align_diff != 0) \ - { \ - align_diff = ALIGNMENT - align_diff; \ - ptr = (void*)((uintptr_t)ptr + align_diff); \ - } \ - *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = align_diff + ALIGN_INFO; \ - } - -#define UNALIGN(ptr) \ - if (ALIGNMENT > 1) \ - { \ - uintptr_t align_diff = *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)); \ - if (align_diff < (ALIGNMENT + ALIGN_INFO)) { ptr = (void*)((uintptr_t)ptr - align_diff); } \ - } - -#define LIBALLOC_MAGIC 0xc001c0de -#define LIBALLOC_DEAD 0xdeaddead - -#if defined DEBUG || defined INFO -#include -#include - -#define FLUSH() - -#endif - -/** A structure found at the top of all system allocated - * memory blocks. It details the usage of the memory block. - */ -struct liballoc_major -{ - struct liballoc_major* prev; ///< Linked list information. - struct liballoc_major* next; ///< Linked list information. - unsigned int pages; ///< The number of pages in the block. - unsigned int size; ///< The number of pages in the block. - unsigned int usage; ///< The number of bytes used in the block. - struct liballoc_minor* first; ///< A pointer to the first allocated memory in the block. -}; - -/** This is a structure found at the beginning of all - * sections in a major block which were allocated by a - * malloc, calloc, realloc call. - */ -struct liballoc_minor -{ - struct liballoc_minor* prev; ///< Linked list information. - struct liballoc_minor* next; ///< Linked list information. - struct liballoc_major* block; ///< The owning block. A pointer to the major structure. - unsigned int magic; ///< A magic number to idenfity correctness. - unsigned int size; ///< The size of the memory allocated. Could be 1 byte or more. - unsigned int req_size; ///< The size of memory requested. -}; - -static struct liballoc_major* l_memRoot = NULL; ///< The root memory block acquired from the system. -static struct liballoc_major* l_bestBet = NULL; ///< The major with the most free memory. - -static unsigned int l_pageSize = 4096; ///< The size of an individual page. Set up in liballoc_init. -static unsigned int l_pageCount = 16; ///< The number of pages to request per chunk. Set up in liballoc_init. -static unsigned long long l_allocated = 0; ///< Running total of allocated memory. -static unsigned long long l_inuse = 0; ///< Running total of used memory. - -static long long l_warningCount = 0; ///< Number of warnings encountered -static long long l_errorCount = 0; ///< Number of actual errors -static long long l_possibleOverruns = 0; ///< Number of possible overruns - -// *********** HELPER FUNCTIONS ******************************* - -static void* liballoc_memset(void* s, int c, size_t n) -{ - unsigned int i; - for (i = 0; i < n; i++) ((char*)s)[i] = c; - - return s; -} -static void* liballoc_memcpy(void* s1, const void* s2, size_t n) -{ - char* cdest; - const char* csrc; - unsigned int* ldest = (unsigned int*)s1; - const unsigned int* lsrc = (const unsigned int*)s2; - - while (n >= sizeof(unsigned int)) - { - *ldest++ = *lsrc++; - n -= sizeof(unsigned int); - } - - cdest = (char*)ldest; - csrc = (const char*)lsrc; - - while (n > 0) - { - *cdest++ = *csrc++; - n -= 1; - } - - return s1; -} - -#if defined DEBUG || defined INFO -static void liballoc_dump() -{ -#ifdef DEBUG - struct liballoc_major* maj = l_memRoot; - struct liballoc_minor* min = NULL; -#endif - - printf("liballoc: ------ Memory data ---------------\n"); - printf("liballoc: System memory allocated: %i bytes\n", l_allocated); - printf("liballoc: Memory in used (malloc'ed): %i bytes\n", l_inuse); - printf("liballoc: Warning count: %i\n", l_warningCount); - printf("liballoc: Error count: %i\n", l_errorCount); - printf("liballoc: Possible overruns: %i\n", l_possibleOverruns); - -#ifdef DEBUG - while (maj != NULL) - { - printf("liballoc: %x: total = %i, used = %i\n", maj, maj->size, maj->usage); - - min = maj->first; - while (min != NULL) - { - printf("liballoc: %x: %i bytes\n", min, min->size); - min = min->next; - } - - maj = maj->next; - } -#endif - - FLUSH(); -} -#endif - -// *************************************************************** - -static struct liballoc_major* allocate_new_page(unsigned int size) -{ - unsigned int st; - struct liballoc_major* maj; - - // This is how much space is required. - st = size + sizeof(struct liballoc_major); - st += sizeof(struct liballoc_minor); - - // Perfect amount of space? - if ((st % l_pageSize) == 0) st = st / (l_pageSize); - else - st = st / (l_pageSize) + 1; - // No, add the buffer. - - // Make sure it's >= the minimum size. - if (st < l_pageCount) st = l_pageCount; - - maj = (struct liballoc_major*)liballoc_alloc(st); - - if (maj == NULL) - { - l_warningCount += 1; -#if defined DEBUG || defined INFO - printf("liballoc: WARNING: liballoc_alloc( %i ) return NULL\n", st); - FLUSH(); -#endif - return NULL; // uh oh, we ran out of memory. - } - - maj->prev = NULL; - maj->next = NULL; - maj->pages = st; - maj->size = st * l_pageSize; - maj->usage = sizeof(struct liballoc_major); - maj->first = NULL; - - l_allocated += maj->size; - -#ifdef DEBUG - printf("liballoc: Resource allocated %x of %i pages (%i bytes) for %i size.\n", maj, st, maj->size, size); - - printf("liballoc: Total memory usage = %i KB\n", (int)((l_allocated / (1024)))); - FLUSH(); -#endif - - return maj; -} - -void* PREFIX(malloc)(size_t req_size) -{ - int startedBet = 0; - unsigned long long bestSize = 0; - void* p = NULL; - uintptr_t diff; - struct liballoc_major* maj; - struct liballoc_minor* min; - struct liballoc_minor* new_min; - unsigned long size = req_size; - - // For alignment, we adjust size so there's enough space to align. - if (ALIGNMENT > 1) { size += ALIGNMENT + ALIGN_INFO; } - // So, ideally, we really want an alignment of 0 or 1 in order - // to save space. - - liballoc_lock(); - - if (size == 0) - { - l_warningCount += 1; -#if defined DEBUG || defined INFO - printf("liballoc: WARNING: alloc( 0 ) called from %x\n", __builtin_return_address(0)); - FLUSH(); -#endif - liballoc_unlock(); - return PREFIX(malloc)(1); - } - - if (l_memRoot == NULL) - { -#if defined DEBUG || defined INFO -#ifdef DEBUG - printf("liballoc: initialization of liballoc " VERSION "\n"); -#endif - atexit(liballoc_dump); - FLUSH(); -#endif - - // This is the first time we are being used. - l_memRoot = allocate_new_page(size); - if (l_memRoot == NULL) - { - liballoc_unlock(); -#ifdef DEBUG - printf("liballoc: initial l_memRoot initialization failed\n", p); - FLUSH(); -#endif - return NULL; - } - -#ifdef DEBUG - printf("liballoc: set up first memory major %x\n", l_memRoot); - FLUSH(); -#endif - } - -#ifdef DEBUG - printf("liballoc: %x PREFIX(malloc)( %i ): ", __builtin_return_address(0), size); - FLUSH(); -#endif - - // Now we need to bounce through every major and find enough space.... - - maj = l_memRoot; - startedBet = 0; - - // Start at the best bet.... - if (l_bestBet != NULL) - { - bestSize = l_bestBet->size - l_bestBet->usage; - - if (bestSize > (size + sizeof(struct liballoc_minor))) - { - maj = l_bestBet; - startedBet = 1; - } - } - - while (maj != NULL) - { - diff = maj->size - maj->usage; - // free memory in the block - - if (bestSize < diff) - { - // Hmm.. this one has more memory then our bestBet. Remember! - l_bestBet = maj; - bestSize = diff; - } - -#ifdef USE_CASE1 - - // CASE 1: There is not enough space in this major block. - if (diff < (size + sizeof(struct liballoc_minor))) - { -#ifdef DEBUG - printf("CASE 1: Insufficient space in block %x\n", maj); - FLUSH(); -#endif - - // Another major block next to this one? - if (maj->next != NULL) - { - maj = maj->next; // Hop to that one. - continue; - } - - if (startedBet == 1) // If we started at the best bet, - { // let's start all over again. - maj = l_memRoot; - startedBet = 0; - continue; - } - - // Create a new major block next to this one and... - maj->next = allocate_new_page(size); // next one will be okay. - if (maj->next == NULL) break; // no more memory. - maj->next->prev = maj; - maj = maj->next; - - // .. fall through to CASE 2 .. - } - -#endif - -#ifdef USE_CASE2 - - // CASE 2: It's a brand new block. - if (maj->first == NULL) - { - maj->first = (struct liballoc_minor*)((uintptr_t)maj + sizeof(struct liballoc_major)); - - maj->first->magic = LIBALLOC_MAGIC; - maj->first->prev = NULL; - maj->first->next = NULL; - maj->first->block = maj; - maj->first->size = size; - maj->first->req_size = req_size; - maj->usage += size + sizeof(struct liballoc_minor); - - l_inuse += size; - - p = (void*)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor)); - - ALIGN(p); - -#ifdef DEBUG - printf("CASE 2: returning %x\n", p); - FLUSH(); -#endif - liballoc_unlock(); // release the lock - return p; - } - -#endif - -#ifdef USE_CASE3 - - // CASE 3: Block in use and enough space at the start of the block. - diff = (uintptr_t)(maj->first); - diff -= (uintptr_t)maj; - diff -= sizeof(struct liballoc_major); - - if (diff >= (size + sizeof(struct liballoc_minor))) - { - // Yes, space in front. Squeeze in. - maj->first->prev = (struct liballoc_minor*)((uintptr_t)maj + sizeof(struct liballoc_major)); - maj->first->prev->next = maj->first; - maj->first = maj->first->prev; - - maj->first->magic = LIBALLOC_MAGIC; - maj->first->prev = NULL; - maj->first->block = maj; - maj->first->size = size; - maj->first->req_size = req_size; - maj->usage += size + sizeof(struct liballoc_minor); - - l_inuse += size; - - p = (void*)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor)); - ALIGN(p); - -#ifdef DEBUG - printf("CASE 3: returning %x\n", p); - FLUSH(); -#endif - liballoc_unlock(); // release the lock - return p; - } - -#endif - -#ifdef USE_CASE4 - - // CASE 4: There is enough space in this block. But is it contiguous? - min = maj->first; - - // Looping within the block now... - while (min != NULL) - { - // CASE 4.1: End of minors in a block. Space from last and end? - if (min->next == NULL) - { - // the rest of this block is free... is it big enough? - diff = (uintptr_t)(maj) + maj->size; - diff -= (uintptr_t)min; - diff -= sizeof(struct liballoc_minor); - diff -= min->size; - // minus already existing usage.. - - if (diff >= (size + sizeof(struct liballoc_minor))) - { - // yay.... - min->next = (struct liballoc_minor*)((uintptr_t)min + sizeof(struct liballoc_minor) + min->size); - min->next->prev = min; - min = min->next; - min->next = NULL; - min->magic = LIBALLOC_MAGIC; - min->block = maj; - min->size = size; - min->req_size = req_size; - maj->usage += size + sizeof(struct liballoc_minor); - - l_inuse += size; - - p = (void*)((uintptr_t)min + sizeof(struct liballoc_minor)); - ALIGN(p); - -#ifdef DEBUG - printf("CASE 4.1: returning %x\n", p); - FLUSH(); -#endif - liballoc_unlock(); // release the lock - return p; - } - } - - // CASE 4.2: Is there space between two minors? - if (min->next != NULL) - { - // is the difference between here and next big enough? - diff = (uintptr_t)(min->next); - diff -= (uintptr_t)min; - diff -= sizeof(struct liballoc_minor); - diff -= min->size; - // minus our existing usage. - - if (diff >= (size + sizeof(struct liballoc_minor))) - { - // yay...... - new_min = (struct liballoc_minor*)((uintptr_t)min + sizeof(struct liballoc_minor) + min->size); - - new_min->magic = LIBALLOC_MAGIC; - new_min->next = min->next; - new_min->prev = min; - new_min->size = size; - new_min->req_size = req_size; - new_min->block = maj; - min->next->prev = new_min; - min->next = new_min; - maj->usage += size + sizeof(struct liballoc_minor); - - l_inuse += size; - - p = (void*)((uintptr_t)new_min + sizeof(struct liballoc_minor)); - ALIGN(p); - -#ifdef DEBUG - printf("CASE 4.2: returning %x\n", p); - FLUSH(); -#endif - - liballoc_unlock(); // release the lock - return p; - } - } // min->next != NULL - - min = min->next; - } // while min != NULL ... - -#endif - -#ifdef USE_CASE5 - - // CASE 5: Block full! Ensure next block and loop. - if (maj->next == NULL) - { -#ifdef DEBUG - printf("CASE 5: block full\n"); - FLUSH(); -#endif - - if (startedBet == 1) - { - maj = l_memRoot; - startedBet = 0; - continue; - } - - // we've run out. we need more... - maj->next = allocate_new_page(size); // next one guaranteed to be okay - if (maj->next == NULL) break; // uh oh, no more memory..... - maj->next->prev = maj; - } - -#endif - - maj = maj->next; - } // while (maj != NULL) - - liballoc_unlock(); // release the lock - -#ifdef DEBUG - printf("All cases exhausted. No memory available.\n"); - FLUSH(); -#endif -#if defined DEBUG || defined INFO - printf("liballoc: WARNING: PREFIX(malloc)( %i ) returning NULL.\n", size); - liballoc_dump(); - FLUSH(); -#endif - return NULL; -} - -void PREFIX(free)(void* ptr) -{ - struct liballoc_minor* min; - struct liballoc_major* maj; - - if (ptr == NULL) - { - l_warningCount += 1; - kwarnln("kfree( NULL ) called from %p", __builtin_return_address(0)); - return; - } - - UNALIGN(ptr); - - liballoc_lock(); // lockit - - min = (struct liballoc_minor*)((uintptr_t)ptr - sizeof(struct liballoc_minor)); - - if (min->magic != LIBALLOC_MAGIC) - { - l_errorCount += 1; - - // Check for overrun errors. For all bytes of LIBALLOC_MAGIC - if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) || - ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) || ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) - { - l_possibleOverruns += 1; - kerrorln("Possible 1-3 byte overrun for magic %x != %x", min->magic, LIBALLOC_MAGIC); - } - - if (min->magic == LIBALLOC_DEAD) - { - kerrorln("double free attempt on %p from %p.", ptr, __builtin_return_address(0)); - } - else { kerrorln("Bad kfree(%p) called from %p\n", ptr, __builtin_return_address(0)); } - - // being lied to... - liballoc_unlock(); // release the lock - return; - } - -#ifdef DEBUG - printf("liballoc: %x PREFIX(free)( %x ): ", __builtin_return_address(0), ptr); - FLUSH(); -#endif - - maj = min->block; - - l_inuse -= min->size; - - maj->usage -= (min->size + sizeof(struct liballoc_minor)); - min->magic = LIBALLOC_DEAD; // No mojo. - - if (min->next != NULL) min->next->prev = min->prev; - if (min->prev != NULL) min->prev->next = min->next; - - if (min->prev == NULL) maj->first = min->next; - // Might empty the block. This was the first - // minor. - - // We need to clean up after the majors now.... - - if (maj->first == NULL) // Block completely unused. - { - if (l_memRoot == maj) l_memRoot = maj->next; - if (l_bestBet == maj) l_bestBet = NULL; - if (maj->prev != NULL) maj->prev->next = maj->next; - if (maj->next != NULL) maj->next->prev = maj->prev; - l_allocated -= maj->size; - - liballoc_free(maj, maj->pages); - } - else - { - if (l_bestBet != NULL) - { - int bestSize = l_bestBet->size - l_bestBet->usage; - int majSize = maj->size - maj->usage; - - if (majSize > bestSize) l_bestBet = maj; - } - } - -#ifdef DEBUG - printf("OK\n"); - FLUSH(); -#endif - - liballoc_unlock(); // release the lock -} - -void* PREFIX(calloc)(size_t nobj, size_t size) -{ - int real_size; - void* p; - - real_size = nobj * size; - - p = PREFIX(malloc)(real_size); - - liballoc_memset(p, 0, real_size); - - return p; -} - -void* PREFIX(realloc)(void* p, size_t size) -{ - void* ptr; - struct liballoc_minor* min; - unsigned int real_size; - - // Honour the case of size == 0 => free old and return NULL - if (size == 0) - { - PREFIX(free)(p); - return NULL; - } - - // In the case of a NULL pointer, return a simple malloc. - if (p == NULL) return PREFIX(malloc)(size); - - // Unalign the pointer if required. - ptr = p; - UNALIGN(ptr); - - liballoc_lock(); // lockit - - min = (struct liballoc_minor*)((uintptr_t)ptr - sizeof(struct liballoc_minor)); - - // Ensure it is a valid structure. - if (min->magic != LIBALLOC_MAGIC) - { - l_errorCount += 1; - - // Check for overrun errors. For all bytes of LIBALLOC_MAGIC - if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) || - ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) || ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) - { - l_possibleOverruns += 1; - kerrorln("Possible 1-3 byte overrun for magic %x != %x", min->magic, LIBALLOC_MAGIC); - } - - if (min->magic == LIBALLOC_DEAD) - { - kerrorln("realloc after free attempt on %p from %p.", ptr, __builtin_return_address(0)); - } - else { kerrorln("Bad krealloc(%p) called from %p\n", ptr, __builtin_return_address(0)); } - - // being lied to... - liballoc_unlock(); // release the lock - return NULL; - } - - // Definitely a memory block. - - real_size = min->req_size; - - if (real_size >= size) - { - min->req_size = size; - liballoc_unlock(); - return p; - } - - liballoc_unlock(); - - // If we got here then we're reallocating to a block bigger than us. - ptr = PREFIX(malloc)(size); // We need to allocate new memory - liballoc_memcpy(ptr, p, real_size); - PREFIX(free)(p); - - return ptr; -} - -#pragma GCC pop_options diff --git a/kernel/src/misc/MSR.cpp b/kernel/src/misc/MSR.cpp deleted file mode 100644 index d38140bd..00000000 --- a/kernel/src/misc/MSR.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "misc/MSR.h" - -void MSR::write_to(uint32_t msr_num, uint64_t value) -{ - uint32_t lo = value & 0xFFFFFFFF; - uint32_t hi = (uint32_t)(value >> 32); - asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr_num)); -} - -uint64_t MSR::read_from(uint32_t msr_num) -{ - uint32_t lo; - uint32_t hi; - asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr_num)); - return (uint64_t)hi << 32 | (uint64_t)lo; -} - -void MSR::write(uint64_t value) -{ - write_to(m_msr_num, value); -} - -uint64_t MSR::read() -{ - return read_from(m_msr_num); -} - -MSR::MSR(uint32_t msr_num) : m_msr_num(msr_num) -{ -} - -void MSR::with_value_of(uint32_t msr_num, void (*callback)(uint64_t&)) -{ - MSR msr(msr_num); - msr.with_value(callback); -} - -void MSR::with_value(void (*callback)(uint64_t&)) -{ - uint64_t value = read(); - callback(value); - write(value); -} \ No newline at end of file diff --git a/kernel/src/misc/PCITypes.cpp b/kernel/src/misc/PCITypes.cpp deleted file mode 100644 index d8a49c5e..00000000 --- a/kernel/src/misc/PCITypes.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "misc/PCITypes.h" - -static const char* unclassified_device(PCI::DeviceType type) -{ - switch (type.dev_subclass) - { - case 0x0: return "Non-VGA-Compatible Unclassified Device"; - case 0x1: return "VGA-Compatible Unclassified Device"; - - default: return "Unclassified"; - } -} - -static const char* display_controller(PCI::DeviceType type) -{ - switch (type.dev_subclass) - { - case 0x0: return type.prog_if == 1 ? "8514-Compatible Controller" : "VGA Controller"; - case 0x1: return "XGA Controller"; - case 0x2: return "3D Controller (Not VGA-Compatible)"; - case 0x80: return "Display Controller"; - - default: return "Unknown Display Controller"; - } -} - -static const char* memory_controller(PCI::DeviceType type) -{ - switch (type.dev_subclass) - { - case 0x0: return "RAM Controller"; - case 0x1: return "Flash Controller"; - case 0x80: return "Memory Controller"; - - default: return "Unknown Memory Controller"; - } -} - -static const char* processor(PCI::DeviceType type) -{ - switch (type.dev_subclass) - { - case 0x0: return "Processor (386)"; - case 0x1: return "Processor (486)"; - case 0x2: return "Processor (Pentium)"; - case 0x3: return "Processor (Pentium Pro)"; - case 0x10: return "Processor (Alpha)"; - case 0x20: return "Processor (PowerPC)"; - case 0x30: return "Processor (MIPS)"; - case 0x40: return "Co-Processor"; - case 0x80: return "Processor"; - - default: return "Unknown Processor"; - } -} - -const char* pci_type_name(PCI::DeviceType type) -{ - switch (type.dev_class) - { - case 0x0: return unclassified_device(type); - case 0x1: return "Mass Storage Controller"; - case 0x2: return "Network Controller"; - case 0x3: return display_controller(type); - case 0x4: return "Multimedia Controller"; - case 0x5: return memory_controller(type); - case 0x6: return "Bridge"; - case 0x7: return "Simple Communication Controller"; - case 0x8: return "Base System Peripheral"; - case 0x9: return "Input Device Controller"; - case 0xA: return "Docking Station"; - case 0xB: return processor(type); - case 0xC: return "Serial Bus Controller"; - case 0xD: return "Wireless Controller"; - case 0xE: return "Intelligent Controller (I20)"; - case 0xF: return "Satellite Communication Controller"; - case 0x10: return "Encryption Controller"; - case 0x11: return "Signal Processing Controller"; - case 0x12: return "Processing Accelerator"; - case 0x13: return "Non-Essential Instrumentation"; - case 0x40: return "Co-Processor"; - - default: return "Unknown"; - } -} \ No newline at end of file diff --git a/kernel/src/misc/Scancodes.cpp b/kernel/src/misc/Scancodes.cpp deleted file mode 100644 index c694a4d5..00000000 --- a/kernel/src/misc/Scancodes.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include "misc/Scancodes.h" - -#define SCANCODE_EXTENDED 0xE0 - -bool scancode_filter_released(unsigned char* scancode) -{ - if (*scancode > 0x80) - { - *scancode -= 0x80; - return true; - } - return false; -} - -static bool next_key_ignored = false; // FIXME: Do not ignore extended scancodes. - -static bool left_shifted = false; -static bool right_shifted = false; -static bool capslock = false; - -static bool should_shift() -{ - if (capslock) return !(left_shifted || right_shifted); - return left_shifted || right_shifted; -} - -#define SCANCODE_LEFT_SHIFT 0x2A -#define SCANCODE_RIGHT_SHIFT 0x36 -#define SCANCODE_CAPS_LOCK 0x3A - -#define SCANCODE_LEFT_CONTROL 0x1D -#define SCANCODE_TAB 0x0F -#define SCANCODE_LEFT_ALT 0x38 -#define SCANCODE_F11 0x57 -#define SCANCODE_F12 0x58 - -static bool should_ignore_key(char scancode) -{ - return (scancode > 0x3A && scancode < 0x47) || scancode == SCANCODE_LEFT_CONTROL || scancode == SCANCODE_TAB || - scancode == SCANCODE_LEFT_ALT || scancode == SCANCODE_F11 || scancode == SCANCODE_F12; -} - -char keys_normal[] = { - '\0', - '\1', // escape - '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', - '\0', // tab - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', - '\0', // left ctrl - 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', - '\0', // left shift - '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', - '\0', // right shift - '*', // keypad * - '\0', // left alt - ' ', - '\0', // caps lock - '\0', // f1 - '\0', // f2 - '\0', // f3 - '\0', // f4 - '\0', // f5 - '\0', // f6 - '\0', // f7 - '\0', // f8 - '\0', // f9 - '\0', // f10 - '\0', // num lock - '\0', // scroll lock - '7', // keypad 7 - '8', // keypad 8 - '9', // keypad 9 - '-', // keypad - - '4', // keypad 4 - '5', // keypad 5 - '6', // keypad 6 - '+', // keypad + - '1', // keypad 1 - '2', // keypad 2 - '3', // keypad 3 - '0', // keypad 0 - '.', // keypad . -}; - -char keys_shifted[] = { - '\0', - '\1', // escape - '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', - '\0', // tab - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', - '\0', // left ctrl - 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', - '\0', // left shift - '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', - '\0', // right shift - '*', // keypad * - '\0', // left alt - ' ', - '\0', // caps lock - '\0', // f1 - '\0', // f2 - '\0', // f3 - '\0', // f4 - '\0', // f5 - '\0', // f6 - '\0', // f7 - '\0', // f8 - '\0', // f9 - '\0', // f10 - '\0', // num lock - '\0', // scroll lock - '7', // keypad 7 - '8', // keypad 8 - '9', // keypad 9 - '-', // keypad - - '4', // keypad 4 - '5', // keypad 5 - '6', // keypad 6 - '+', // keypad + - '1', // keypad 1 - '2', // keypad 2 - '3', // keypad 3 - '0', // keypad 0 - '.', // keypad . -}; - -char translate_scancode(unsigned char scancode, bool* ignore) -{ - if (next_key_ignored) - { - next_key_ignored = false; - *ignore = true; - return 0; - } - if (scancode == SCANCODE_EXTENDED) - { - next_key_ignored = true; - *ignore = true; - return 0; - } - bool released = scancode_filter_released(&scancode); - if (scancode == SCANCODE_CAPS_LOCK) - { - if (!released) { capslock = !capslock; } - *ignore = true; - return 0; - } - if (scancode == SCANCODE_LEFT_SHIFT) - { - left_shifted = !released; - *ignore = true; - return 0; - } - if (scancode == SCANCODE_RIGHT_SHIFT) - { - right_shifted = !released; - *ignore = true; - return 0; - } - if (released || should_ignore_key(scancode)) - { - *ignore = true; - return 0; - } - *ignore = false; - if (should_shift()) { return keys_shifted[scancode]; } - return keys_normal[scancode]; -} \ No newline at end of file diff --git a/kernel/src/misc/config.cpp b/kernel/src/misc/config.cpp deleted file mode 100644 index 0e364f8f..00000000 --- a/kernel/src/misc/config.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "config.h" - -#define STRINGIZE(x) #x -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) - -#ifndef MOON_MAJOR -#define MOON_MAJOR 0 -#endif - -#ifndef MOON_MINOR -#define MOON_MINOR 15 -#endif - -#ifndef _MOON_SUFFIX -#define MOON_SUFFIX "" -#else -#define MOON_SUFFIX STRINGIZE_VALUE_OF(_MOON_SUFFIX) -#endif - -int __moon_version_major() -{ - return MOON_MAJOR; -} - -int __moon_version_minor() -{ - return MOON_MINOR; -} - -const char* __moon_version_suffix() -{ - return MOON_SUFFIX; -} - -const char* moon_version() -{ - return STRINGIZE_VALUE_OF(MOON_MAJOR) "." STRINGIZE_VALUE_OF(MOON_MINOR) MOON_SUFFIX; -} diff --git a/kernel/src/misc/cxxabi.cpp b/kernel/src/misc/cxxabi.cpp deleted file mode 100644 index 48898377..00000000 --- a/kernel/src/misc/cxxabi.cpp +++ /dev/null @@ -1,52 +0,0 @@ -typedef void* (*cxa_atexit_func_t)(void*); - -struct cxa_atexit_entry -{ - cxa_atexit_func_t function; - void* argument; - void* dso_handle; -}; - -#define CXA_ATEXIT_MAX 64 - -int cxa_atexit_entry_count = 0; - -cxa_atexit_entry cxa_atexit_entries[CXA_ATEXIT_MAX]; - -__attribute__((visibility("hidden"))) void* __dso_handle = 0; - -extern "C" -{ - int __cxa_atexit(cxa_atexit_func_t func, void* arg, void* dso) - { - if (cxa_atexit_entry_count >= CXA_ATEXIT_MAX) return -1; - cxa_atexit_entries[cxa_atexit_entry_count].function = func; - cxa_atexit_entries[cxa_atexit_entry_count].argument = arg; - cxa_atexit_entries[cxa_atexit_entry_count].dso_handle = dso; - cxa_atexit_entry_count++; - return 0; - } - - void __cxa_finalize(void* f) - { - int i = cxa_atexit_entry_count; - if (!f) - { - while (i--) - { - if (cxa_atexit_entries[i].function) { cxa_atexit_entries[i].function(cxa_atexit_entries[i].argument); } - } - } - else - { - while (i--) - { - if (cxa_atexit_entries[i].function == (cxa_atexit_func_t)f) - { - cxa_atexit_entries[i].function(cxa_atexit_entries[i].argument); - cxa_atexit_entries[i].function = 0; - } - } - } - } -} \ No newline at end of file diff --git a/kernel/src/misc/hang.cpp b/kernel/src/misc/hang.cpp deleted file mode 100644 index e655f0c5..00000000 --- a/kernel/src/misc/hang.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "misc/hang.h" - -[[noreturn]] void hang() -{ - asm volatile("cli"); -end: - halt(); - goto end; -} - -void halt() -{ - asm volatile("hlt"); -} \ No newline at end of file diff --git a/kernel/src/misc/new.cpp b/kernel/src/misc/new.cpp deleted file mode 100644 index 8ecd8175..00000000 --- a/kernel/src/misc/new.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "std/stdlib.h" -#include - -void* operator new(size_t size) -{ - return kmalloc(size); -} - -void* operator new[](size_t size) -{ - return kmalloc(size); -} - -void operator delete(void* p) -{ - kfree(p); -} - -void operator delete[](void* p) -{ - kfree(p); -} - -void operator delete(void* p, size_t) -{ - kfree(p); -} - -void operator delete[](void* p, size_t) -{ - kfree(p); -} \ No newline at end of file diff --git a/kernel/src/misc/reboot.cpp b/kernel/src/misc/reboot.cpp deleted file mode 100644 index 8f134556..00000000 --- a/kernel/src/misc/reboot.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#define MODULE "power" - -#include "misc/reboot.h" -#include "acpi/FADT.h" -#include "acpi/RSDT.h" -#include "assert.h" -#include "interrupts/IDT.h" -#include "interrupts/Interrupts.h" -#include "io/IO.h" -#include "log/Log.h" -#include "memory/VMM.h" -#include "misc/hang.h" -#include "std/string.h" - -static void try_acpi_reboot() -{ - kdbgln("Fetching pointer to RSDT/XSDT"); - ACPI::SDTHeader* rootSDT = ACPI::get_rsdt_or_xsdt(); - if (!rootSDT) - { - kwarnln("The pointer to the RSDT/XSDT is null"); - return; - } - if (!ACPI::validate_rsdt_or_xsdt(rootSDT)) - { - kwarnln("The RSDT/XSDT is invalid"); - return; - } - kdbgln("Searching for the FADT"); - ACPI::FADT* fadt = (ACPI::FADT*)ACPI::find_table(rootSDT, "FACP"); - if (!fadt) - { - kwarnln("Unable to find the FADT"); - return; - } - if (fadt->header.Revision < 2) - { - kwarnln("ACPI revision is too low (%d), ACPI Reset is only implemented in ACPI 2.0+", fadt->header.Revision); - return; - } - if (!(fadt->Flags & 1 << 10)) - { - kwarnln("This system does not support ACPI Reset"); - return; - } - switch (fadt->ResetReg.AddressSpace) - { - case ACPI::SystemIO: - kdbgln("Attempting ACPI Reset via SystemIO: sending byte %d to port %lx", fadt->ResetValue, - fadt->ResetReg.Address); - IO::outb((uint16_t)fadt->ResetReg.Address, fadt->ResetValue); - break; - case ACPI::GeneralPurposeIO: - kdbgln("Attempting ACPI Reset via GeneralPurposeIO: sending byte %d to port %lx", fadt->ResetValue, - fadt->ResetReg.Address); - IO::outb((uint16_t)fadt->ResetReg.Address, fadt->ResetValue); - break; - default: kwarnln("This method of rebooting via ACPI is not yet implemented"); return; - } - kerrorln("Tried to reboot, but apparently did nothing"); -} - -static void try_kbd_reboot() -{ - Interrupts::disable(); - - uint8_t temp; - do { - temp = IO::inb(0x64); - if (temp & 0b1) IO::inb(0x60); - } while (temp & 0b10); - - IO::outb(0x64, 0xFE); -} - -static void try_idt_triple_fault() -{ - IDTR idtr; - idtr.limit = 0x0000; - idtr.offset = 0x0000; - asm volatile("lidt %0" : : "m"(idtr)); - Interrupts::enable(); - asm volatile("int $0x80"); -} - -[[noreturn]] void reboot() -{ - Interrupts::disable(); - if (!VMM::is_using_kernel_address_space()) - { - VMM::switch_back_to_kernel_address_space(); - VMM::apply_address_space(); - } - kinfoln("Attempting reboot using ACPI"); - try_acpi_reboot(); - kinfoln("Attempting reboot using keyboard RESET pulsing"); - try_kbd_reboot(); - kinfoln("Attempting reboot by triple faulting"); - try_idt_triple_fault(); - kerrorln("Failed to reboot, halting machine"); - hang(); -} \ No newline at end of file diff --git a/kernel/src/misc/shutdown.cpp b/kernel/src/misc/shutdown.cpp deleted file mode 100644 index 3087ab1a..00000000 --- a/kernel/src/misc/shutdown.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#define MODULE "power" - -#include "misc/shutdown.h" -#include "interrupts/Interrupts.h" -#include "io/IO.h" -#include "log/Log.h" -#include "misc/hang.h" - -[[noreturn]] void shutdown() -{ - Interrupts::disable(); - kinfoln("Attempting shutdown using the Bochs method"); - IO::outw(0xB004, 0x2000); - kinfoln("Attempting shutdown using the QEMU method"); - IO::outw(0x604, 0x2000); - kinfoln("Attempting shutdown using the VirtualBox method"); - IO::outw(0x4004, 0x3400); - kerrorln("Failed to shutdown, halting. It is now safe to turn off your computer manually, though."); - hang(); -} \ No newline at end of file diff --git a/kernel/src/misc/stack.cpp b/kernel/src/misc/stack.cpp deleted file mode 100644 index 781b9f29..00000000 --- a/kernel/src/misc/stack.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#define MODULE "stack" - -#include "log/Log.h" -#include "misc/hang.h" -#include "render/TextRenderer.h" -#include - -extern "C" void __stack_chk_fail() -{ - KernelLog::enable_log_backend(Backend::Console); - TextRenderer::reset(); - kerrorln("stack smashing detected"); - hang(); -} \ No newline at end of file diff --git a/kernel/src/misc/ubsan.cpp b/kernel/src/misc/ubsan.cpp deleted file mode 100644 index d9394956..00000000 --- a/kernel/src/misc/ubsan.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#define MODULE "ubsan" - -#include -#include -#include - -#pragma GCC push_options -#pragma GCC diagnostic ignored "-Wpedantic" - -struct source_location -{ - const char* file; - uint32_t line; - uint32_t column; -}; - -struct type_descriptor -{ - uint16_t kind; - uint16_t info; - char name[]; -}; - -struct type_mismatch_info -{ - struct source_location location; - struct type_descriptor* type; - uintptr_t alignment; - uint8_t type_check_kind; -}; - -struct type_mismatch_info_v1 -{ - struct source_location location; - struct type_descriptor* type; - unsigned char log_alignment; - unsigned char type_check_kind; -}; - -struct overflow_info -{ - struct source_location location; - struct type_descriptor* type; -}; - -struct unreachable_info -{ - struct source_location location; -}; - -struct out_of_bounds_info -{ - struct source_location location; - struct type_descriptor* array_type; - struct type_descriptor* index_type; -}; - -struct invalid_value_info -{ - struct source_location location; - struct type_descriptor* type; -}; - -struct shift_out_of_bounds_info -{ - struct source_location location; - struct type_descriptor* lhs_type; - struct type_descriptor* rhs_type; -}; - -struct pointer_overflow_info -{ - struct source_location location; -}; - -#define is_aligned(value, alignment) !(value & (alignment - 1)) - -const char* Type_Check_Kinds[] = { - "load of", - "store to", - "reference binding to", - "member access within", - "member call on", - "constructor call on", - "downcast of", - "downcast of", - "upcast of", - "cast to virtual base of", -}; - -static void log_location(source_location* location) -{ - kinfoln("at %s:%d:%d", location->file, location->line, location->column); -} - -extern "C" void __ubsan_handle_type_mismatch(type_mismatch_info* type_mismatch, uintptr_t pointer) -{ - source_location* location = &type_mismatch->location; - if (pointer == 0) { kinfoln("Null pointer access"); } - else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment)) - { - // Most useful on architectures with stricter memory alignment requirements, like ARM. - kinfoln("Unaligned memory access"); - } - else - { - kinfoln("Insufficient size"); - kinfoln("%s address %p with insufficient space for object of type %s\n", - Type_Check_Kinds[type_mismatch->type_check_kind], (void*)pointer, type_mismatch->type->name); - } - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_type_mismatch_v1(type_mismatch_info_v1* type_mismatch, unsigned long pointer) -{ - type_mismatch_info info = {type_mismatch->location, type_mismatch->type, 1UL << type_mismatch->log_alignment, - type_mismatch->type_check_kind}; - - __ubsan_handle_type_mismatch(&info, pointer); -} - -extern "C" void __ubsan_handle_add_overflow(overflow_info* overflow_data, uintptr_t, uintptr_t) -{ - source_location* location = &overflow_data->location; - kinfoln("Addition overflow for two values of type %s", overflow_data->type->name); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_sub_overflow(overflow_info* overflow_data, uintptr_t, uintptr_t) -{ - source_location* location = &overflow_data->location; - kinfoln("Substraction overflow for two values of type %s", overflow_data->type->name); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_mul_overflow(overflow_info* overflow_data, uintptr_t, uintptr_t) -{ - source_location* location = &overflow_data->location; - kinfoln("Multiplication overflow for two values of type %s", overflow_data->type->name); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_negate_overflow(overflow_info* overflow_data, uintptr_t) -{ - source_location* location = &overflow_data->location; - kinfoln("Negation overflow for two values of type %s", overflow_data->type->name); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_divrem_overflow(overflow_info* overflow_data, uintptr_t, uintptr_t) -{ - source_location* location = &overflow_data->location; - kinfoln("Division overflow for two values of type %s", overflow_data->type->name); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_builtin_unreachable(unreachable_info* unreachable_data) -{ - source_location* location = &unreachable_data->location; - kinfoln("Reached the unreachable"); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_out_of_bounds(out_of_bounds_info* out_of_bounds_data, uintptr_t index) -{ - source_location* location = &out_of_bounds_data->location; - kinfoln("Out of bounds access at index %ld of array type %s and index type %s", index, - out_of_bounds_data->array_type->name, out_of_bounds_data->index_type->name); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_load_invalid_value(invalid_value_info* invalid_value_data, uintptr_t) -{ - source_location* location = &invalid_value_data->location; - kinfoln("Invalid value load of type %s", invalid_value_data->type->name); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_shift_out_of_bounds(shift_out_of_bounds_info* shift_out_of_bounds_data, uintptr_t, - uintptr_t) -{ - source_location* location = &shift_out_of_bounds_data->location; - kinfoln("Shift out of bounds for type %s", shift_out_of_bounds_data->lhs_type->name); - log_location(location); - panic("Undefined behaviour detected"); -} - -extern "C" void __ubsan_handle_pointer_overflow(pointer_overflow_info* pointer_overflow_data, uintptr_t, uintptr_t) -{ - source_location* location = &pointer_overflow_data->location; - kinfoln("Pointer overflow"); - log_location(location); - panic("Undefined behaviour detected"); -} - -#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/panic/Panic.cpp b/kernel/src/panic/Panic.cpp deleted file mode 100644 index 1e6565e0..00000000 --- a/kernel/src/panic/Panic.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#define MODULE "panic" - -#include "panic/Panic.h" -#include "fs/InitRD.h" -#include "interrupts/IDT.h" -#include "io/PIC.h" -#include "log/Log.h" -#include "memory/VMM.h" -#include "misc/MSR.h" -#include "render/Framebuffer.h" -#include "render/TextRenderer.h" -#include "std/stdio.h" -#include "thread/Scheduler.h" -#include "trace/StackTracer.h" - -static bool g_is_in_panic = false; -static bool g_is_in_double_panic = false; - -void panic_prepare_keyboard_triple_fault() -{ - PIC::enable_master(0b11111101); // enable keyboard only - PIC::enable_slave(0b11111111); - - IDTR idtr; - idtr.limit = 0x0000; - idtr.offset = 0x0000; - asm volatile( - "lidt %0" - : - : "m"( - idtr)); // when an interrupt arrives, triple-fault (the only interrupt that should come is the keyboard one) - - asm volatile("sti"); -} - -void dump_registers(Context* context) -{ - kinfoln("-- Registers:"); - kinfoln("rax: %lx, rbx: %lx, rcx: %lx, rdx: %lx", context->rax, context->rbx, context->rcx, context->rdx); - kinfoln("rsi: %lx, rdi: %lx, rsp: %lx, rbp: %lx", context->rsi, context->rdi, context->rsp, context->rbp); - kinfoln("r8: %lx, r9: %lx, r10: %lx, r11: %lx", context->r8, context->r9, context->r10, context->r11); - kinfoln("r12: %lx, r13: %lx, r14: %lx, r15: %lx", context->r12, context->r13, context->r14, context->r15); - kinfoln("rip: %lx, cs: %lx, ss: %lx", context->rip, context->cs, context->ss); - kinfoln("rflags: %lx, cr2: %lx", context->rflags, context->cr2); - kinfoln("ia32_efer: %lx", MSR::read_from(IA32_EFER_MSR)); -} - -void fatal_dump_registers(Context* context) -{ - printf("-- Possibly Relevant Registers:\n"); - printf("rbp: %lx, rsp: %lx, rip: %lx, cs: %lx, ss: %lx, rflags: %lx, cr2: %lx, error code: %lx\n", context->rbp, - context->rsp, context->rip, context->cs, context->ss, context->rflags, context->cr2, context->error_code); -} - -[[noreturn]] void __panic_fatal_stub(Context* context) -{ - if (context) fatal_dump_registers(context); - printf("-- No stack trace available\n"); - - KernelLog::enable_log_backend(Backend::Console); - KernelLog::toggle_log_backend( - Backend::Console); // disable console logging, as we can page fault while writing to the framebuffer. - - Scheduler::current_task()->id = 0; // we're panicking, we don't even care anymore. This is so KernelLog shows - // (kernel) instead of (taskname: PID) in the log. - - panic_prepare_keyboard_triple_fault(); - - printf("Press any key to restart.\n"); - - while (1) asm volatile("hlt"); -} - -[[noreturn]] void __panic_stub(Context* context) -{ - VMM::switch_back_to_kernel_address_space(); - VMM::apply_address_space(); - if (context) dump_registers(context); - - if (InitRD::is_initialized()) - { - kinfoln("-- Stack trace:"); - if (context) - { - StackTracer tracer(context->rbp); - tracer.trace_with_ip(context->rip); - } - else - { - uintptr_t rbp; - - asm volatile("mov %%rbp, %0" : "=r"(rbp)); - StackTracer tracer(rbp); - tracer.trace(); - } - } - else { kinfoln("-- No stack trace available"); } - - panic_prepare_keyboard_triple_fault(); - - while (1) asm volatile("hlt"); -} - -extern "C" [[noreturn]] bool __do_int_panic(Context* context, const char* file, int line, const char* message) -{ - asm volatile("cli"); - - if (g_is_in_double_panic) - { - panic_prepare_keyboard_triple_fault(); - while (1) asm volatile("hlt"); - } - - if (g_is_in_panic) - { - g_is_in_double_panic = true; - printf("Kernel panic while panicking (showing vital information only) at %s, line %d: %s\n", file, line, - message); - __panic_fatal_stub(context); - } - - g_is_in_panic = true; - - KernelLog::enable_log_backend(Backend::Console); - - TextRenderer::reset(); - - framebuffer0.clear(Color::Black); - - if (context->number >= 0x20 && context->number < 0x30) { PIC::send_eoi((uint8_t)(context->irq_number & 0xFF)); } - - Task* task; - if ((task = Scheduler::current_task())) - { - kerrorln("Kernel panic in task %ld, at %s, line %d: %s", task->id, file, line, message); - } - else { kerrorln("Kernel panic at %s, line %d: %s", file, line, message); } - - __panic_stub(context); -} - -extern "C" [[noreturn]] bool __do_panic(const char* file, int line, const char* message) -{ - asm volatile("cli"); - - if (g_is_in_double_panic) - { - panic_prepare_keyboard_triple_fault(); - while (1) asm volatile("hlt"); - } - - if (g_is_in_panic) - { - g_is_in_double_panic = true; - printf("Kernel panic while panicking (showing vital information only) at %s, line %d: %s\n", file, line, - message); - __panic_fatal_stub(nullptr); - } - - g_is_in_panic = true; - - KernelLog::enable_log_backend(Backend::Console); - - TextRenderer::reset(); - - framebuffer0.clear(Color::Black); - - Task* task; - if ((task = Scheduler::current_task())) - { - kerrorln("Kernel panic in task %ld, at %s, line %d: %s", task->id, file, line, message); - } - else { kerrorln("Kernel panic at %s, line %d: %s", file, line, message); } - - __panic_stub(nullptr); -} \ No newline at end of file diff --git a/kernel/src/rand/Init.asm b/kernel/src/rand/Init.asm deleted file mode 100644 index 9dbe3db8..00000000 --- a/kernel/src/rand/Init.asm +++ /dev/null @@ -1,11 +0,0 @@ -global asm_test_rdseed - -asm_test_rdseed: - xor rax, rax - mov eax, 7 - mov ecx, 0 - cpuid - shr ebx, 18 - and ebx, 1 - mov eax, ebx - ret \ No newline at end of file diff --git a/kernel/src/rand/Init.cpp b/kernel/src/rand/Init.cpp deleted file mode 100644 index 79f9569b..00000000 --- a/kernel/src/rand/Init.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#define MODULE "rand" - -#include "rand/Init.h" -#include "config.h" -#include "cpu/CPU.h" -#include "io/IO.h" -#include "log/Log.h" -#include "rand/Mersenne.h" - -static uint64_t state = 0xf5026f5ae96319e9; - -static bool has_rdrand = false; -static bool has_rdseed = false; - -extern "C" int asm_test_rdseed(); - -static uint64_t rdtsc() -{ - uint64_t result1; - uint64_t result2; - asm volatile("rdtsc" : "=a"(result1), "=d"(result2)); - return result2 << 32 | result1; -} - -static uint64_t rdseed() -{ - uint64_t result; - asm volatile("rdseed %0" : "=r"(result)); - return result; -} - -static uint64_t rdrand() -{ - uint64_t result; - asm volatile("rdrand %0" : "=r"(result)); - return result; -} - -void Mersenne::init() -{ - has_rdrand = CPU::has_feature(CPU::Features::RDRAND); - has_rdseed = asm_test_rdseed(); - - if (!has_rdrand && !has_rdseed) kwarnln("CPU does not support either RDRAND or RDSEED"); - - state ^= (0x45fe1024UL + __moon_version_major()) * (__moon_version_minor() ^ 200UL); - - state ^= 0xe0e4f5332ea75b; - - reseed(); - - state ^= Mersenne::get() * 0xffe3; - - state ^= rdtsc(); - - Mersenne::seed(state); -} - -void Mersenne::reseed() -{ - state ^= rdtsc(); - - if (has_rdrand) { state ^= rdrand(); } - - if (has_rdseed) { state ^= rdseed(); } - - state ^= rdtsc(); - - state ^= IO::inb(0x40); - - state ^= rdtsc(); - - Mersenne::seed(state); -} \ No newline at end of file diff --git a/kernel/src/rand/Mersenne.cpp b/kernel/src/rand/Mersenne.cpp deleted file mode 100644 index 9f30d469..00000000 --- a/kernel/src/rand/Mersenne.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#define MODULE "rand" - -#include "rand/Mersenne.h" -#include "std/ensure.h" -#include - -typedef uint64_t word_t; - -static const int STATE_SIZE = 312; -static const int MIDDLE = 156; -static const int INIT_SHIFT = 62; -static const uint64_t TWIST_MASK = 0xb5026f5aa96619e9; -static const uint64_t INIT_FACT = 6364136223846793005; -static const int SHIFT1 = 29; -static const uint64_t MASK1 = 0x5555555555555555; -static const int SHIFT2 = 17; -static const uint64_t MASK2 = 0x71d67fffeda60000; -static const int SHIFT3 = 37; -static const uint64_t MASK3 = 0xfff7eee000000000; -static const int SHIFT4 = 43; - -static const word_t LOWER_MASK = 0x7fffffff; -static const word_t UPPER_MASK = (~(word_t)LOWER_MASK); - -static word_t state[STATE_SIZE]; -static size_t index = STATE_SIZE + 1; - -void Mersenne::seed(uint64_t s) -{ - index = STATE_SIZE; - state[0] = s; - for (size_t i = 1; i < STATE_SIZE; i++) state[i] = (INIT_FACT * (state[i - 1] ^ (state[i - 1] >> INIT_SHIFT))) + i; -} - -static void twist() -{ - for (size_t i = 0; i < STATE_SIZE; i++) - { - word_t x = (state[i] & UPPER_MASK) | (state[(i + 1) % STATE_SIZE] & LOWER_MASK); - x = (x >> 1) ^ (x & 1 ? TWIST_MASK : 0); - state[i] = state[(i + MIDDLE) % STATE_SIZE] ^ x; - } - index = 0; -} - -uint64_t Mersenne::get() -{ - if (index >= STATE_SIZE) - { - ensure(index == STATE_SIZE && "Mersenne generator was never seeded"); - twist(); - } - - word_t y = state[index]; - y ^= (y >> SHIFT1) & MASK1; - y ^= (y << SHIFT2) & MASK2; - y ^= (y << SHIFT3) & MASK3; - y ^= y >> SHIFT4; - - index++; - return y; -} \ No newline at end of file diff --git a/kernel/src/render/Color.cpp b/kernel/src/render/Color.cpp deleted file mode 100644 index 505b8516..00000000 --- a/kernel/src/render/Color.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "render/Color.h" - -Color Color::White = {0xFF, 0xFF, 0xFF, 0xFF}; -Color Color::Black = {0x00, 0x00, 0x00, 0xFF}; -Color Color::Red = {0x00, 0x00, 0xFF, 0xFF}; -Color Color::Green = {0x00, 0xFF, 0x00, 0xFF}; -Color Color::Blue = {0xFF, 0x00, 0x00, 0xFF}; -Color Color::Yellow = {0x00, 0xFF, 0xFF, 0xFF}; -Color Color::Cyan = {0xFF, 0xFF, 0x00, 0xFF}; -Color Color::Magenta = {0xFF, 0x00, 0xFF, 0xFF}; -Color Color::Gray = {0x80, 0x80, 0x80, 0xFF}; - -#pragma GCC push_options -#pragma GCC diagnostic ignored "-Wstrict-aliasing" - -Color Color::from_integer(uint32_t source) -{ - return reinterpret_cast(source); -} - -#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/render/Framebuffer.cpp b/kernel/src/render/Framebuffer.cpp deleted file mode 100644 index bdde5a73..00000000 --- a/kernel/src/render/Framebuffer.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#define MODULE "fb" - -#include "render/Framebuffer.h" -#include "assert.h" -#include "bootboot.h" -#include "panic/Panic.h" -#include "string.h" - -Framebuffer framebuffer0; - -void Framebuffer::init(void* fb_address, int fb_type, int fb_scanline, int fb_width, int fb_height) -{ - m_fb_address = fb_address; - m_fb_height = fb_height; - m_fb_width = fb_width; - m_fb_scanline = fb_scanline; - m_fb_type = fb_type; - if (m_fb_type != FB_ARGB) - { - memset(m_fb_address, 0xe4, 500); // make it visible - panic("unsupported framebuffer"); - } -} - -void Framebuffer::set_pixel(uint32_t x, uint32_t y, Color color) -{ - *(uint32_t*)((char*)m_fb_address + m_fb_scanline * y + x * 4) = *(uint32_t*)&color; -} - -Color Framebuffer::get_pixel(uint32_t x, uint32_t y) -{ - return *(Color*)((char*)m_fb_address + m_fb_scanline * y + x * 4); -} - -void Framebuffer::clear(Color color) -{ - paint_rect(0, 0, m_fb_width, m_fb_height, color); -} - -void Framebuffer::paint_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, Color color) -{ - for (uint32_t i = y; i < (y + h); i++) - { - uint64_t addr = (uint64_t)((char*)m_fb_address + (m_fb_scanline * i) + (x * 4)); - for (uint64_t addr_current = addr; addr_current < (addr + w * 4); addr_current += 4) - { - *(uint32_t*)addr_current = *(uint32_t*)&color; - } - } -} - -void Framebuffer::paint_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, Color* colors) -{ - uint32_t j; - for (uint32_t l = j = 0; l < h; l++) - { - for (uint32_t i = 0; i < w; i++, j++) { set_pixel(x + i, y + l, colors[j]); } - } -} diff --git a/kernel/src/render/TextRenderer.cpp b/kernel/src/render/TextRenderer.cpp deleted file mode 100644 index d8e2ad7f..00000000 --- a/kernel/src/render/TextRenderer.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#define MODULE "text" - -#include "render/TextRenderer.h" -#include "bootboot.h" -#include "font.h" -#include "fs/InitRD.h" -#include "io/Serial.h" -#include "log/Log.h" -#include "render/Framebuffer.h" -#include "std/stdio.h" -#include "std/string.h" - -extern BOOTBOOT bootboot; - -static Color bgColor = Color::Black; -static Color fgColor = Color::White; -static uint32_t xpos = 0; -static uint32_t ypos = 0; - -#define FONT_HEIGHT 16 -#define FONT_WIDTH 8 - -void TextRenderer::reset() -{ - xpos = 0; - ypos = 0; -} - -#pragma GCC push_options -#pragma GCC optimize("O0") - -static void putchar_at_offset( - char c, uint32_t cx, uint32_t cy, [[maybe_unused]] Color& fg, - [[maybe_unused]] Color& bg) // FIXME: Rewrite this function to actually work with foreground and background colors. -{ - uint8_t* glyph = &font[c * 16]; - for (uint32_t y = 0; y < FONT_HEIGHT; y++) - { - for (uint32_t x = 0; x < FONT_WIDTH; x++) - { - volatile uint8_t mask = *glyph; - if ((mask & (0b10000000 >> x)) > 0) { framebuffer0.set_pixel(cx + x, cy + y, Color::White); } - else { framebuffer0.set_pixel(cx + x, cy + y, Color::Black); } - } - glyph++; - } -} - -static bool g_escape_sequence = false; - -#pragma GCC pop_options - -void TextRenderer::putchar(char chr) -{ - if (g_escape_sequence) - { - g_escape_sequence = false; - switch (chr) - { - case '@': - reset(); - framebuffer0.clear(Color::Black); - break; - default: break; - } - } - else - { - switch (chr) - { - case '\n': { - ypos += FONT_HEIGHT; - if ((ypos + FONT_HEIGHT) >= bootboot.fb_height) - { - memcpy((void*)bootboot.fb_ptr, (char*)bootboot.fb_ptr + (bootboot.fb_scanline * FONT_HEIGHT), - bootboot.fb_size - (bootboot.fb_scanline * FONT_HEIGHT)); - ypos -= FONT_HEIGHT; - framebuffer0.paint_rect(0, ypos, bootboot.fb_width, FONT_HEIGHT, Color::Black); - } - xpos = 0; - break; - } - case '\r': xpos = 0; break; - case '\b': - if (xpos != 0) - { - xpos -= FONT_WIDTH; - framebuffer0.paint_rect(xpos, ypos, FONT_WIDTH, FONT_HEIGHT, Color::Black); - } - break; - case '\033': g_escape_sequence = true; break; - default: { - putchar_at_offset(chr, xpos, ypos, fgColor, bgColor); - xpos += FONT_WIDTH; - if ((xpos + FONT_WIDTH) > bootboot.fb_width) - { - xpos = 0; - ypos += FONT_HEIGHT; - if ((ypos + FONT_HEIGHT) >= bootboot.fb_height) - { - memcpy((void*)bootboot.fb_ptr, (char*)bootboot.fb_ptr + (bootboot.fb_scanline * FONT_HEIGHT), - bootboot.fb_size - (bootboot.fb_scanline * FONT_HEIGHT)); - ypos -= FONT_HEIGHT; - framebuffer0.paint_rect(0, ypos, bootboot.fb_width, FONT_HEIGHT, Color::Black); - } - } - break; - } - } - } -} - -void TextRenderer::write(const char* str, size_t size) -{ - for (size_t i = 0; i < size; i++) { putchar(str[i]); } -} \ No newline at end of file diff --git a/kernel/src/std/libgen.cpp b/kernel/src/std/libgen.cpp deleted file mode 100644 index b0a46a98..00000000 --- a/kernel/src/std/libgen.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "std/libgen.h" -#include "std/stdlib.h" -#include "std/string.h" - -static char dot[] = "."; - -char* basename(char* path) -{ - // If path is NULL, or the string's length is 0, return . - if (!path) return dot; - size_t len = strlen(path); - if (!len) return dot; - - // Strip trailing slashes. - char* it = path + len - 1; - while (*it == '/' && it != path) { it--; } - *(it + 1) = 0; - if (it == path) return path; - - // Return path from the first character if there are no more slashes, or from the first character after the last - // slash. - char* beg = strrchr(path, '/'); - if (!beg) return path; - return beg + 1; -} - -char* dirname(char* path) -{ - // If path is NULL, or the string's length is 0, return . - if (!path) return dot; - size_t len = strlen(path); - if (!len) return dot; - - // Strip trailing slashes. - char* it = path + len - 1; - while (*it == '/' && it != path) { it--; } - *(char*)(it + 1) = 0; - if (it == path) return path; - - // Search for the last slash. If there is none, return . - // Otherwise, we end the string there and return. - char* end = strrchr(path, '/'); - if (!end) return dot; - if (end != path) *end = 0; - else - *(end + 1) = 0; - return path; -} - -char* better_basename(const char* path) -{ - char* mut = strdup(path); // create a mutable copy of path - char* ptr = basename(mut); // get a pointer to the start of the base name - char* result = strdup(ptr); // create a copy of it, so the caller can free the returned pointer directly - kfree(mut); // free the original mutable copy - return result; -} - -char* better_dirname(const char* path) -{ - // same as above - char* mut = strdup(path); - char* ptr = dirname(mut); - char* result = strdup(ptr); - kfree(mut); - return result; -} \ No newline at end of file diff --git a/kernel/src/std/stdio.cpp b/kernel/src/std/stdio.cpp deleted file mode 100644 index d17a70cc..00000000 --- a/kernel/src/std/stdio.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include "std/stdio.h" -#include "io/Serial.h" -#include "render/TextRenderer.h" -#include "std/stdlib.h" -#include "std/string.h" - -typedef long int ssize_t; - -template -static int internal_printf(const char* format, PutString put_string_callback, ssize_t max, va_list ap) -{ - char buffer[1025]; // 1024 with null terminator - size_t format_size = strlen(format); - size_t format_index = 0; - size_t buffer_insert_index = 0; - ssize_t max_remaining = max; - size_t written = 0; - - auto flush_buffer = [&]() { - size_t buffer_length = buffer_insert_index; - written += buffer_length; - buffer_insert_index = 0; - if (max_remaining < 0) - { - buffer[buffer_length] = 0; - put_string_callback(buffer); - return; - } - if (max_remaining == 0) { return; } - if (buffer_length <= (size_t)max_remaining) - { - max_remaining -= buffer_length; - buffer[buffer_length] = 0; - put_string_callback(buffer); - } - else - { - buffer[max_remaining] = 0; - max_remaining = 0; - put_string_callback(buffer); - } - }; - - bool is_long = false; - bool is_unsigned_long = false; - - bool preserve_format = false; - - while (format_index < format_size) - { - char current_char = format[format_index]; - if (current_char == '%' || preserve_format) - { - if (!preserve_format && format_index + 1 == format_size) // end of format string - { - format_index++; - continue; - } - else - { - if (!preserve_format) format_index++; - preserve_format = false; - current_char = format[format_index]; - switch (current_char) - { - case 'c': { - buffer[buffer_insert_index++] = (char)va_arg(ap, int); - if (buffer_insert_index == 1024) flush_buffer(); - break; - } - case '%': { - buffer[buffer_insert_index++] = '%'; - if (buffer_insert_index == 1024) flush_buffer(); - break; - } - case 'z': { - is_unsigned_long = true; - preserve_format = true; - break; - } - case 'l': { - is_long = true; - preserve_format = true; - break; - } - case 'd': { - if (is_unsigned_long) - { - char result[25]; - ultoa(va_arg(ap, uint64_t), result, 10); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - is_unsigned_long = is_long = false; - } - else if (is_long) - { - char result[25]; - ltoa(va_arg(ap, int64_t), result, 10); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - is_unsigned_long = is_long = false; - } - else - { - char result[25]; - itoa(va_arg(ap, int32_t), result, 10); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - } - break; - } - case 'o': { - if (is_unsigned_long || is_long) - { - char result[25]; - ultoa(va_arg(ap, uint64_t), result, 8); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - is_unsigned_long = is_long = false; - } - else - { - char result[25]; - utoa(va_arg(ap, uint32_t), result, 8); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - } - break; - } - case 'u': { - if (is_unsigned_long || is_long) - { - char result[25]; - ultoa(va_arg(ap, uint64_t), result, 10); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - is_unsigned_long = is_long = false; - } - else - { - char result[25]; - utoa(va_arg(ap, uint32_t), result, 10); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - } - break; - } - case 'x': { - if (is_unsigned_long || is_long) - { - char result[25]; - ultoa(va_arg(ap, uint64_t), result, 16); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - is_unsigned_long = is_long = false; - } - else - { - char result[25]; - utoa(va_arg(ap, uint32_t), result, 16); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - } - break; - } - case 'p': { - char result[25]; - ultoa(va_arg(ap, uint64_t), result, 16); - if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, result, strlen(result)); - buffer_insert_index += strlen(result); - if (buffer_insert_index == 1024) flush_buffer(); - break; - } - case 's': { - const char* str = va_arg(ap, const char*); - while (strlen(str) > 1024) - { - flush_buffer(); - memcpy(buffer, str, 1024); - str += 1024; - buffer_insert_index = 1024; - } - if (buffer_insert_index + strlen(str) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, str, strlen(str)); - buffer_insert_index += strlen(str); - if (buffer_insert_index == 1024) flush_buffer(); - break; - } - default: { - buffer[buffer_insert_index++] = '%'; - if (buffer_insert_index == 1024) flush_buffer(); - buffer[buffer_insert_index++] = current_char; - if (buffer_insert_index == 1024) flush_buffer(); - break; - } - } - } - } - else - { - buffer[buffer_insert_index++] = current_char; - if (buffer_insert_index == 1024) flush_buffer(); - } - format_index++; - } - - if (buffer_insert_index > 0) flush_buffer(); - return (int)written; -} - -int printf(const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - int written = internal_printf( - fmt, [](const char* s) { Serial::print(s); }, -1, ap); - va_end(ap); - return written; -} - -int kprintf(const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - int written = vkprintf(fmt, ap); - va_end(ap); - return written; -} - -int sprintf(char* __s, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - if (__s) *__s = 0; - int written = internal_printf( - fmt, - [&](const char* s) { - if (__s) { strncat(__s, s, 1025); } - }, - -1, ap); - va_end(ap); - return written; -} - -int snprintf(char* __s, size_t max, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - if (__s && max) *__s = 0; - int written = internal_printf( - fmt, - [&](const char* s) { - if (__s) { strncat(__s, s, 1025); } - }, - max == 0 ? 0 : max - 1, ap); - va_end(ap); - return written; -} - -int vprintf(const char* fmt, va_list ap) -{ - return internal_printf( - fmt, [](const char* s) { Serial::print(s); }, -1, ap); -} - -int vkprintf(const char* fmt, va_list ap) -{ - return internal_printf( - fmt, [](const char* s) { TextRenderer::write(s, strlen(s)); }, -1, ap); -} - -int vsprintf(char* __s, const char* fmt, va_list ap) -{ - *__s = 0; - return internal_printf( - fmt, - [&](const char* s) { - if (__s) { strncat(__s, s, 1025); } - }, - -1, ap); -} - -int vsnprintf(char* __s, size_t max, const char* fmt, va_list ap) -{ - if (max) *__s = 0; - return internal_printf( - fmt, - [&](const char* s) { - if (__s) { strncat(__s, s, 1025); } - }, - max == 0 ? 0 : max - 1, ap); -} \ No newline at end of file diff --git a/kernel/src/std/stdlib.cpp b/kernel/src/std/stdlib.cpp deleted file mode 100644 index b7d42f42..00000000 --- a/kernel/src/std/stdlib.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "std/stdlib.h" -#include "thread/Scheduler.h" - -static void strrev(char* arr, int start, int end) -{ - char temp; - - if (start >= end) return; - - temp = *(arr + start); - *(arr + start) = *(arr + end); - *(arr + end) = temp; - - start++; - end--; - strrev(arr, start, end); -} - -char* itoa(int32_t number, char* arr, int base) -{ - int i = 0, r, negative = 0; - - if (number == 0) - { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - if (number < 0 && base == 10) - { - number *= -1; - negative = 1; - } - - while (number != 0) - { - r = number % base; - arr[i] = (char)((r > 9) ? (r - 10) + 'a' : r + '0'); - i++; - number /= base; - } - - if (negative) - { - arr[i] = '-'; - i++; - } - - strrev(arr, 0, i - 1); - - arr[i] = '\0'; - - return arr; -} - -char* ltoa(int64_t number, char* arr, int base) -{ - int i = 0, negative = 0; - int64_t r; - - if (number == 0) - { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - if (number < 0 && base == 10) - { - number *= -1; - negative = 1; - } - - while (number != 0) - { - r = number % base; - arr[i] = (char)((r > 9) ? (r - 10) + 'a' : r + '0'); - i++; - number /= base; - } - - if (negative) - { - arr[i] = '-'; - i++; - } - - strrev(arr, 0, i - 1); - - arr[i] = '\0'; - - return arr; -} - -char* utoa(uint32_t number, char* arr, int base) -{ - int i = 0; - uint32_t r; - - if (number == 0) - { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - while (number != 0) - { - r = number % base; - arr[i] = (char)((r > 9) ? (r - 10) + 'a' : r + '0'); - i++; - number /= base; - } - - strrev(arr, 0, i - 1); - - arr[i] = '\0'; - - return arr; -} - -char* ultoa(uint64_t number, char* arr, int base) -{ - int i = 0; - uint64_t r; - - if (number == 0) - { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - while (number != 0) - { - r = number % base; - arr[i] = (char)((r > 9) ? (r - 10) + 'a' : r + '0'); - i++; - number /= base; - } - - strrev(arr, 0, i - 1); - - arr[i] = '\0'; - - return arr; -} - -void sleep(uint64_t ms) -{ - Scheduler::sleep(ms); -} \ No newline at end of file diff --git a/kernel/src/std/string.cpp b/kernel/src/std/string.cpp deleted file mode 100644 index bcb3e62d..00000000 --- a/kernel/src/std/string.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "std/string.h" -#include "std/stdlib.h" - -size_t strlen(const char* __s) -{ - const char* i = __s; - for (; *i; ++i) - ; - return (i - __s); -} - -char* strcpy(char* dest, const char* src) -{ - memcpy(dest, src, strlen(src) + 1); - return dest; -} - -char* strncpy(char* dest, const char* src, size_t n) -{ - size_t i; - for (i = 0; i < n && src[i] != 0; i++) dest[i] = src[i]; - for (; i < n; i++) dest[i] = 0; - return dest; -} - -size_t strlcpy(char* dest, const char* src, size_t size) -{ - size_t len = strlen(src); - if (size == 0) return len; - if (len < (size - 1)) - { - memcpy(dest, src, len); - dest[len] = 0; - } - else - { - memcpy(dest, src, size - 1); - dest[size - 1] = 0; - } - return len; -} - -int strcmp(const char* a, const char* b) -{ - while (*a && (*a == *b)) - { - a++; - b++; - } - return *(const unsigned char*)a - *(const unsigned char*)b; -} - -int strncmp(const char* a, const char* b, size_t n) -{ - const char* base = a; - while (*a && (*a == *b) && (size_t)(a - base) < (n - 1)) - { - a++; - b++; - } - return *(const unsigned char*)a - *(const unsigned char*)b; -} - -char* strncat(char* dest, const char* src, size_t n) -{ - size_t dest_len = strlen(dest); - size_t i; - - for (i = 0; i < n && *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i); - - *(char*)(dest + dest_len + i) = '\0'; - - return dest; -} - -char* strcat(char* dest, const char* src) -{ - size_t dest_len = strlen(dest); - size_t i; - - for (i = 0; *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i); - - *(char*)(dest + dest_len + i) = '\0'; - - return dest; -} - -char* strstr(char* haystack, const char* needle) -{ - size_t needle_size = strlen(needle); - size_t haystack_size = strlen(haystack); - while (*haystack) - { - if (*haystack == *needle) - { - if (needle_size <= haystack_size) - { - if (!strncmp(haystack, needle, needle_size)) return haystack; - } - else { return NULL; } - } - haystack++; - haystack_size--; - } - return NULL; -} - -void* memcpy(void* dest, const void* src, size_t n) -{ - for (size_t i = 0; i < n; ++i) { *((char*)dest + i) = *((const char*)src + i); } - return dest; -} - -void* memset(void* buf, int c, size_t n) -{ - for (size_t i = 0; i < n; ++i) { *((char*)buf + i) = (char)c; } - return buf; -} - -int memcmp(const void* a, const void* b, size_t n) -{ - if (!n) return 0; - const unsigned char* ap = (const unsigned char*)a; - const unsigned char* bp = (const unsigned char*)b; - while (--n && *ap == *bp) - { - ap++; - bp++; - } - return *ap - *bp; -} - -void* memmove(void* dest, const void* src, size_t n) -{ - if (dest == src) return dest; - if (dest > src) - for (long i = n - 1; i >= 0; i++) { *((char*)dest + i) = *((const char*)src + i); } - else - for (long i = 0; i < (long)n; i++) { *((char*)dest + i) = *((const char*)src + i); } - return dest; -} - -char* strdup(const char* src) -{ - size_t length = strlen(src); - char* duplicated = (char*)kmalloc(length + 1); - memcpy(duplicated, src, length + 1); - return duplicated; -} - -char* strrchr(const char* str, int c) -{ - const char* s = str + strlen(str); - while (s != str && *s != (char)c) s--; - if (*s == (char)c) return const_cast(s); - return NULL; -} \ No newline at end of file diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp deleted file mode 100644 index 992bafa3..00000000 --- a/kernel/src/sys/Syscall.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "sys/Syscall.h" -#include "io/Serial.h" -#include "memory/VMM.h" -#include "std/errno.h" -#include "std/string.h" -#include "thread/Scheduler.h" - -void Syscall::entry(Context* context) -{ - asm volatile("cli"); - VMM::enter_syscall_context(); - switch (context->rax) - { - case SYS_exit: sys_exit(context, (int)context->rdi); break; - case SYS_yield: sys_yield(context); break; - case SYS_sleep: sys_sleep(context, context->rdi); break; - case SYS_write: sys_write(context, (int)context->rdi, context->rsi, (const char*)context->rdx); break; - case SYS_getprocid: sys_getprocid(context, (int)context->rdi); break; - case SYS_mmap: - sys_mmap(context, (void*)context->rdi, context->rsi, (int)context->rdx, (int)context->r10, (off_t)context->r8); - break; - case SYS_munmap: sys_munmap(context, (void*)context->rdi, context->rsi); break; - case SYS_open: sys_open(context, (const char*)context->rdi, (int)context->rsi, (mode_t)context->rdx); break; - case SYS_read: sys_read(context, (int)context->rdi, context->rsi, (char*)context->rdx); break; - case SYS_close: sys_close(context, (int)context->rdi); break; - case SYS_seek: sys_seek(context, (int)context->rdi, (long)context->rsi, (int)context->rdx); break; - case SYS_execv: sys_execv(context, (const char*)context->rdi, (char**)context->rsi); break; - case SYS_fcntl: sys_fcntl(context, (int)context->rdi, (int)context->rsi, context->rdx); break; - case SYS_mprotect: sys_mprotect(context, (void*)context->rdi, context->rsi, (int)context->rdx); break; - case SYS_clock_gettime: sys_clock_gettime(context, (int)context->rdi, (struct timespec*)context->rsi); break; - case SYS_mkdir: sys_mkdir(context, (const char*)context->rdi, (mode_t)context->rsi); break; - case SYS_fork: sys_fork(context); break; - case SYS_waitpid: sys_waitpid(context, (long)context->rdi, (int*)context->rsi, (int)context->rdx); break; - case SYS_access: sys_access(context, (const char*)context->rdi, (int)context->rsi); break; - case SYS_fstat: sys_fstat(context, (int)context->rdi, (struct stat*)context->rsi); break; - case SYS_stat: sys_stat(context, (const char*)context->rdi, (struct stat*)context->rsi); break; - case SYS_pstat: sys_pstat(context, (long)context->rdi, (struct pstat*)context->rsi); break; - case SYS_getdents: - sys_getdents(context, (int)context->rdi, (struct luna_dirent*)context->rsi, (size_t)context->rdx); - break; - case SYS_dup2: sys_dup2(context, (int)context->rdi, (int)context->rsi); break; - case SYS_setuid: sys_setuid(context, (uid_t)context->rdi); break; - case SYS_setgid: sys_setgid(context, (gid_t)context->rdi); break; - case SYS_umask: sys_umask(context, (mode_t)context->rdi); break; - case SYS_ioctl: sys_ioctl(context, (int)context->rdi, (int)context->rsi, (uintptr_t)context->rdx); break; - case SYS_seteuid: sys_seteuid(context, (uid_t)context->rdi); break; - case SYS_setegid: sys_setegid(context, (gid_t)context->rdi); break; - default: context->rax = -ENOSYS; break; - } - VMM::exit_syscall_context(); -} diff --git a/kernel/src/sys/UserMemory.cpp b/kernel/src/sys/UserMemory.cpp deleted file mode 100644 index fc71fb40..00000000 --- a/kernel/src/sys/UserMemory.cpp +++ /dev/null @@ -1,224 +0,0 @@ -#include "sys/UserMemory.h" -#include "memory/Memory.h" -#include "memory/MemoryManager.h" -#include "std/stdlib.h" -#include "std/string.h" -#include "utils/Addresses.h" - -struct dynamic_string -{ - char* buf; - long capacity; - long size; -}; - -bool dynamic_expand(dynamic_string* str, long new_capacity) -{ - char* buffer = (char*)krealloc(str->buf, new_capacity); - if (!buffer) { return false; } - str->buf = buffer; - str->capacity = new_capacity; - return true; -} - -bool dynamic_push(dynamic_string* str, char c) -{ - if (str->size == str->capacity) - { - if (!dynamic_expand(str, str->capacity + 16)) return false; - } - str->buf[str->size] = c; - str->size++; - return true; -} - -bool dynamic_init(dynamic_string* str) -{ - str->buf = (char*)kmalloc(10); - if (!str->buf) return false; - str->capacity = 10; - str->size = 0; - return true; -} - -bool validate_user_readable_page(uintptr_t address) -{ - if (Memory::is_kernel_address(address)) return false; - auto rc = VMM::get_flags(address); - if (rc == (uint64_t)-1) return false; - if (rc & MAP_USER) return true; - return false; -} - -bool validate_user_writable_page(uintptr_t address) -{ - if (Memory::is_kernel_address(address)) return false; - auto rc = VMM::get_flags(address); - if (rc == (uint64_t)-1) return false; - if (rc & (MAP_USER | MAP_READ_WRITE)) return true; - return false; -} - -Result strdup_from_user(const char* user_string) -{ - uintptr_t user_ptr = (uintptr_t)user_string; - auto aligned = round_down_to_nearest_page(user_ptr); - char* ptr = nullptr; - uintptr_t index = 0; - if (aligned != user_ptr) // Otherwise, we already do this check below. - { - if (!validate_user_readable_page(aligned)) return nullptr; - auto result = MemoryManager::get_mapping((void*)VMM::get_physical(aligned), 0); - if (result.has_error()) return result.release_error(); - ptr = (char*)result.release_value(); - index = user_ptr - aligned; - } - dynamic_string str; - if (!dynamic_init(&str)) - { - if (ptr) MemoryManager::release_mapping(ptr); - return {ENOMEM}; - } - while (true) // FIXME: set a limit for this and fail with ENAMETOOLONG otherwise. - { - if (user_ptr % PAGE_SIZE == 0) - { - index = 0; - if (ptr) MemoryManager::release_mapping(ptr); - if (!validate_user_readable_page(user_ptr)) - { - kfree(str.buf); - return {EFAULT}; - } - auto result = MemoryManager::get_mapping((void*)VMM::get_physical(user_ptr), 0); - if (result.has_error()) return result.release_error(); - ptr = (char*)result.release_value(); - } - char c = ptr[index]; - if (!dynamic_push(&str, c)) - { - MemoryManager::release_mapping(ptr); - kfree(str.buf); - return {ENOMEM}; - } - if (!c) // We reached the null terminator!! - { - MemoryManager::release_mapping(ptr); - return str.buf; - } - user_ptr++; - index++; - } -} - -bool validate_user_read(uintptr_t address, size_t size) -{ - auto aligned = round_down_to_nearest_page(address); - if (aligned != address) // Otherwise, we already do this check below. - { - if (!validate_user_readable_page(aligned)) return false; - } - while (size--) - { - if (address % PAGE_SIZE == 0) - { - if (!validate_user_readable_page(address)) return false; - } - address++; - } - return true; -} - -bool validate_user_write(uintptr_t address, size_t size) -{ - auto aligned = round_down_to_nearest_page(address); - if (aligned != address) // Otherwise, we already do this check below. - { - if (!validate_user_writable_page(aligned)) return false; - } - while (size--) - { - if (address % PAGE_SIZE == 0) - { - if (!validate_user_writable_page(address)) return false; - } - address++; - } - return true; -} - -bool do_copy_from_user(const char* uptr, char* ptr, size_t size) -{ - uintptr_t user_ptr = (uintptr_t)uptr; - auto aligned = round_down_to_nearest_page(user_ptr); - char* mapping = nullptr; - uintptr_t index = 0; - if (aligned != user_ptr) // Otherwise, we already do this check below. - { - if (!validate_user_readable_page(aligned)) return false; - auto result = MemoryManager::get_mapping((void*)VMM::get_physical(aligned), 0); - if (result.has_error()) return false; // FIXME: Propagate errors. - mapping = (char*)result.release_value(); - index = user_ptr - aligned; - } - while (size--) - { - if (user_ptr % PAGE_SIZE == 0) - { - if (mapping) MemoryManager::release_mapping(mapping); - index = 0; - if (!validate_user_readable_page(user_ptr)) return false; - auto result = MemoryManager::get_mapping((void*)VMM::get_physical(user_ptr), 0); - if (result.has_error()) return false; // FIXME: Propagate errors. - mapping = (char*)result.release_value(); - } - *ptr = mapping[index]; - user_ptr++; - ptr++; - index++; - } - return true; -} - -bool do_copy_to_user(char* uptr, const char* ptr, size_t size) -{ - uintptr_t user_ptr = (uintptr_t)uptr; - auto aligned = round_down_to_nearest_page(user_ptr); - char* mapping = nullptr; - uintptr_t index = 0; - if (aligned != user_ptr) // Otherwise, we already do this check below. - { - if (!validate_user_writable_page(aligned)) return false; - auto result = MemoryManager::get_mapping((void*)VMM::get_physical(aligned)); - if (result.has_error()) return false; - mapping = (char*)result.release_value(); - index = user_ptr - aligned; - } - while (size--) - { - if (user_ptr % PAGE_SIZE == 0) - { - if (mapping) MemoryManager::release_mapping(mapping); - index = 0; - if (!validate_user_writable_page(user_ptr)) return false; - auto result = MemoryManager::get_mapping((void*)VMM::get_physical(user_ptr), 0); - if (result.has_error()) return false; - mapping = (char*)result.release_value(); - } - mapping[index] = *ptr; - user_ptr++; - ptr++; - index++; - } - return true; -} - -bool copy_from_user(const void* user_ptr, void* ptr, size_t size) -{ - return do_copy_from_user((const char*)user_ptr, (char*)ptr, size); -} - -bool copy_to_user(void* user_ptr, const void* ptr, size_t size) -{ - return do_copy_to_user((char*)user_ptr, (const char*)ptr, size); -} \ No newline at end of file diff --git a/kernel/src/sys/clock.cpp b/kernel/src/sys/clock.cpp deleted file mode 100644 index b4f7f1a8..00000000 --- a/kernel/src/sys/clock.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "bootboot.h" -#include "interrupts/Context.h" -#include "std/errno.h" -#include "sys/UserMemory.h" -#include "thread/PIT.h" -#include "thread/Scheduler.h" -#include "utils/Time.h" -#include - -static uint64_t unix_boot_time; - -#define CLOCK_REALTIME 0 -#define CLOCK_MONOTONIC 1 -#define CLOCK_PROCTIME 2 - -struct timeval -{ - time_t tv_sec; - suseconds_t tv_usec; -}; - -struct timespec -{ - time_t tv_sec; - long tv_nsec; -}; - -static void ms_to_timespec(long ms, struct timespec* tv) -{ - tv->tv_sec = ms / 1000; - tv->tv_nsec = (ms % 1000) * 1000000; -} - -void sys_clock_gettime(Context* context, int clock, struct timespec* tp) -{ - struct timespec ktp; - Task* current_task = Scheduler::current_task(); - switch (clock) - { - case CLOCK_REALTIME: { - ms_to_timespec(PIT::ms_since_boot, &ktp); - ktp.tv_sec += unix_boot_time; - break; - } - case CLOCK_MONOTONIC: { - ms_to_timespec(PIT::ms_since_boot, &ktp); - break; - } - case CLOCK_PROCTIME: { - ms_to_timespec(current_task->cpu_time, &ktp); - break; - } - default: context->rax = -EINVAL; return; - } - if (!copy_typed_to_user(tp, &ktp)) context->rax = -EFAULT; - else - context->rax = 0; - return; -} - -extern BOOTBOOT bootboot; - -void clock_init() -{ - unix_boot_time = unix_boottime(bootboot.datetime); -} - -uint64_t clock_now() -{ - return unix_boot_time + (PIT::ms_since_boot / 1000); -} - -uint64_t clock_boot() -{ - return unix_boot_time; -} \ No newline at end of file diff --git a/kernel/src/sys/dirent.cpp b/kernel/src/sys/dirent.cpp deleted file mode 100644 index 1e205974..00000000 --- a/kernel/src/sys/dirent.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#define MODULE "dir" - -#include "luna/dirent.h" -#include "fs/VFS.h" -#include "interrupts/Context.h" -#include "std/errno.h" -#include "std/string.h" -#include "sys/UserMemory.h" -#include "thread/Scheduler.h" - -void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t count) -{ - if (fd < 0 || fd > TASK_MAX_FDS) - { - context->rax = -EBADF; - return; - } - Task* current_task = Scheduler::current_task(); - if (!current_task->files[fd].is_open()) - { - context->rax = -EBADF; - return; - } - Descriptor& dir = current_task->files[fd]; - VFS::Node* node = dir.node(); - if (node->type != VFS_DIRECTORY) - { - context->rax = -ENOTDIR; - return; - } - size_t nread = 0; - while (count) - { - VFS::Node* entry = VFS::readdir(node, dir.offset()); - if (!entry) - { - context->rax = nread; - return; - } - - luna_dirent dirent; - - dirent.total = node->length; - dirent.offset = dir.offset(); - dirent.inode = entry->inode; - strlcpy(dirent.name, entry->name, sizeof(dirent.name)); - - if (!copy_typed_to_user(buf, &dirent)) - { - context->rax = -EFAULT; - return; - } - - dir.seek(dir.offset() + 1); - buf++; - nread++; - count--; - } - context->rax = nread; -} \ No newline at end of file diff --git a/kernel/src/sys/elf/ELFLoader.cpp b/kernel/src/sys/elf/ELFLoader.cpp deleted file mode 100644 index 2673b07e..00000000 --- a/kernel/src/sys/elf/ELFLoader.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#define MODULE "elf" - -#include "sys/elf/ELFLoader.h" -#include "fs/InitRD.h" -#include "fs/VFS.h" -#include "log/Log.h" -#include "memory/Memory.h" -#include "memory/MemoryManager.h" -#include "memory/VMM.h" -#include "misc/utils.h" -#include "std/ensure.h" -#include "std/errno.h" -#include "std/stdlib.h" -#include "std/string.h" -#include "sys/elf/ELF.h" -#include "utils/Addresses.h" - -static const char* format_permissions(uint32_t flags) -{ - static char perms[4]; - perms[0] = (flags & 4) > 0 ? 'r' : '-'; - perms[1] = (flags & 2) > 0 ? 'w' : '-'; - perms[2] = (flags & 1) > 0 ? 'x' : '-'; - perms[3] = 0; - return perms; -} - -static bool can_execute_segment(int flags) -{ - return flags & 1; -} - -static bool can_write_segment(int flags) -{ - return flags & 2; -} - -ELFImage* ELFLoader::load_elf_from_filesystem(const char* filename) -{ - VFS::Node* node = VFS::resolve_path(filename); - - if (!node) - { - kwarnln("Failed to open file %s for loading", filename); - return 0; - } - - if (node->type == VFS_DIRECTORY) - { - kwarnln("Failed to load %s: is a directory", filename); - return 0; - } - - ELFImage* result = load_elf_from_vfs(node); - return result; -} - -long ELFLoader::check_elf_image_from_filesystem(const char* filename) -{ - VFS::Node* node = VFS::resolve_path(filename); - - if (!node) - { - kwarnln("Failed to open file %s for checking", filename); - return -ENOENT; - } - - if (node->type == VFS_DIRECTORY) - { - kwarnln("Failed to check %s: is a directory", filename); - return -EISDIR; - } - - return check_elf_image(node); -} - -ELFImage* ELFLoader::load_elf_from_vfs(VFS::Node* node) -{ - Elf64_Ehdr elf_ehdr; - ensure(VFS::read(node, 0, sizeof(elf_ehdr), (char*)&elf_ehdr) >= 0); - ensure(strncmp((const char*)elf_ehdr.e_ident, ELFMAG, SELFMAG) == - 0); // If you haven't checked the ELF executable with check_elf_image() first, then an assertion fail is your - // fault =D - ensure(elf_ehdr.e_ident[EI_CLASS] == ELFCLASS64); - ensure(elf_ehdr.e_ident[EI_DATA] == ELFDATA2LSB); - ensure(elf_ehdr.e_type == ET_EXEC); - ensure(elf_ehdr.e_machine == EM_MACH); - ensure(elf_ehdr.e_phnum != 0); - ELFImage* image = (ELFImage*)kmalloc(sizeof(ELFImage) - sizeof(ELFSection)); - memset(image, 0, sizeof(ELFImage) - sizeof(ELFSection)); - image->entry = elf_ehdr.e_entry; - int i; - Elf64_Phdr phdr; - for (VFS::read(node, elf_ehdr.e_phoff, sizeof(Elf64_Phdr), (char*)&phdr), i = 0; i < elf_ehdr.e_phnum; - i++, VFS::read(node, elf_ehdr.e_phoff + (i * elf_ehdr.e_phentsize), sizeof(Elf64_Phdr), (char*)&phdr)) - { - if (phdr.p_type == PT_LOAD) - { - kdbgln("Loading loadable segment at address %lx, file size %ld, mem size %ld, permissions %s", phdr.p_vaddr, - phdr.p_filesz, phdr.p_memsz, format_permissions(phdr.p_flags)); - ensure(phdr.p_vaddr); - - ensure(!(can_write_segment(phdr.p_flags) && can_execute_segment(phdr.p_flags))); - - uint64_t pages = Utilities::get_blocks_from_size(PAGE_SIZE, (phdr.p_vaddr % PAGE_SIZE) + phdr.p_memsz); - void* buffer = (void*)((uint64_t)MemoryManager::get_pages_at(round_down_to_nearest_page(phdr.p_vaddr), - pages, MAP_READ_WRITE) - .release_value() // FIXME: We check for enough space before loading the ELF, - // although a race condition could happen. - + (phdr.p_vaddr % PAGE_SIZE)); - - if (VMM::is_using_kernel_address_space()) { VMM::switch_to_previous_user_address_space(); } - VMM::apply_address_space(); - - VFS::read(node, phdr.p_offset, phdr.p_filesz, (char*)buffer); - memset((void*)((uint64_t)buffer + phdr.p_filesz), 0, phdr.p_memsz - phdr.p_filesz); - - VMM::switch_back_to_kernel_address_space(); - VMM::apply_address_space(); - VMM::switch_to_previous_user_address_space(); - - int new_flags = MAP_USER | MAP_AS_OWNED_BY_TASK; - if (can_write_segment(phdr.p_flags)) new_flags |= MAP_READ_WRITE; - else if (can_execute_segment(phdr.p_flags)) - new_flags |= MAP_EXEC; - - MemoryManager::protect(buffer, pages, new_flags); - - image = (ELFImage*)krealloc(image, (sizeof(ELFImage) - sizeof(ELFSection)) + - (image->section_count + 1) * sizeof(ELFSection)); - ELFSection& section = image->sections[image->section_count]; - section.base = (uintptr_t)buffer; - section.pages = pages; - image->section_count++; - } - else { kdbgln("skipping non-loadable segment"); } - } - ensure(image->section_count); - return image; -} - -long ELFLoader::check_elf_image(VFS::Node* node) -{ - Elf64_Ehdr elf_ehdr; - if (VFS::read(node, 0, sizeof(elf_ehdr), (char*)&elf_ehdr) < (long)sizeof(elf_ehdr)) - { - kwarnln("Unable to read ELF header"); - return -ENOEXEC; - } - if (strncmp((const char*)elf_ehdr.e_ident, ELFMAG, SELFMAG) != 0) - { - kwarnln("ELF file has invalid magic, skipping"); - return -ENOEXEC; - } - if (elf_ehdr.e_ident[EI_CLASS] != ELFCLASS64) - { - kwarnln("ELF file is not ELF64, skipping"); - return -ENOEXEC; - } - if (elf_ehdr.e_ident[EI_DATA] != ELFDATA2LSB) - { - kwarnln("ELF file is not little-endian, skipping"); - return -ENOEXEC; - } - if (elf_ehdr.e_type != ET_EXEC) - { - kwarnln("not supported: ELF file is not an executable"); - return -ENOEXEC; - } - if (elf_ehdr.e_machine != EM_MACH) - { - kwarnln("Unsupported target machine"); - return -ENOEXEC; - } - if (elf_ehdr.e_phnum == 0) - { - kwarnln("ELF file has no PHDRS"); - return -ENOEXEC; - } - int i; - int loadable_sections = 0; - long memusage = 0; - Elf64_Phdr phdr; - for (VFS::read(node, elf_ehdr.e_phoff, sizeof(Elf64_Phdr), (char*)&phdr), i = 0; i < elf_ehdr.e_phnum; - i++, VFS::read(node, elf_ehdr.e_phoff + (i * elf_ehdr.e_phentsize), sizeof(Elf64_Phdr), (char*)&phdr)) - { - if (phdr.p_type == PT_LOAD) - { - if (!phdr.p_vaddr) - { - kerrorln("segment address is NULL, this is invalid :("); - return -ENOEXEC; - } - if (Memory::is_kernel_address(phdr.p_vaddr) || Memory::is_kernel_address(phdr.p_vaddr + phdr.p_memsz)) - { - kerrorln("trying to load ELF into kernel memory"); - return -ENOEXEC; - } - if (can_write_segment(phdr.p_flags) && can_execute_segment(phdr.p_flags)) - { - kwarnln("executable violates W^X"); - return -ENOEXEC; - } - loadable_sections++; - memusage += Utilities::get_blocks_from_size(PAGE_SIZE, phdr.p_memsz) * PAGE_SIZE; - } - } - if (!loadable_sections) - { - kwarnln("No loadable sections"); - return -ENOEXEC; - } - return memusage; -} - -void ELFLoader::release_elf_image(ELFImage* image) -{ - for (uint64_t i = 0; i < image->section_count; i++) - { - ELFSection& section = image->sections[i]; - kdbgln("Freeing up section %lx, was using %ld pages", section.base, section.pages); - MemoryManager::release_pages((void*)round_down_to_nearest_page(section.base), section.pages); - } - kfree(image); -} diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp deleted file mode 100644 index bcbd6572..00000000 --- a/kernel/src/sys/exec.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#define MODULE "exec" - -#include "interrupts/Interrupts.h" -#include "log/Log.h" -#include "memory/Memory.h" -#include "memory/MemoryManager.h" -#include "memory/PMM.h" -#include "memory/VMM.h" -#include "std/ensure.h" -#include "std/errno.h" -#include "std/stdlib.h" -#include "std/string.h" -#include "sys/Syscall.h" -#include "sys/UserMemory.h" -#include "sys/elf/ELFLoader.h" -#include "thread/Scheduler.h" - -void sys_fork(Context* context) -{ - kinfoln("fork(): attempting fork"); - - Task* parent = Scheduler::current_task(); - - Task* child = Scheduler::create_user_task(); - if (!child) - { - context->rax = -ENOMEM; - return; - } - - if (!child->allocator.inherit(parent->allocator)) - { - child->state = child->Exited; - child->exit_status = -127; // so the reaper reaps it on next reaping - context->rax = -ENOMEM; - return; - } - - child->save_context(context); - child->save_floating(); - - for (int i = 0; i < TASK_MAX_FDS; i++) { child->files[i] = parent->files[i]; } - - child->address_space = parent->address_space.clone(); - - child->ppid = parent->id; - - child->uid = parent->uid; - child->euid = parent->euid; - child->gid = parent->gid; - child->egid = parent->egid; - - child->umask = parent->umask; - - child->regs.rax = 0; - context->rax = child->id; - - strlcpy(child->name, parent->name, sizeof(child->name)); - - child->state = child->Running; - - kinfoln("fork(): forked parent %ld into child %ld", parent->id, child->id); - - return; -} - -void push_on_user_stack(uint64_t* rsp, char* value, - size_t size) // FIXME: Handle segments of stack that extend beyond one page. -{ - (*rsp) -= size; - char* kvalue = (char*)VMM::get_physical(*rsp); - ensure(kvalue != (char*)UINT64_MAX); - memcpy(kvalue, value, size); -} - -void sys_execv(Context* context, const char* pathname, char** argv) -{ - auto result = strdup_from_user(pathname); - if (result.has_error()) - { - context->rax = -result.error(); - return; - } - char* kpathname = result.release_value(); - - kinfoln("exec(): executing %s", kpathname); - - VFS::Node* program = VFS::resolve_path(kpathname); - if (!program) - { - kfree(kpathname); - context->rax = -ENOENT; - return; - } - - if (program->type == VFS_DIRECTORY) - { - kfree(kpathname); - context->rax = -EISDIR; - return; - } - - if (!VFS::can_execute(program, Scheduler::current_task()->euid, Scheduler::current_task()->egid)) - { - kfree(kpathname); - context->rax = -EACCES; - return; - } - - long memusage; - if ((memusage = ELFLoader::check_elf_image(program)) < 0) - { - kfree(kpathname); - context->rax = -ENOEXEC; - return; - } - - if ((uint64_t)memusage > PMM::get_free()) - { - kfree(kpathname); - context->rax = -ENOMEM; - return; - } - - uint64_t kargc = 0; - char** kargv = nullptr; - char* arg; - - auto free_kernel_argv_copy = [&]() { - for (uint64_t i = 0; i < kargc; i++) - { - if (kargv[i]) kfree(kargv[i]); - } - if (kargv) kfree(kargv); - }; - - // FIXME: This code is a bit messy. Should probably be refactored and moved into a separate function. - - do { - if (!copy_from_user(argv, &arg, sizeof(char*))) - { - free_kernel_argv_copy(); - context->rax = -EFAULT; - return; - } - kargv = (char**)krealloc(kargv, (kargc + 1) * sizeof(char*)); // we need a vector class for the kernel. - if (!kargv) - { - free_kernel_argv_copy(); - context->rax = -ENOMEM; - return; - } - if (arg) - { - auto rc = strdup_from_user(arg); - if (rc.has_error()) // FIXME: This could also be EFAULT. - { - free_kernel_argv_copy(); - context->rax = -rc.error(); - return; - } - kargv[kargc] = rc.release_value(); - } - else - { - kargv[kargc] = nullptr; - break; - } - kargc++; - argv++; - } while (arg != nullptr); - - kinfoln("Copied %lu arguments from user process", kargc); - - size_t stack_size = 0; - for (uint64_t i = 0; i <= kargc; i++) - { - stack_size += sizeof(char*); - if (kargv[i]) - { - stack_size += strlen(kargv[i]) + 1; // count the null byte - } - } - - if (stack_size > - ((TASK_PAGES_IN_STACK / 2) * - PAGE_SIZE)) // FIXME: Maybe we should allocate a larger stack in this case, but still set a larger upper limit. - { - free_kernel_argv_copy(); - context->rax = -E2BIG; - return; - } - - char** user_argv = (char**)kcalloc(kargc + 1, sizeof(char*)); - if (!user_argv) - { - free_kernel_argv_copy(); - context->rax = -ENOMEM; - return; - } - - Interrupts::disable(); - ensure(!Interrupts::are_enabled()); // This part is pretty sensitive. - - Task* task = Scheduler::current_task(); - ensure(task); - - // At this point, pretty much nothing can fail. (FIXME: Race conditions could happen) - - task->allocator.free(); - task->allocator - .init(); // If we had enough space for the old bitmap, we should have enough space for the new bitmap. - - task->address_space.clear(); - task->allocated_stack = (uint64_t)MemoryManager::get_pages_at(0x100000, TASK_PAGES_IN_STACK, - MAP_USER | MAP_READ_WRITE | MAP_AS_OWNED_BY_TASK) - .release_value(); // If we had enough space for the old stack, there should be - // enough space for the new stack. - - ELFImage* image = ELFLoader::load_elf_from_vfs(program); - ensure(image); // If check_elf_image succeeded, load_elf_from_vfs MUST succeed, unless something has gone terribly - // wrong. - - if (VFS::is_setuid(program)) task->euid = program->uid; - if (VFS::is_setgid(program)) task->egid = program->gid; - - strlcpy(task->name, kpathname, sizeof(task->name)); - - Scheduler::reset_task(task, image); - - for (int i = 0; i < TASK_MAX_FDS; i++) - { - Descriptor& file = task->files[i]; - if (file.close_on_exec()) { file.close(); } - } - - for (uint64_t i = 0; i <= kargc; i++) - { - if (kargv[i]) - { - push_on_user_stack(&task->regs.rsp, kargv[i], strlen(kargv[i]) + 1); - user_argv[i] = (char*)task->regs.rsp; - } - else - user_argv[i] = nullptr; - } - push_on_user_stack(&task->regs.rsp, (char*)user_argv, (kargc + 1) * sizeof(char*)); - task->regs.rdi = kargc; // argc - task->regs.rsi = task->regs.rsp; // argv - - task->regs.rsp &= (UINT64_MAX ^ 15); // align it - - free_kernel_argv_copy(); - - kfree(user_argv); - - kfree(kpathname); - - task->restore_context(context); - - return; -} \ No newline at end of file diff --git a/kernel/src/sys/id.cpp b/kernel/src/sys/id.cpp deleted file mode 100644 index 1d330359..00000000 --- a/kernel/src/sys/id.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "std/errno.h" -#include "thread/Scheduler.h" -#include - -#define ID_PID 0 -#define ID_PPID 1 -#define ID_UID 2 -#define ID_EUID 3 -#define ID_GID 4 -#define ID_EGID 5 - -void sys_getprocid(Context* context, int field) -{ - if (field == ID_PID) - { - context->rax = Scheduler::current_task()->id; - return; - } - else if (field == ID_PPID) - { - context->rax = Scheduler::current_task()->ppid; - return; - } - else if (field == ID_UID) - { - context->rax = Scheduler::current_task()->uid; - return; - } - else if (field == ID_EUID) - { - context->rax = Scheduler::current_task()->euid; - return; - } - else if (field == ID_GID) - { - context->rax = Scheduler::current_task()->gid; - return; - } - else if (field == ID_EGID) - { - context->rax = Scheduler::current_task()->egid; - return; - } - else - { - context->rax = -EINVAL; - return; - } -} - -void sys_setuid(Context* context, uid_t uid) -{ - Task* current_task = Scheduler::current_task(); - - if (!current_task->is_superuser()) - { - if (uid != current_task->uid && uid != current_task->euid) - { - context->rax = -EPERM; - return; - } - } - - current_task->uid = uid; - current_task->euid = uid; - - context->rax = 0; -} - -void sys_seteuid(Context* context, uid_t euid) -{ - Task* current_task = Scheduler::current_task(); - - if (!current_task->is_superuser()) - { - if (euid != current_task->uid) - { - context->rax = -EPERM; - return; - } - } - - current_task->euid = euid; - - context->rax = 0; -} - -void sys_setgid(Context* context, gid_t gid) -{ - Task* current_task = Scheduler::current_task(); - - if (!current_task->is_superuser()) - { - if (gid != current_task->gid && gid != current_task->egid) - { - context->rax = -EPERM; - return; - } - } - - current_task->gid = gid; - current_task->egid = gid; - - context->rax = 0; -} - -void sys_setegid(Context* context, gid_t egid) -{ - Task* current_task = Scheduler::current_task(); - - if (!current_task->is_superuser()) - { - if (egid != current_task->gid) - { - context->rax = -EPERM; - return; - } - } - - current_task->egid = egid; - - context->rax = 0; -} \ No newline at end of file diff --git a/kernel/src/sys/mem.cpp b/kernel/src/sys/mem.cpp deleted file mode 100644 index 99a6a0b0..00000000 --- a/kernel/src/sys/mem.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#define MODULE "mem" - -#include "interrupts/Context.h" -#include "log/Log.h" -#include "memory/Memory.h" -#include "memory/MemoryManager.h" -#include "memory/VMM.h" -#include "misc/utils.h" -#include "std/errno.h" -#include "thread/Scheduler.h" -#include - -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_NONE 0 -#define PROT_EXEC 4 - -#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno) - -static const char* format_prot(int prot) -{ - static char prot_string[4]; - prot_string[3] = 0; - prot_string[0] = ((prot & PROT_READ) > 0) ? 'r' : '-'; - prot_string[1] = ((prot & PROT_WRITE) > 0) ? 'w' : '-'; - prot_string[2] = ((prot & PROT_EXEC) > 0) ? 'x' : '-'; - return prot_string; -} - -static int mman_flags_from_prot(int prot) -{ - prot &= 0b111; - int flags = MAP_USER | MAP_AS_OWNED_BY_TASK; - if (prot == PROT_NONE) return MAP_AS_OWNED_BY_TASK; - if ((prot & PROT_WRITE) > 0) { flags |= MAP_READ_WRITE; } - if ((prot & PROT_EXEC) > 0) { flags |= MAP_EXEC; } - return flags; -} - -void sys_mmap(Context* context, void* address, size_t size, int prot, int fd, off_t offset) -{ - if (size < PAGE_SIZE) - { - kwarnln("mmap(): size too small"); - context->rax = MAP_FAIL(EINVAL); - return; - } - if (size % PAGE_SIZE) - { - kwarnln("mmap(): size not a multiple of PAGE_SIZE"); - context->rax = MAP_FAIL(EINVAL); - return; - } - int real_flags = mman_flags_from_prot(prot); - if (address) - { - kdbgln("mmap(): %ld pages at address %p, %s, fd %d", size / PAGE_SIZE, address, format_prot(prot), fd); - if (Memory::is_kernel_address((uintptr_t)address)) - { - kwarnln("munmap() failed: attempted to unmap a kernel page"); - context->rax = MAP_FAIL(ENOMEM); - return; - } - if (VMM::get_physical((uint64_t)address) != (uint64_t)-1) // Address is already used. - { - kwarnln("attempt to map an already mapped address"); - context->rax = MAP_FAIL(ENOMEM); - return; - } - uint64_t addr_offset = (uint64_t)address % PAGE_SIZE; - if (fd >= 0) - { - int err; - Descriptor* file = Scheduler::current_task()->open_descriptor_from_fd(fd, err); - if (!file) - { - context->rax = MAP_FAIL(err); - return; - } - context->rax = file->mmap((uint64_t)address - addr_offset, size, real_flags, offset); - return; - } - auto result = MemoryManager::get_pages_at((uint64_t)address - addr_offset, - Utilities::get_blocks_from_size(PAGE_SIZE, size), real_flags); - if (result.has_value()) - { - kdbgln("mmap() succeeded: %p", result.value()); - context->rax = (uint64_t)result.release_value(); - return; - } - else - { - kwarnln("mmap() failed: failed to allocate physical memory"); - context->rax = MAP_FAIL(result.error()); - return; - } - } - kdbgln("mmap(): %ld pages at any address, %s, fd %d", Utilities::get_blocks_from_size(PAGE_SIZE, size), - format_prot(prot), fd); - uint64_t ptr = - Scheduler::current_task()->allocator.request_virtual_pages(Utilities::get_blocks_from_size(PAGE_SIZE, size)); - if (!ptr) - { - kwarnln("mmap() failed: failed to allocate virtual address"); - context->rax = MAP_FAIL(ENOMEM); - return; - } - if (fd >= 0) - { - int err; - Descriptor* file = Scheduler::current_task()->open_descriptor_from_fd(fd, err); - if (!file) - { - context->rax = MAP_FAIL(err); - return; - } - context->rax = file->mmap(ptr, size, real_flags, offset); - return; - } - auto result = MemoryManager::get_pages_at(ptr, Utilities::get_blocks_from_size(PAGE_SIZE, size), real_flags); - if (result.has_value()) - { - kdbgln("mmap() succeeded: %p", result.value()); - context->rax = (uint64_t)result.release_value(); - return; - } - else - { - kwarnln("mmap() failed: failed to allocate physical memory"); - context->rax = MAP_FAIL(result.error()); - return; - } -} - -void sys_munmap(Context* context, void* address, size_t size) -{ - kdbgln("munmap(): attempting to unmap %p", address); - if (size < PAGE_SIZE) - { - kwarnln("munmap() failed: size is too small"); - context->rax = -EINVAL; - return; - } - if (size % PAGE_SIZE) - { - kwarnln("munmap() failed: size is not a multiple of PAGE_SIZE"); - context->rax = -EINVAL; - return; - } - if (!address) - { - kwarnln("munmap() failed: attempted to unmap page 0"); - context->rax = -EINVAL; - return; - } - if (Memory::is_kernel_address((uintptr_t)address)) - { - kwarnln("munmap() failed: attempted to unmap a kernel page"); - context->rax = -EINVAL; - return; - } - uint64_t flags = VMM::get_flags((uint64_t)address); - if (flags == (uint64_t)-1) - { - kwarnln("munmap() failed: attempted to unmap a non-existent page"); - context->rax = -EINVAL; - return; - } - uint64_t offset = (uint64_t)address % PAGE_SIZE; - Scheduler::current_task()->allocator.free_virtual_pages(((uint64_t)address - offset), - Utilities::get_blocks_from_size(PAGE_SIZE, size)); - if (flags & MAP_AS_OWNED_BY_TASK) - MemoryManager::release_pages((void*)((uint64_t)address - offset), - Utilities::get_blocks_from_size(PAGE_SIZE, size)); - else - MemoryManager::release_unaligned_mappings((void*)((uint64_t)address - offset), - Utilities::get_blocks_from_size(PAGE_SIZE, size)); - kdbgln("munmap() succeeded"); - context->rax = 0; - return; -} - -void sys_mprotect(Context* context, void* address, size_t size, int prot) -{ - kdbgln("mprotect(): attempting to protect %p with %s", address, format_prot(prot)); - - if (size < PAGE_SIZE) - { - kwarnln("mprotect() failed: size is too small"); - context->rax = -EINVAL; - return; - } - if (size % PAGE_SIZE) - { - kwarnln("mprotect() failed: size is not a multiple of PAGE_SIZE"); - context->rax = -EINVAL; - return; - } - if (!address) - { - kwarnln("mprotect() failed: attempted to protect page 0"); - context->rax = -EINVAL; - return; - } - if (Memory::is_kernel_address((uintptr_t)address)) - { - kwarnln("mprotect() failed: attempted to protect a kernel page"); - context->rax = -EINVAL; - return; - } - uint64_t flags = VMM::get_flags((uint64_t)address); - if (flags == (uint64_t)-1) - { - kwarnln("mprotect() failed: attempted to protect a non-existent page"); - context->rax = -EINVAL; - return; - } - - uint64_t offset = (uint64_t)address % PAGE_SIZE; - MemoryManager::protect((void*)((uint64_t)address - offset), Utilities::get_blocks_from_size(PAGE_SIZE, size), - flags & MAP_AS_OWNED_BY_TASK ? mman_flags_from_prot(prot) - : mman_flags_from_prot(prot) & ~(MAP_AS_OWNED_BY_TASK)); - kdbgln("mprotect() succeeded"); - context->rax = 0; - return; -} \ No newline at end of file diff --git a/kernel/src/sys/sched.cpp b/kernel/src/sys/sched.cpp deleted file mode 100644 index 6112d3c9..00000000 --- a/kernel/src/sys/sched.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "memory/VMM.h" -#include "std/errno.h" -#include "sys/UserMemory.h" -#include "thread/Scheduler.h" - -void sys_exit(Context* context, int status) -{ - Scheduler::task_exit(context, status); -} - -void sys_yield(Context* context) -{ - context->rax = 0; - Scheduler::task_yield(context); -} - -void sys_sleep(Context* context, uint64_t ms) -{ - context->rax = 0; - Task* task = Scheduler::current_task(); - task->task_sleep = ms; - task->state = task->Sleeping; - Scheduler::task_yield(context); -} \ No newline at end of file diff --git a/kernel/src/sys/stat.cpp b/kernel/src/sys/stat.cpp deleted file mode 100644 index 5d026633..00000000 --- a/kernel/src/sys/stat.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "fs/VFS.h" -#include "interrupts/Context.h" -#include "std/errno.h" -#include "std/stdlib.h" -#include "sys/UserMemory.h" -#include "thread/Scheduler.h" - -typedef unsigned short mode_t; -typedef unsigned long ino_t; - -struct stat // FIXME: This struct is quite stubbed out. -{ - ino_t st_ino; - mode_t st_mode; - off_t st_size; - int st_dev; // FIXME: Implement this. - int st_nlink; // FIXME: Implement this. - uid_t st_uid; - gid_t st_gid; - time_t st_atime; - time_t st_mtime; - time_t st_ctime; -}; - -void do_stat(Context* context, VFS::Node* node, struct stat* buf) -{ - struct stat stat; - stat.st_ino = node->inode; - stat.st_mode = node->mode | ((1 << (node->type)) * 010000); - stat.st_size = node->length; - stat.st_uid = node->uid; - stat.st_gid = node->gid; - stat.st_atime = node->atime; - stat.st_ctime = node->ctime; - stat.st_mtime = node->mtime; - stat.st_dev = 0; - stat.st_nlink = 0; - if (!copy_typed_to_user(buf, &stat)) context->rax = -EFAULT; - else - context->rax = 0; -} - -void sys_fstat(Context* context, int fd, struct stat* buf) -{ - Task* current_task = Scheduler::current_task(); - if (fd < 0 || fd >= TASK_MAX_FDS) - { - context->rax = -EBADF; - return; - } - Descriptor& file = current_task->files[fd]; - if (!file.is_open()) - { - context->rax = -EBADF; - return; - } - VFS::Node* node = file.node(); - return do_stat(context, node, buf); -} - -void sys_stat(Context* context, const char* path, struct stat* buf) -{ - auto result = strdup_from_user(path); - if (result.has_error()) - { - context->rax = -result.error(); - return; - } - char* kpath = result.release_value(); - VFS::Node* node = VFS::resolve_path(kpath); - kfree(kpath); - if (!node) - { - context->rax = -ENOENT; - return; - } - return do_stat(context, node, buf); -} \ No newline at end of file diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp deleted file mode 100644 index 2058bd00..00000000 --- a/kernel/src/sys/stdio.cpp +++ /dev/null @@ -1,411 +0,0 @@ -#define MODULE "stdio" - -#include "interrupts/Context.h" -#include "io/Serial.h" -#include "log/Log.h" -#include "memory/VMM.h" -#include "render/TextRenderer.h" -#include "std/errno.h" -#include "std/stdlib.h" -#include "sys/Syscall.h" -#include "sys/UserMemory.h" -#include "thread/Scheduler.h" -#include "thread/Task.h" -#include - -#define OPEN_READ 1 -#define OPEN_WRITE 2 -#define OPEN_NONBLOCK 4 -#define OPEN_CLOEXEC 8 -#define OPEN_DIRECTORY 16 -#define OPEN_TRUNCATED 32 -#define OPEN_CREATE 64 -#define OPEN_APPEND 128 -#define OPEN_EXCL 256 - -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 - -#define FCNTL_DUPFD 0 -#define FCNTL_ISTTY 1 -#define FCNTL_GETFD 2 -#define FCNTL_SETFD 3 - -#define FD_CLOEXEC 1 - -void sys_fcntl(Context* context, int fd, int command, uintptr_t arg) -{ - Task* current_task = Scheduler::current_task(); - int err; - Descriptor* file = current_task->open_descriptor_from_fd(fd, err); - if (!file) - { - context->rax = -err; - return; - } - if (command == FCNTL_DUPFD) - { - int minfd = (int)arg; - if (minfd < 0 || minfd >= TASK_MAX_FDS) - { - context->rax = -EINVAL; - return; - } - int dupfd = current_task->alloc_fd_greater_than_or_equal(minfd); - if (dupfd < 0) - { - context->rax = -EMFILE; - return; - } - current_task->files[dupfd] = *file; - context->rax = dupfd; - kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd); - return; - } - else if (command == FCNTL_ISTTY) - { - VFS::Node* node = file->node(); - if (node->tty) { context->rax = 1; } - else - context->rax = -ENOTTY; - return; - } - else if (command == FCNTL_GETFD) - { - int flags = 0; - if (file->close_on_exec()) context->rax |= FD_CLOEXEC; - context->rax = flags; - return; - } - else if (command == FCNTL_SETFD) - { - int flags = (int)arg; - if (flags & FD_CLOEXEC) file->set_close_on_exec(true); - else - file->set_close_on_exec(false); - context->rax = 0; - return; - } - else - { - context->rax = -EINVAL; - return; - } -} - -void sys_seek(Context* context, int fd, long offset, int whence) -{ - if (whence < SEEK_SET || whence > SEEK_END) - { - context->rax = -EINVAL; - return; - } - int err; - Descriptor* file = Scheduler::current_task()->open_descriptor_from_fd(fd, err); - if (!file) - { - context->rax = -err; - return; - } - long new_offset; - if (whence == SEEK_SET) new_offset = offset; - else if (whence == SEEK_CUR) - new_offset = offset + file->offset(); - else if (whence == SEEK_END) - new_offset = file->length() + offset; - else - __builtin_unreachable(); - if (new_offset < 0) - { - context->rax = -EINVAL; // FIXME: Is this the right error? - return; - } - if (new_offset == file->offset()) - { - context->rax = new_offset; - return; - } - int result = file->seek(new_offset); - if (result < 0) - { - context->rax = result; - return; - } - context->rax = new_offset; - return; -} - -void sys_write(Context* context, int fd, size_t size, const char* addr) -{ - if (!validate_user_read((uintptr_t)addr, size)) - { - context->rax = -EFAULT; - return; - } - int err; - Descriptor* file = Scheduler::current_task()->open_descriptor_from_fd(fd, err); - if (!file) - { - context->rax = -err; - return; - } - if (!file->can_write()) - { - context->rax = -EBADF; - return; - } - ssize_t result = file->user_write(size, addr); - context->rax = (size_t)result; - return; -} - -void sys_open(Context* context, const char* filename, int flags, mode_t mode) -{ - Task* current_task = Scheduler::current_task(); - int fd = current_task->alloc_fd(); - if (fd < 0) - { - context->rax = -EMFILE; - return; - } - - auto result = strdup_from_user(filename); - if (result.has_error()) - { - context->rax = -result.error(); - return; - } - char* kfilename = result.release_value(); - - VFS::Node* node = VFS::resolve_path(kfilename); - if (!node) - { - bool create = (flags & OPEN_CREATE) > 0; - if (create) - { - mode = mode & (~current_task->umask); - auto rc = VFS::create(kfilename, mode, current_task->euid, current_task->egid); - if (rc.has_error()) context->rax = -rc.error(); - else - { - kinfoln("Created file %s with mode %o, uid %d and gid %d", kfilename, mode, current_task->euid, - current_task->egid); - node = rc.release_value(); - goto do_open; - } - } - else { context->rax = -ENOENT; } - kfree(kfilename); - return; - } - else - { - bool excl = (flags & OPEN_EXCL) > 0; - - if (excl) - { - kfree(kfilename); - context->rax = -EEXIST; - return; - } - } - -do_open: - - bool can_read = (flags & OPEN_READ) > 0; - bool can_write = (flags & OPEN_WRITE) > 0; - if (!can_read && !can_write) - { - kfree(kfilename); - context->rax = -EINVAL; - return; - } - - if (can_read && !VFS::can_read(node, current_task->euid, current_task->egid)) - { - kwarnln("open failed because process with uid %d and gid %d couldn't open file %s with mode %o for reading", - current_task->euid, current_task->egid, kfilename, node->mode); - kfree(kfilename); - context->rax = -EACCES; - return; - } - - if (can_write && !VFS::can_write(node, current_task->euid, current_task->egid)) - { - kwarnln("open failed because process with uid %d and gid %d couldn't open file %s with mode %o for writing", - current_task->euid, current_task->egid, kfilename, node->mode); - kfree(kfilename); - context->rax = -EACCES; - return; - } - - bool able_to_block = (flags & OPEN_NONBLOCK) == 0; - bool close_on_exec = (flags & OPEN_CLOEXEC) > 0; - - bool only_directory = (flags & OPEN_DIRECTORY) > 0; - - bool truncate = (flags & OPEN_TRUNCATED) > 0; - if (truncate) - { - kfree(kfilename); - kerrorln("FIXME: open(O_TRUNC) is not implemented"); - context->rax = -ENOTSUP; - return; - } - - bool append = (flags & OPEN_APPEND) > 0; - - if (only_directory && node->type != VFS_DIRECTORY) - { - kfree(kfilename); - context->rax = -ENOTDIR; - return; - } - - kdbgln("open(): opening %s %s, allocated file descriptor %d", kfilename, - (can_read && can_write) ? "rw" - : can_read ? "r-" - : "-w", - fd); - - kfree(kfilename); - current_task->files[fd].open(node, can_read, can_write, able_to_block, close_on_exec); - - if (append && current_task->files[fd].node()->type != VFS_DEVICE) - { - current_task->files[fd].seek((long)current_task->files[fd].length()); - } - - context->rax = fd; - return; -} - -void sys_read(Context* context, int fd, size_t size, char* buffer) -{ - if (!validate_user_write((uintptr_t)buffer, size)) - { - context->rax = -EFAULT; - return; - } - int err; - Descriptor* file = Scheduler::current_task()->open_descriptor_from_fd(fd, err); - if (!file) - { - context->rax = -err; - return; - } - if (!file->can_read()) - { - context->rax = -EBADF; - return; - } - if (VFS::would_block(file->node())) - { - if (!file->able_to_block()) - { - context->rax = -EAGAIN; - return; - } - Task* current_task = Scheduler::current_task(); - current_task->state = current_task->Blocking; - current_task->block_reason = BlockReason::Reading; - current_task->blocking_read_info.fd = fd; - current_task->blocking_read_info.buf = buffer; - current_task->blocking_read_info.size = size; - return Scheduler::task_yield(context); - } - ssize_t result = file->user_read(size, buffer); - context->rax = (size_t)result; - return; -} - -void sys_close(Context* context, int fd) -{ - int err; - Descriptor* file = Scheduler::current_task()->open_descriptor_from_fd(fd, err); - if (!file) - { - context->rax = -err; - return; - } - kdbgln("close(): releasing file descriptor %d", fd); - file->close(); - context->rax = 0; - return; -} - -void sys_mkdir(Context* context, const char* filename, mode_t mode) -{ - auto result = strdup_from_user(filename); - if (result.has_error()) - { - context->rax = -result.error(); - return; - } - char* kfilename = result.release_value(); - - Task* current_task = Scheduler::current_task(); - - int rc = VFS::do_mkdir(kfilename, current_task->euid, current_task->egid, mode & (~current_task->umask)); - - kfree(kfilename); - - context->rax = rc; -} - -void sys_access(Context* context, const char* path, int) // FIXME: Use the amode argument. -{ - auto result = strdup_from_user(path); - if (result.has_error()) - { - context->rax = -result.error(); - return; - } - char* kpath = result.release_value(); - if (!VFS::exists(kpath)) { context->rax = -ENOENT; } - else - context->rax = 0; - kfree(kpath); -} - -void sys_dup2(Context* context, int fd, int fd2) -{ - int err; - Descriptor* file1 = Scheduler::current_task()->open_descriptor_from_fd(fd, err); - if (!file1) - { - context->rax = -err; - return; - } - Descriptor* file2 = Scheduler::current_task()->descriptor_from_fd(fd2, err); - if (!file2) - { - context->rax = -err; - return; - } - if (file2->is_open()) file2->close(); - *file2 = *file1; - kinfoln("dup2(): overwrote fd %d with fd %d", fd2, fd); - context->rax = fd2; -} - -void sys_umask(Context* context, mode_t cmask) -{ - Task* current_task = Scheduler::current_task(); - context->rax = current_task->umask; - current_task->umask = cmask; -} - -void sys_ioctl(Context* context, int fd, int cmd, uintptr_t arg) -{ - int err; - Descriptor* file = Scheduler::current_task()->open_descriptor_from_fd(fd, err); - if (!file) - { - context->rax = -err; - return; - } - kinfoln("ioctl(): fd %d, cmd %d, arg %lu", fd, cmd, arg); - context->rax = file->ioctl(cmd, arg); -} \ No newline at end of file diff --git a/kernel/src/thread/PIT.cpp b/kernel/src/thread/PIT.cpp deleted file mode 100644 index 074e5b5e..00000000 --- a/kernel/src/thread/PIT.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#define MODULE "pit" - -#include "thread/PIT.h" -#include "io/IO.h" -#include "log/Log.h" - -#define PIT_CHANNEL_0_PORT 0x40 - -volatile uint64_t PIT::ms_since_boot = 0; -static uint16_t divisor = 65535; - -void PIT::initialize(uint64_t frequency) -{ - divisor = (uint16_t)(base_frequency / frequency); - kdbgln("Configuring PIT to use divisor %d (will tick %lu times per second)", divisor, frequency); - if (divisor < 100) divisor = 100; - IO::outb(PIT_CHANNEL_0_PORT, (uint8_t)(divisor & 0xFF)); - IO::delay(); - IO::outb(PIT_CHANNEL_0_PORT, (uint8_t)((divisor & 0xFF00) >> 8)); -} - -uint64_t PIT::frequency() -{ - return base_frequency / divisor; -} - -void PIT::tick() -{ - ms_since_boot += 1000 / frequency(); -} \ No newline at end of file diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp deleted file mode 100644 index 9ff79db3..00000000 --- a/kernel/src/thread/Scheduler.cpp +++ /dev/null @@ -1,634 +0,0 @@ -#define MODULE "sched" - -#include "thread/Scheduler.h" -#include "interrupts/Interrupts.h" -#include "log/Log.h" -#include "memory/MemoryManager.h" -#include "memory/PMM.h" -#include "memory/VMM.h" -#include "misc/hang.h" -#include "misc/reboot.h" -#include "misc/utils.h" -#include "panic/Panic.h" -#include "std/ensure.h" -#include "std/errno.h" -#include "std/stdlib.h" -#include "std/string.h" -#include "sys/UserMemory.h" -#include "sys/elf/ELFLoader.h" -#include "thread/PIT.h" -#include "thread/Task.h" -#include "utils/Addresses.h" -#include "utils/Registers.h" - -static uint64_t task_num = 0; - -static Task idle_task; - -static uint64_t free_pid = 0; - -static Task* sched_current_task; -static Task* base_task; -static Task* end_task; - -extern "C" void idle_task_function(); - -static uint64_t frequency; - -template void sched_for_each_task(Callback callback) -{ - Task* task = base_task; - if (!task) return; - do { - if (!task) break; - bool will_continue = callback(task); - if (!will_continue) break; - task = task->next_task; - } while (task != base_task); -} - -template void sched_for_each_child(Task* task, Callback callback) -{ - sched_for_each_task([&](Task* child) { - if (child->ppid == task->id) { return callback(child); } - return true; - }); -} - -Task* Scheduler::find_by_pid(uint64_t pid) -{ - Task* result = nullptr; - sched_for_each_task([&](Task* task) { - if (task->id == pid) - { - result = task; - return false; - } - return true; - }); - return result; -} - -void Scheduler::append_task(Task* task) -{ - if (!base_task) - { - ensure(!end_task); - base_task = task; - end_task = base_task; - task->next_task = task; - task->prev_task = task; - } - else - { - end_task->next_task = task; - task->prev_task = end_task; - base_task->prev_task = task; - task->next_task = base_task; - end_task = task; - } -} - -void Scheduler::init() -{ - memset(&idle_task, 0, sizeof(Task)); - idle_task.id = free_pid++; - idle_task.regs.rip = (uint64_t)idle_task_function; - idle_task.regs.rsp = - get_top_of_stack((uint64_t)MemoryManager::get_page().release_value(), - 1); // If we OOM while creating the idle task, that's NOT good and we can panic. - idle_task.regs.cs = 0x08; - idle_task.regs.ss = 0x10; - idle_task.regs.rflags = (1 << 21) | (1 << 9); - idle_task.task_sleep = 1000; - idle_task.user_task = false; - idle_task.block_reason = BlockReason::None; - idle_task.state = idle_task.Idle; - - strlcpy(idle_task.name, "[cpu-idle]", sizeof(idle_task.name)); - - sched_current_task = &idle_task; - - frequency = 1000 / PIT::frequency(); -} - -void Scheduler::add_kernel_task(const char* taskname, void (*task)(void)) -{ - Task* new_task = new Task; - ensure(new_task); - new_task->user_task = false; - new_task->id = free_pid++; - new_task->ppid = 0; - new_task->uid = new_task->euid = new_task->gid = new_task->egid = 0; - new_task->regs.rip = (uint64_t)task; - new_task->allocated_stack = - (uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK).release_value(); // FIXME: Propagate errors. - new_task->regs.rsp = get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK); - new_task->regs.cs = 0x08; - new_task->regs.ss = 0x10; - new_task->regs.ds = 0x10; - new_task->regs.rflags = read_rflags() | 0x200; // enable interrupts - new_task->task_sleep = 0; - new_task->task_time = 0; - new_task->cpu_time = 0; - strlcpy(new_task->name, taskname, sizeof(new_task->name)); - append_task(new_task); - new_task->block_reason = BlockReason::None; - new_task->state = new_task->Running; - task_num++; - kinfoln("Adding kernel task: %s, starts at %lx, PID %ld, stack at %lx, total tasks: %ld", new_task->name, - new_task->regs.rip, new_task->id, new_task->regs.rsp, task_num); -} - -Task* Scheduler::create_user_task() -{ - Task* new_task = new Task; - if (!new_task) return nullptr; - memset(&new_task->regs, 0, sizeof(Context)); - new_task->user_task = true; - new_task->id = free_pid++; - new_task->ppid = 0; - new_task->task_sleep = 0; - new_task->task_time = 0; - new_task->cpu_time = 0; - new_task->block_reason = BlockReason::None; - append_task(new_task); - task_num++; - return new_task; -} - -long Scheduler::load_user_task(const char* filename) -{ - kinfoln("Loading user task: %s", filename); - Interrupts::push_and_disable(); - Task* new_task = new Task; - ensure(new_task); - memset(&new_task->regs, 0, sizeof(Context)); - new_task->id = free_pid++; - new_task->ppid = 0; - new_task->uid = new_task->euid = new_task->gid = new_task->egid = 0; - if (!new_task->allocator.init()) - { - delete new_task; - free_pid--; - Interrupts::pop(); - return -ENOMEM; - } - new_task->address_space = AddressSpace::create().release_value(); // FIXME: Propagate this error. - VMM::switch_to_user_address_space(new_task->address_space); - long result; - if ((result = ELFLoader::check_elf_image_from_filesystem(filename)) < 0) - { - delete new_task; - free_pid--; - kerrorln("Failed to load %s from initrd", filename); - Interrupts::pop(); - return result; - } - if ((uint64_t)result > PMM::get_free()) - { - delete new_task; - free_pid--; - kerrorln("Not enough memory for task %s", filename); - Interrupts::pop(); - return -ENOMEM; - } - ELFImage* image = ELFLoader::load_elf_from_filesystem(filename); - ensure(image); - new_task->user_task = true; - new_task->regs.rip = image->entry; - new_task->image = image; - new_task->umask = 0; - new_task->allocated_stack = (uint64_t)MemoryManager::get_pages_at(0x100000, TASK_PAGES_IN_STACK, - MAP_READ_WRITE | MAP_USER | MAP_AS_OWNED_BY_TASK) - .release_value(); // FIXME: Propagate errors. - if (!new_task->allocated_stack) - { - new_task->address_space.destroy(); - delete new_task; - free_pid--; - ELFLoader::release_elf_image(image); - VMM::switch_back_to_kernel_address_space(); - Interrupts::pop(); - return -ENOMEM; - } - new_task->regs.rsp = get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK); - new_task->regs.cs = 0x18 | 0x03; - new_task->regs.ss = 0x20 | 0x03; - new_task->regs.ds = 0x20 | 0x03; - new_task->regs.rflags = (1 << 21) | (1 << 9); // enable interrupts - new_task->task_sleep = 0; - new_task->task_time = 0; - new_task->cpu_time = 0; - strlcpy(new_task->name, filename, sizeof(new_task->name)); - append_task(new_task); - new_task->block_reason = BlockReason::None; - new_task->state = new_task->Running; - task_num++; - kinfoln("Adding user task: %s, loaded at %lx, PID %ld, stack at %lx, total tasks: %ld", new_task->name, - new_task->regs.rip, new_task->id, new_task->regs.rsp, task_num); - VMM::switch_back_to_kernel_address_space(); - Interrupts::pop(); - return (long)new_task->id; -} - -void Scheduler::reset_task(Task* task, ELFImage* new_image) -{ - memset(&task->regs, 0, sizeof(Context)); - task->state = task->Running; - task->regs.rip = new_image->entry; - task->image = new_image; - task->regs.rsp = get_top_of_stack(task->allocated_stack, TASK_PAGES_IN_STACK); - task->regs.cs = 0x18 | 0x03; - task->regs.ss = 0x20 | 0x03; - task->regs.ds = 0x20 | 0x03; - task->regs.rflags = (1 << 21) | (1 << 9); // enable interrupts - task->task_sleep = 0; - task->cpu_time = 0; - task->block_reason = BlockReason::None; - kinfoln("Resetting task: %s, loaded at %lx, PID %ld, stack at %lx, total tasks: %ld", task->name, task->regs.rip, - task->id, task->regs.rsp, task_num); -} - -void Scheduler::reap_task(Task* task) -{ - ensure(!Interrupts::is_in_handler()); - task_num--; - Task* exiting_task = task; - ensure(task->id != 0); // WHY IN THE WORLD WOULD WE BE REAPING THE IDLE TASK? - if (exiting_task->is_user_task()) - { - VMM::switch_back_to_kernel_address_space(); - VMM::apply_address_space(); - VMM::switch_to_user_address_space(exiting_task->address_space); - } - kinfoln("reaping task %s, PID %ld, exited with code %ld", exiting_task->name, exiting_task->id, - exiting_task->exit_status); - if (exiting_task->id == (free_pid - 1)) free_pid--; // If we are the last spawned thread, free our PID. - if (exiting_task->allocated_stack && !exiting_task->is_user_task()) - MemoryManager::release_pages((void*)exiting_task->allocated_stack, TASK_PAGES_IN_STACK); - if (exiting_task->image) kfree(exiting_task->image); - if (exiting_task->is_user_task()) - { - exiting_task->allocator.free(); - VMM::switch_back_to_kernel_address_space(); - VMM::apply_address_space(); - Interrupts::push_and_enable(); - exiting_task->address_space.destroy(); - Interrupts::pop(); - } - for (int i = 0; i < TASK_MAX_FDS; i++) { exiting_task->files[i].close(); } - delete exiting_task; -} - -void sched_common_exit(Context* context, int64_t status) -{ - if (sched_current_task->id == 1) sched_current_task->state = sched_current_task->Exited; - else - sched_current_task->state = sched_current_task->Dying; - sched_current_task->exit_status = status; - if (sched_current_task->id != 1) - { - sched_for_each_child(sched_current_task, [](Task* child) { - if (child->state != child->Exited) child->ppid = 1; - return true; - }); - } - else - { - kinfoln("PID 1 exited with code %ld", status); -#ifndef RUN_TEST_AS_INIT - reboot(); -#else - hang(); -#endif - } - Scheduler::task_yield(context); -} - -void Scheduler::task_exit(Context* context, int64_t status) -{ - ensure(Interrupts::is_in_handler()); - kdbgln("exit: task %ld finished running, used %ld ms of cpu time", sched_current_task->id, - sched_current_task->cpu_time); - sched_common_exit(context, status); -} - -void Scheduler::task_misbehave(Context* context, int64_t status) -{ - ensure(Interrupts::is_in_handler()); - kdbgln("exit: task %ld misbehaved, used %ld ms of cpu time", sched_current_task->id, sched_current_task->cpu_time); - sched_common_exit(context, status); -} - -void Scheduler::reap_tasks() -{ - Interrupts::disable(); - ensure(!Interrupts::is_in_handler()); - Task* reap_base = nullptr; - Task* reap_end = nullptr; - Task* task = base_task; - Task* task_reaping; - uint64_t iter_index = 0; - do { - if (task->state == task->Exited) - { - if (task == base_task && task == end_task) { panic("Last task exited"); } - else if (task == base_task) { base_task = task->next_task; } - else if (task == end_task) { end_task = task->prev_task; } - if (!reap_base) - { - reap_base = task; - reap_end = task; - task->prev_task->next_task = task->next_task; - task->next_task->prev_task = task->prev_task; - task->prev_task = nullptr; - task_reaping = task; - task = task->next_task; - task_reaping->next_task = nullptr; - } - else - { - reap_end->next_task = task; - task->prev_task->next_task = task->next_task; - task->next_task->prev_task = task->prev_task; - task->prev_task = nullptr; - reap_end = task; - task_reaping = task; - task = task->next_task; - task_reaping->next_task = nullptr; - } - } - else { task = task->next_task; } - iter_index++; - } while (iter_index < task_num); - task = reap_base; - while (task) - { - Task* reaped_task = task; - task = task->next_task; - reap_task(reaped_task); - } - Interrupts::enable(); -} - -static void sched_decrement_sleep_times() -{ - sched_for_each_task([](Task* task) { - if (task->task_sleep > 0) - { - task->task_sleep -= frequency; - if (task->task_sleep < 0) task->task_sleep = 0; - } - if (task->task_sleep == 0 && task->state == task->Sleeping) task->state = task->Running; - return true; - }); -} - -void Scheduler::task_tick(Context* context) -{ - ensure(Interrupts::is_in_handler()); - Interrupts::disable(); - sched_decrement_sleep_times(); - sched_current_task->task_time -= frequency; - sched_current_task->cpu_time += frequency; - if (sched_current_task->id == 0) return task_yield(context); - if (sched_current_task->task_time <= 0) - { - sched_current_task->task_time = 0; - task_yield(context); - } - Interrupts::enable(); -} - -void Scheduler::task_yield(Context* context) -{ - ensure(Interrupts::is_in_handler()); - Interrupts::disable(); - sched_current_task->save_context(context); - bool was_idle = false; - if (sched_current_task->state == sched_current_task->Idle) - { - sched_current_task = end_task; - was_idle = true; - } - Task* original_task = sched_current_task; - do { - sched_current_task = sched_current_task->next_task; - if (sched_current_task->state == sched_current_task->Blocking) - { - if (!sched_current_task->is_still_blocking()) sched_current_task->resume(); - } - if (sched_current_task->state == sched_current_task->Running) - { - if (sched_current_task->id != original_task->id || was_idle) - { - if (!was_idle && original_task->is_user_task() && !original_task->has_died()) - { - original_task->save_floating(); - } - if (sched_current_task->is_user_task()) - { - sched_current_task->switch_to_address_space(); - sched_current_task->restore_floating(); - } - else if (!was_idle && original_task->is_user_task() && !sched_current_task->is_user_task()) - { - VMM::switch_back_to_kernel_address_space(); - VMM::apply_address_space(); - } - } - sched_current_task->task_time = 20; - sched_current_task->restore_context(context); - return; - } - } while (sched_current_task != original_task); - if (!was_idle && original_task->is_user_task() && original_task->state != original_task->Exited) - { - original_task->save_floating(); - } - sched_current_task = &idle_task; - sched_current_task->task_time = frequency; - if (!was_idle) { sched_current_task->restore_context(context); } - return; -} - -void Scheduler::yield() -{ - asm volatile("int $0x42" : : "a"(1)); -} - -void Scheduler::exit(int status) -{ - asm volatile("int $0x42" : : "a"(0), "D"(status)); -} - -void Scheduler::sleep(unsigned long ms) -{ - asm volatile("int $0x42" : : "D"(ms), "a"(2)); -} - -Task* Scheduler::current_task() -{ - return sched_current_task; -} - -#define WNOHANG 1 - -void sys_waitpid(Context* context, long pid, int* wstatus, - int options) // FIXME: only allow waiting for child processes when specifying a PID. -{ - Task* child = nullptr; - if (pid == -1) - { - sched_for_each_child(sched_current_task, [&](Task* task) { - if (task->state == task->Dying) - { - child = task; - return false; - } - return true; - }); - if (!child) - { - if (options & WNOHANG) - { - context->rax = 0; // No child has exited, let's return 0. - return; - } - kdbgln("blocking wait on any child"); - sched_current_task->state = sched_current_task->Blocking; - sched_current_task->block_reason = BlockReason::Waiting; - sched_current_task->blocking_wait_info.pid = -1; - sched_current_task->blocking_wait_info.wstatus = wstatus; - return Scheduler::task_yield(context); - } - } - else - { - child = Scheduler::find_by_pid(pid); - if (!child) - { - context->rax = -ECHILD; - return; - } - } - if (child->ppid != sched_current_task->id) - { - // We are trying to call waitpid() on a task that isn't a child of ours. This is not allowed. - context->rax = -ECHILD; - return; - } - if (child->state != child->Dying) - { - if (options & WNOHANG) - { - context->rax = 0; // No child has exited, let's return 0. - return; - } - sched_current_task->state = sched_current_task->Blocking; - sched_current_task->block_reason = BlockReason::Waiting; - sched_current_task->blocking_wait_info.pid = pid; - sched_current_task->blocking_wait_info.wstatus = wstatus; - return Scheduler::task_yield(context); - } - child->state = child->Exited; - context->rax = (long)child->id; - if (wstatus) - { - int status = (int)(child->exit_status & 0xff); - if (!copy_to_user(wstatus, &status, sizeof(int))) context->rax = -EFAULT; - } -} - -bool Task::is_wait_still_blocking() -{ - Task* child = nullptr; - if (blocking_wait_info.pid == -1) - { - sched_for_each_child(sched_current_task, [&](Task* task) { - if (task->state == task->Dying) - { - child = task; - return false; - } - return true; - }); - if (!child) return true; - else - { - blocking_wait_info.pid = child->id; // We're committed to this child now. - return false; - } - } - else - { - child = Scheduler::find_by_pid(blocking_wait_info.pid); - ensure(child); // since sys_waitpid should have validated this child, and the only way for it to disappear from - // the process list is for someone to wait for it, this should be pretty safe. - if (child->state != child->Dying) return true; - else - return false; - } -} - -void Task::resume_wait() -{ - ensure(blocking_wait_info.pid != -1); // is_wait_still_blocking should have chosen a child for us if the user - // process told us to wait for any child. - Task* child = Scheduler::find_by_pid(blocking_wait_info.pid); - ensure(child); // This should also already have been validated. - - child->state = child->Exited; - regs.rax = (long)child->id; - - if (blocking_wait_info.wstatus) - { - int wstatus = (int)(child->exit_status & 0xff); - if (!copy_to_user(blocking_wait_info.wstatus, &wstatus, sizeof(int))) regs.rax = -EFAULT; - } -} - -struct pstat -{ - long pt_pid; - long pt_ppid; - char pt_name[128]; - int pt_state; - long pt_time; - uid_t pt_uid; - gid_t pt_gid; -}; - -void sys_pstat(Context* context, long pid, struct pstat* buf) -{ - Task* task; - if (pid == -1) task = Scheduler::find_by_pid(free_pid - 1); - else if (pid == 0) - task = &idle_task; - else - task = Scheduler::find_by_pid(pid); - if (!task) - { - context->rax = -ESRCH; - return; - } - if (task->state == task->Exited) // we're just waiting for the reaper to reap it - { - context->rax = -ESRCH; - return; - } - context->rax = task->id; - if (buf) - { - struct pstat stat; - stat.pt_pid = task->id; - stat.pt_ppid = task->ppid; - stat.pt_state = (int)task->state; - stat.pt_time = (long)task->cpu_time; - stat.pt_uid = task->uid; - stat.pt_gid = task->gid; - strlcpy(stat.pt_name, task->name, sizeof(stat.pt_name)); - if (!copy_to_user(buf, &stat, sizeof(struct pstat))) context->rax = -EFAULT; - } -} \ No newline at end of file diff --git a/kernel/src/thread/Spinlock.asm b/kernel/src/thread/Spinlock.asm deleted file mode 100644 index 2b2e7a43..00000000 --- a/kernel/src/thread/Spinlock.asm +++ /dev/null @@ -1,20 +0,0 @@ -global spinlock_lock_acquire -spinlock_lock_acquire: - lock bts qword [rdi], 0 - jc .spin - ret -.spin: - pause - test qword [rdi], 1 - jnz .spin - jmp spinlock_lock_acquire - -global spinlock_lock_release -spinlock_lock_release: - mov qword [rdi], 0 - ret - -global spinlock_lock_is_locked -spinlock_lock_is_locked: - mov rax, [rdi] - ret \ No newline at end of file diff --git a/kernel/src/thread/Spinlock.cpp b/kernel/src/thread/Spinlock.cpp deleted file mode 100644 index 2db971c2..00000000 --- a/kernel/src/thread/Spinlock.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "thread/Spinlock.h" - -extern "C" void spinlock_lock_acquire(volatile uint64_t* lock); -extern "C" void spinlock_lock_release(volatile uint64_t* lock); -extern "C" int spinlock_lock_is_locked(volatile uint64_t* lock); - -void Spinlock::acquire() -{ - spinlock_lock_acquire(&m_lock); -} - -void Spinlock::release() -{ - spinlock_lock_release(&m_lock); -} - -bool Spinlock::locked() -{ - return spinlock_lock_is_locked(&m_lock); -} - -void lock(Spinlock& lock, void (*action)(void)) -{ - lock.acquire(); - action(); - lock.release(); -} \ No newline at end of file diff --git a/kernel/src/thread/Task.cpp b/kernel/src/thread/Task.cpp deleted file mode 100644 index 95a450a1..00000000 --- a/kernel/src/thread/Task.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#define MODULE "sched" - -#include "thread/Task.h" -#include "log/Log.h" -#include "memory/VMM.h" -#include "std/ensure.h" -#include "std/errno.h" -#include "std/string.h" - -void Task::restore_context(Context* context) -{ - memcpy(context, ®s, sizeof(Context)); -} - -void Task::save_context(Context* context) -{ - memcpy(®s, context, sizeof(Context)); -} - -void Task::save_floating() -{ - floating_saved = true; - asm volatile("fxsave (%0)" : : "r"((char*)floating_region)); -} - -void Task::restore_floating() -{ - if (!floating_saved) return; - asm volatile("fxrstor (%0)" : : "r"((char*)floating_region)); -} - -bool Task::is_user_task() -{ - return user_task; -} - -int Task::alloc_fd() -{ - int fd; - for (fd = 0; fd < TASK_MAX_FDS; fd++) - { - if (!files[fd].is_open()) break; - } - - if (fd == TASK_MAX_FDS) { return -1; } - - return fd; -} - -int Task::alloc_fd_greater_than_or_equal(int base_fd) -{ - int fd; - if (base_fd >= TASK_MAX_FDS) return -1; - for (fd = base_fd; fd < TASK_MAX_FDS; fd++) - { - if (!files[fd].is_open()) break; - } - - if (fd == TASK_MAX_FDS) { return -1; } - - return fd; -} - -void Task::switch_to_address_space() -{ - VMM::switch_to_user_address_space(address_space); - VMM::apply_address_space(); -} - -bool Task::has_died() -{ - return state == Exited; -} - -void Task::resume_read() -{ - regs.rax = files[blocking_read_info.fd].user_read(blocking_read_info.size, blocking_read_info.buf); -} - -bool Task::is_read_still_blocking() -{ - return VFS::would_block(files[blocking_read_info.fd].node()); -} - -void Task::resume() -{ - VMM::switch_back_to_kernel_address_space(); - VMM::apply_address_space(); - VMM::switch_to_user_address_space(address_space); - switch (block_reason) - { - case BlockReason::None: return; - case BlockReason::Reading: resume_read(); break; - case BlockReason::Waiting: resume_wait(); break; - - default: ensure(false); - } - VMM::apply_address_space(); - block_reason = BlockReason::None; - state = Running; -} - -bool Task::is_still_blocking() -{ - switch (block_reason) - { - case BlockReason::None: return true; - case BlockReason::Reading: return is_read_still_blocking(); - case BlockReason::Waiting: return is_wait_still_blocking(); - - default: return true; - } -} - -Descriptor* Task::open_descriptor_from_fd(int fd, int& error) -{ - Descriptor* file = descriptor_from_fd(fd, error); - if (!file) return nullptr; - if (!file->is_open()) - { - error = EBADF; - return nullptr; - } - return file; -} - -Descriptor* Task::descriptor_from_fd(int fd, int& error) -{ - if (fd < 0 || fd >= TASK_MAX_FDS) - { - error = EBADF; - return nullptr; - } - return &files[fd]; -} - -bool Task::is_superuser() -{ - return euid == 0; -} \ No newline at end of file diff --git a/kernel/src/trace/Resolve.cpp b/kernel/src/trace/Resolve.cpp deleted file mode 100644 index 77bbc71d..00000000 --- a/kernel/src/trace/Resolve.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "trace/Resolve.h" -#include "fs/InitRD.h" -#include "std/stdlib.h" -#include "std/string.h" -#include - -extern int kernel_start; -extern int kernel_end; - -static InitRD::File symbol_map = {"", 0, 0, (void*)-1, 0}; - -static size_t symbol_strlen(const char* symbol) -{ - const char* i = symbol; - for (; *i != '\n' && *i; ++i) - ; - return (i - symbol); -} - -void get_symbol_name(uintptr_t address, char* buffer, size_t max) -{ - if (symbol_map.addr == (void*)-1) { symbol_map = InitRD::open("sys/moon.sym"); } - if (!symbol_map.addr) { strlcpy(buffer, "(no symbols loaded)", max); } - while (address >= (uintptr_t)&kernel_start && address <= (uintptr_t)&kernel_end) - { - char addr_as_str[60]; - ultoa(address, addr_as_str, 16); - char* symbol = strstr((char*)symbol_map.addr, addr_as_str); - if (symbol) - { - symbol += 19; - size_t symlen = symbol_strlen(symbol); - size_t copylen = (max - 1) < symlen ? (max - 1) : symlen; - memcpy(buffer, symbol, copylen); - buffer[copylen] = 0; - return; - } - address--; - } - strlcpy(buffer, "(no symbol)", max); -} \ No newline at end of file diff --git a/kernel/src/trace/StackTracer.cpp b/kernel/src/trace/StackTracer.cpp deleted file mode 100644 index cf9a4572..00000000 --- a/kernel/src/trace/StackTracer.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#define MODULE "trace" - -#include "trace/StackTracer.h" -#include "log/Log.h" -#include "memory/Memory.h" -#include "std/stdio.h" -#include "trace/Resolve.h" - -StackTracer::StackTracer() -{ - asm("mov %%rbp, %0" : "=r"(m_base_pointer)); -} - -StackTracer::StackTracer(uintptr_t base_pointer) : m_base_pointer(base_pointer) -{ -} - -typedef struct stackframe -{ - struct stackframe* next; - uintptr_t instruction; -} stackframe; - -void StackTracer::trace() -{ - stackframe* frame = (stackframe*)m_base_pointer; - while (frame && frame->instruction && Memory::is_kernel_address(frame->instruction)) - { - char symbol_name[512]; - get_symbol_name(frame->instruction - sizeof(uintptr_t), symbol_name, sizeof(symbol_name)); - kinfoln("%lx: %s", frame->instruction - sizeof(uintptr_t), symbol_name); - frame = frame->next; - } -} - -void StackTracer::trace_with_ip(uintptr_t ip) -{ - char symbol_name[512]; - get_symbol_name(ip, symbol_name, sizeof(symbol_name)); - kinfoln("%lx: %s", ip, symbol_name); - trace(); -} - -bool stack_trace_contains(uintptr_t address) -{ - uintptr_t base_pointer; - asm volatile("mov %%rbp, %0" : "=r"(base_pointer)); - stackframe* frame = (stackframe*)base_pointer; - while (Memory::is_kernel_address((uintptr_t)frame)) - { - if (frame->instruction == address) return true; - frame = frame->next; - } - return false; -} \ No newline at end of file diff --git a/kernel/src/utils/PageFaultReason.cpp b/kernel/src/utils/PageFaultReason.cpp deleted file mode 100644 index 054a2294..00000000 --- a/kernel/src/utils/PageFaultReason.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#define MODULE "mem" - -#include "utils/PageFaultReason.h" -#include "log/Log.h" - -#define PROGRAM_STACK_BOTTOM 0x100000 - -void determine_user_page_fault_reason(uintptr_t faulting_address) -{ - if (faulting_address < 0x1000) - { - kinfoln("Address 0x%lx looks like a nullptr dereference", faulting_address); - return; - } - if (faulting_address < PROGRAM_STACK_BOTTOM && (PROGRAM_STACK_BOTTOM - faulting_address) < 0x1000) - { - kinfoln("Address 0x%lx looks like a stack overflow", faulting_address); - return; - } -} \ No newline at end of file diff --git a/kernel/src/utils/StringParsing.cpp b/kernel/src/utils/StringParsing.cpp deleted file mode 100644 index 0662aa52..00000000 --- a/kernel/src/utils/StringParsing.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "utils/StringParsing.h" - -int isdigit(int c) -{ - return c >= '0' && c < ':'; -} - -int isodigit(int c) -{ - return c >= '0' && c < '8'; -} - -int isxdigit(int c) -{ - return isdigit(c) || ((unsigned int)c | 32) - 'a' < 6; -} - -template -static T string_to_integer_type(const char* str, int base, ValidDigitChecker checker, Converter converter) -{ - bool neg = false; - T val = 0; - - switch (*str) - { - case '-': - neg = true; - str++; - break; - case '+': str++; break; - default: break; - } - - while (checker(*str)) { val = (base * val) + converter(*str++); } - - return (neg ? -val : val); -} - -long parse_decimal(const char* str) -{ - return string_to_integer_type( - str, 10, [](char c) { return isdigit(c); }, [](char c) { return c - '0'; }); -} - -long parse_octal(const char* str) -{ - return string_to_integer_type( - str, 8, [](char c) { return isodigit(c); }, [](char c) { return c - '0'; }); -} \ No newline at end of file diff --git a/kernel/src/utils/Time.cpp b/kernel/src/utils/Time.cpp deleted file mode 100644 index 0476a6b2..00000000 --- a/kernel/src/utils/Time.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#define MODULE "time" - -#include "utils/Time.h" -#include "log/Log.h" - -int isleap(int year) -{ - return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); -} - -int make_yday(int year, int month) -{ - static const short int upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - int yd; - - yd = upto[month - 1]; - if (month > 2 && isleap(year)) yd++; - return yd; -} - -uint64_t broken_down_to_unix(uint64_t year, uint64_t yday, uint64_t hour, uint64_t min, uint64_t sec) -{ - return sec + min * 60 + hour * 3600 + yday * 86400 + (year - 70) * 31536000 + ((year - 69) / 4) * 86400 - - ((year - 1) / 100) * 86400 + ((year + 299) / 400) * 86400; -} - -static int bcd_number_to_decimal(int num) -{ - return ((num >> 4) * 10) + (num & 0xf); -} - -uint64_t unix_boottime(uint8_t boottime[8]) -{ - int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); - int month = bcd_number_to_decimal(boottime[2]); - int day = bcd_number_to_decimal(boottime[3]); - int hour = bcd_number_to_decimal(boottime[4]); - int minute = bcd_number_to_decimal(boottime[5]); - int second = bcd_number_to_decimal(boottime[6]); - kinfoln("UTC boot time: %d-%d-%d %d:%d:%d", year, month, day, hour, minute, second); - return broken_down_to_unix(year - 1900, make_yday(year, month) + (day - 1), hour, minute, second); -} \ No newline at end of file diff --git a/libs/Makefile b/libs/Makefile deleted file mode 100644 index a0712517..00000000 --- a/libs/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -build: - @$(MAKE) -C libc build - -install: - @$(MAKE) -C libc install - -clean: - @$(MAKE) -C libc clean \ No newline at end of file diff --git a/libs/libc/Makefile b/libs/libc/Makefile deleted file mode 100644 index 804c5682..00000000 --- a/libs/libc/Makefile +++ /dev/null @@ -1,87 +0,0 @@ -LIBC_DIR := $(LUNA_ROOT)/libs/libc -LIBC_SRC := $(LIBC_DIR)/src -LIBC_OBJ := $(LIBC_DIR)/lib -LIBC_BIN := $(LIBC_DIR)/bin - -DESTDIR ?= $(LUNA_BASE)/usr/lib - -CFLAGS := -Os -nostdlib -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -pedantic -Wall -Wextra -Werror -Wfloat-equal -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion -CXXFLAGS := -fno-rtti -fno-exceptions -Wsign-promo -Wstrict-null-sentinel -Wctor-dtor-privacy -ASMFLAGS := -felf64 - -rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) - -CXX_SRC = $(call rwildcard,$(LIBC_SRC),*.cpp) -C_SRC = $(call rwildcard,$(LIBC_SRC),*.c) -ASM_SRC = $(call rwildcard,$(LIBC_SRC),*.asm) - -OBJS = $(patsubst $(LIBC_SRC)/%.cpp, $(LIBC_OBJ)/%.cpp.o, $(CXX_SRC)) -OBJS += $(patsubst $(LIBC_SRC)/%.c, $(LIBC_OBJ)/%.c.o, $(C_SRC)) -OBJS += $(patsubst $(LIBC_SRC)/%.asm, $(LIBC_OBJ)/%.asm.o, $(ASM_SRC)) - -$(LIBC_OBJ)/%.cpp.o: $(LIBC_SRC)/%.cpp - @mkdir -p $(@D) - @$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $^ - @echo " CXX $^" - -$(LIBC_OBJ)/%.c.o: $(LIBC_SRC)/%.c - @mkdir -p $(@D) - @$(CC) $(CFLAGS) -o $@ -c $^ - @echo " CC $^" - -$(LIBC_OBJ)/%.asm.o: $(LIBC_SRC)/%.asm - @mkdir -p $(@D) - @$(ASM) $(ASMFLAGS) -o $@ $^ - @echo " ASM $^" - -$(LIBC_BIN)/libc.a: $(OBJS) - @mkdir -p $(@D) - @$(AR) rcs $@ $(OBJS) - @echo " AR $@" - -$(LIBC_BIN)/crt0.o: $(LIBC_DIR)/crt0.asm - @mkdir -p $(@D) - @$(ASM) $(ASMFLAGS) -o $@ $^ - @echo " ASM $^" - -$(LIBC_BIN)/crti.o: $(LIBC_DIR)/crti.asm - @mkdir -p $(@D) - @$(ASM) $(ASMFLAGS) -o $@ $^ - @echo " ASM $^" - -$(LIBC_BIN)/crtn.o: $(LIBC_DIR)/crtn.asm - @mkdir -p $(@D) - @$(ASM) $(ASMFLAGS) -o $@ $^ - @echo " ASM $^" - -build: $(LIBC_BIN)/crt0.o $(LIBC_BIN)/crti.o $(LIBC_BIN)/crtn.o $(LIBC_BIN)/libc.a - -$(DESTDIR)/libc.a: $(LIBC_BIN)/libc.a - @mkdir -p $(@D) - @cp $^ $@ - @rm -f $(DESTDIR)/libm.a - @ln -s $@ $(DESTDIR)/libm.a - @echo " INSTALL $^" - -$(DESTDIR)/crt0.o: $(LIBC_BIN)/crt0.o - @mkdir -p $(@D) - @cp $^ $@ - @echo " INSTALL $^" - -$(DESTDIR)/crti.o: $(LIBC_BIN)/crti.o - @mkdir -p $(@D) - @cp $^ $@ - @echo " INSTALL $^" - -$(DESTDIR)/crtn.o: $(LIBC_BIN)/crtn.o - @mkdir -p $(@D) - @cp $^ $@ - @echo " INSTALL $^" - -install: $(DESTDIR)/libc.a $(DESTDIR)/crt0.o $(DESTDIR)/crti.o $(DESTDIR)/crtn.o - -clean: - rm -rf $(LIBC_OBJ)/* - rm -rf $(LIBC_BIN)/* - rm -f $(DESTDIR)/libc.a - rm -f $(DESTDIR)/crt*.o \ No newline at end of file diff --git a/libs/libc/crt0.asm b/libs/libc/crt0.asm deleted file mode 100644 index 71973e6a..00000000 --- a/libs/libc/crt0.asm +++ /dev/null @@ -1,35 +0,0 @@ -section .text - -extern _init -extern main -extern _fini -extern initialize_libc -extern exit - -global _start -_start: - ; Set up end of the stack frame linked list. - xor rbp, rbp - push rbp ; rip=0 - push rbp ; rbp=0 - mov rbp, rsp - - push rdi - push rsi - - call initialize_libc - - call _init - - pop rsi ; argv - pop rdi ; argc - - call main - - push rax - - call _fini - - pop rdi - - call exit \ No newline at end of file diff --git a/libs/libc/crti.asm b/libs/libc/crti.asm deleted file mode 100644 index 6b5aed06..00000000 --- a/libs/libc/crti.asm +++ /dev/null @@ -1,11 +0,0 @@ -section .init -global _init -_init: - push rbp - mov rbp, rsp - -section .fini -global _fini -_fini: - push rbp - mov rbp, rsp \ No newline at end of file diff --git a/libs/libc/crtn.asm b/libs/libc/crtn.asm deleted file mode 100644 index 5d8b3e55..00000000 --- a/libs/libc/crtn.asm +++ /dev/null @@ -1,7 +0,0 @@ -section .init - pop rbp - ret - -section .fini - pop rbp - ret \ No newline at end of file diff --git a/libs/libc/include/alloca.h b/libs/libc/include/alloca.h deleted file mode 100644 index 17b377cb..00000000 --- a/libs/libc/include/alloca.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ALLOCA_H -#define _ALLOCA_H - -#define alloca __builtin_alloca - -#endif \ No newline at end of file diff --git a/libs/libc/include/assert.h b/libs/libc/include/assert.h deleted file mode 100644 index 2090bd17..00000000 --- a/libs/libc/include/assert.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _ASSERT_H -#define _ASSERT_H - -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - - __lc_noreturn bool __assertion_failed(const char* file, int line, const char* function, const char* expr); - -#ifdef __cplusplus -} -#endif - -#ifdef NDEBUG -#define assert(expr) (void)0 -#else -#define assert(expr) (bool)(expr) || __assertion_failed(__FILE__, __LINE__, __FUNCTION__, #expr) // Verify a condition. -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/bits/error.h b/libs/libc/include/bits/error.h deleted file mode 100644 index 8e92d81f..00000000 --- a/libs/libc/include/bits/error.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _BITS_ERROR_H -#define _BITS_ERROR_H - -#include - -#define _RETURN_WITH_ERRNO(rc, type) \ - do { \ - if (rc < 0) \ - { \ - errno = (int)(-rc); \ - return -1; \ - } \ - errno = 0; \ - return (type)rc; \ - } while (0) - -#define _RETURN_WITH_MEMORY_ERRNO(rc, type) \ - do { \ - if ((unsigned long int)rc > 0xffffffffffffff00) \ - { \ - errno = (int)((rc)&0xff); \ - return (type)-1; \ - } \ - errno = 0; \ - return (type)rc; \ - } while (0) - -#endif \ No newline at end of file diff --git a/libs/libc/include/bits/getprocid.h b/libs/libc/include/bits/getprocid.h deleted file mode 100644 index aa0396a4..00000000 --- a/libs/libc/include/bits/getprocid.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _BITS_GETPROCID_H -#define _BITS_GETPROCID_H - -#define ID_PID 0 -#define ID_PPID 1 -#define ID_UID 2 -#define ID_EUID 3 -#define ID_GID 4 -#define ID_EGID 5 - -#endif \ No newline at end of file diff --git a/libs/libc/include/bits/liballoc.h b/libs/libc/include/bits/liballoc.h deleted file mode 100644 index 1375c4fe..00000000 --- a/libs/libc/include/bits/liballoc.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef _BITS_LIBALLOC_H -#define _BITS_LIBALLOC_H - -#include - -/** \defgroup ALLOCHOOKS liballoc hooks - * - * These are the OS specific functions which need to - * be implemented on any platform that the library - * is expected to work on. - */ - -/** @{ */ - -// If we are told to not define our own size_t, then we skip the define. -//#define _HAVE_UINTPTR_T -// typedef unsigned long uintptr_t; - -// This lets you prefix malloc and friends -#define PREFIX(func) func - -#ifdef __cplusplus -extern "C" -{ -#endif - - /** This function is supposed to lock the memory data structures. It - * could be as simple as disabling interrupts or acquiring a spinlock. - * It's up to you to decide. - * - * \return 0 if the lock was acquired successfully. Anything else is - * failure. - */ - extern int liballoc_lock(); - - /** This function unlocks what was previously locked by the liballoc_lock - * function. If it disabled interrupts, it enables interrupts. If it - * had acquiried a spinlock, it releases the spinlock. etc. - * - * \return 0 if the lock was successfully released. - */ - extern int liballoc_unlock(); - - /** This is the hook into the local system which allocates pages. It - * accepts an integer parameter which is the number of pages - * required. The page size was set up in the liballoc_init function. - * - * \return NULL if the pages were not allocated. - * \return A pointer to the allocated memory. - */ - extern void* liballoc_alloc(size_t); - - /** This frees previously allocated memory. The void* parameter passed - * to the function is the exact same value returned from a previous - * liballoc_alloc call. - * - * The integer value is the number of pages to free. - * - * \return 0 if the memory was successfully freed. - */ - extern int liballoc_free(void*, size_t); - - extern void* PREFIX(malloc)(size_t); ///< The standard function. - extern void* PREFIX(realloc)(void*, size_t); ///< The standard function. - extern void* PREFIX(calloc)(size_t, size_t); ///< The standard function. - extern void PREFIX(free)(void*); ///< The standard function. - -#ifdef __cplusplus -} -#endif - -/** @} */ - -#endif diff --git a/libs/libc/include/bits/macros.h b/libs/libc/include/bits/macros.h deleted file mode 100644 index 12ca8372..00000000 --- a/libs/libc/include/bits/macros.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _BITS_MACROS_H -#define _BITS_MACROS_H - -#define __lc_noreturn __attribute__((noreturn)) -#define __lc_align(n) __attribute__((aligned(n))) -#define __lc_deprecated(msg) __attribute__((deprecated(msg))) -#define __lc_is_deprecated __attribute__((deprecated)) -#define __lc_unreachable __builtin_unreachable -#define __lc_used __attribute__((used)) -#define __lc_unused __attribute__((unused)) - -#endif \ No newline at end of file diff --git a/libs/libc/include/bits/seek.h b/libs/libc/include/bits/seek.h deleted file mode 100644 index ed0e59d3..00000000 --- a/libs/libc/include/bits/seek.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _BITS_SEEK_H -#define _BITS_SEEK_H - -#define SEEK_SET 0 // Seek from beginning of file. -#define SEEK_CUR 1 // Seek from current position. -#define SEEK_END 2 // Seek from end of file. - -#endif \ No newline at end of file diff --git a/libs/libc/include/ctype.h b/libs/libc/include/ctype.h deleted file mode 100644 index ac08800d..00000000 --- a/libs/libc/include/ctype.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _CTYPE_H -#define _CTYPE_H - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Is this character alphanumeric? */ - int isalnum(int c); - - /* Is this character a letter? */ - int isalpha(int c); - - /* Is this character part of ASCII? */ - int isascii(int c); - - /* Is this character a blank character (space or tab)? */ - int isblank(int c); - - /* Is this character a control character? */ - int iscntrl(int c); - - /* Is this character a digit? */ - int isdigit(int c); - - /* Is this character any printable character except space? */ - int isgraph(int c); - - /* Is this character a lowercase letter? */ - int islower(int c); - - /* Is this character any printable character (including space)? */ - int isprint(int c); - - /* Is this character any printable character which is not a space or an alphanumeric character? */ - int ispunct(int c); - - /* Is this character any space character (space, form feed, newline, carriage return, tab, vertical tab)? */ - int isspace(int c); - - /* Is this character an uppercase letter? */ - int isupper(int c); - - /* Is this character a hexadecimal digit (0-9, a-f, A-F)? */ - int isxdigit(int c); - - /* Returns the lowercase form of the specified character. */ - int tolower(int c); - - /* Returns the uppercase form of the specified character. */ - int toupper(int c); - - /* Returns the character c, truncated to fit in the ASCII character set. This function should not be used, as it - * will convert accented letters into random characters. */ - __lc_is_deprecated int toascii(int c); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/dirent.h b/libs/libc/include/dirent.h deleted file mode 100644 index 26f3dc0b..00000000 --- a/libs/libc/include/dirent.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef _DIRENT_H -#define _DIRENT_H - -#include -#include - -/* An entry in a directory. */ -struct dirent -{ - ino_t d_ino; - off_t d_off; - unsigned short d_reclen; - unsigned char d_type; - char d_name[NAME_MAX]; -}; - -#define DT_BLK 1 // This is a block device. -#define DT_CHR 2 // This is a character device. -#define DT_DIR 3 // This is a directory. -#define DT_FIFO 4 // This is a named pipe (FIFO). -#define DT_LNK 5 // This is a symbolic link. -#define DT_REG 6 // This is a regular file. -#define DT_SOCK 7 // This is a UNIX domain socket. -#define DT_UNKNOWN 0 // The file type could not be determined. - -/* A stream representing a directory. */ -typedef struct -{ - int d_dirfd; -} DIR; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Opens the directory at path and returns a handle to it, or NULL on error. */ - DIR* opendir(const char* path); - - /* Returns a new directory handle associated with the file descriptor fd. */ - DIR* fdopendir(int fd); - - /* Closes the directory stream. */ - int closedir(DIR* stream); - - /* Reads an entry from the directory stream. The contents of the pointer returned may be overwritten by subsequent - * calls to readdir(). */ - struct dirent* readdir(DIR* stream); - - /* Returns the file descriptor associated with stream. */ - int dirfd(DIR* stream); - - /* Positions stream's offset at the start of the directory. */ - void rewinddir(DIR* stream); - - /* Returns the current offset position for stream. */ - long telldir(DIR* stream); - - /* Moves stream's read offset to offset, which should be the return value of a previous call to telldir(). */ - void seekdir(DIR* stream, long offset); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/errno.h b/libs/libc/include/errno.h deleted file mode 100644 index 53d58486..00000000 --- a/libs/libc/include/errno.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _ERRNO_H -#define _ERRNO_H - -/* The last error encountered during a call to a library or system function. */ -extern int errno; - -#define EPERM 1 // Operation not permitted -#define ENOENT 2 // No such file or directory -#define ESRCH 3 // No such process -#define EINTR 4 // Interrupted system call. Not implemented. -#define EIO 5 // Input/output error. Not implemented. -#define ENXIO 6 // No such device or address. Not implemented. -#define E2BIG 7 // Argument list too long -#define ENOEXEC 8 // Exec format error -#define EBADF 9 // Bad file descriptor -#define ECHILD 10 // No child processes -#define EAGAIN 11 // Resource temporarily unavailable -#define EWOULDBLOCK 11 // Resource temporarily unavailable -#define ENOMEM 12 // Cannot allocate memory -#define EACCES 13 // Permission denied -#define EFAULT 14 // Bad address -#define EBUSY 16 // Device or resource busy. Not implemented. -#define EEXIST 17 // File exists -#define EXDEV 18 // Invalid cross-device link. Not implemented. -#define ENODEV 19 // No such device. Not implemented. -#define ENOTDIR 20 // Not a directory -#define EISDIR 21 // Is a directory -#define EINVAL 22 // Invalid argument -#define ENFILE 23 // Too many open files in system. Not implemented. -#define EMFILE 24 // Too many open files -#define ENOTTY 25 // Inappropriate ioctl for device -#define EFBIG 27 // File too large. Not implemented. -#define ENOSPC 28 // No space left on device -#define ESPIPE 29 // Illegal seek. Not implemented. -#define EROFS 30 // Read-only file system. Not implemented. -#define EMLINK 31 // Too many links. Not implemented. -#define EPIPE 32 // Broken pipe. Not implemented. -#define EDOM 33 // Numerical argument out of domain. Not implemented. -#define ERANGE 34 // Numerical result out of range -#define EDEADLK 35 // Resource deadlock avoided. Not implemented. -#define ENAMETOOLONG 36 // File name too long. Not implemented. -#define ENOLCK 37 // No locks available. Not implemented. -#define ENOSYS 38 // Function not implemented -#define ENOTEMPTY 39 // Directory not empty. Not implemented. -#define ELOOP 40 // Too many levels of symbolic links. Not implemented. -#define ENOMSG 42 // No message of desired type. Not implemented. -#define EOVERFLOW 75 // Value too large for defined data type. Not implemented. -#define EILSEQ 84 // Invalid or incomplete multibyte or wide character. Not implemented. -#define ENOTSOCK 88 // Socket operation on non-socket. Not implemented. -#define ENOTSUP 95 // Operation not supported -#define EOPNOTSUPP 95 // Operation not supported -#define EADDRINUSE 98 // Address already in use. Not implemented. -#define ENETRESET 102 // Network dropped connection on reset. Not implemented. -#define ECONNRESET 104 // Connection reset by peer. Not implemented. -#define EISCONN 106 // Transport endpoint is already connected. Not implemented. -#define ETIMEDOUT 110 // Connection timed out. Not implemented. -#define EALREADY 114 // Operation already in progress. Not implemented. - -// FIXME: Right now I don't want to have to order and label these, since we have no net support anyways. -#define EADDRNOTAVAIL -1 -#define EAFNOSUPPORT -2 -#define ECONNABORTED -3 -#define ECONNREFUSED -4 -#define EDESTADDRREQ -5 -#define EHOSTUNREACH -6 -#define EINPROGRESS -7 -#define EMSGSIZE -8 -#define ENETDOWN -9 -#define ENETRESET -10 -#define ENETUNREACH -11 -#define ENOBUFS -12 -#define ENOMSG -13 -#define ENOPROTOOPT -14 -#define ENOTCONN -15 -#define ENOTSOCK -16 -#define EPROTONOSUPPORT -17 -#define EPROTOTYPE -18 - -#ifdef _GNU_SOURCE // Give it only to programs that ask for it. -/* Name used to invoke calling program. Same value as argv[0] in main(), but can be used globally. */ -extern char* program_invocation_name; -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/fcntl.h b/libs/libc/include/fcntl.h deleted file mode 100644 index 0af71315..00000000 --- a/libs/libc/include/fcntl.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _FCNTL_H -#define _FCNTL_H - -#include - -/* Open for reading only. */ -#define O_RDONLY 1 -/* Open for writing only. */ -#define O_WRONLY 2 -/* Open for reading and writing. */ -#define O_RDWR 3 -/* Open without blocking. */ -#define O_NONBLOCK 4 -/* Close the opened file descriptor on a call to execve(). */ -#define O_CLOEXEC 8 -/* Refuse to open the file if it is not a directory. */ -#define O_DIRECTORY 16 -/* Truncate the file on open. */ -#define O_TRUNC 32 -/* Create the file if it doesn't exist. */ -#define O_CREAT 64 -/* Open the file for appending. */ -#define O_APPEND 128 -/* Fail to open the file if it already exists. */ -#define O_EXCL 256 - -/* Duplicate a file descriptor. */ -#define F_DUPFD 0 -/* Is a file descriptor a TTY? */ -#define F_ISTTY 1 -/* Get the file descriptor flags. */ -#define F_GETFD 2 -/* Set the file descriptor flags. */ -#define F_SETFD 3 - -/* Close the file descriptor on a call to execve(). */ -#define FD_CLOEXEC 1 - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Opens the file specified by pathname. Returns a file descriptor on success, or -1 on error. */ - int open(const char* pathname, int flags, ...); - - /* Opens the file specified by pathname, creating it if it doesn't exist or overwriting it otherwise. Calling this - * function is equivalent to calling open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode) */ - int creat(const char* pathname, mode_t mode); - - /* Performs an operation on the file descriptor fd determined by cmd. */ - int fcntl(int fd, int cmd, ...); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/inttypes.h b/libs/libc/include/inttypes.h deleted file mode 100644 index ecc873d1..00000000 --- a/libs/libc/include/inttypes.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _INTTYPES_H -#define _INTTYPES_H - -#include - -#define __PRI64_PREFIX "l" - -#define PRId8 "d" -#define PRId16 "d" -#define PRId32 "d" -#define PRId64 __PRI64_PREFIX "d" -#define PRIdLEAST8 "d" -#define PRIdLEAST16 "d" -#define PRIdLEAST32 "d" -#define PRIdLEAST64 __PRI64_PREFIX "d" -#define PRIdFAST8 "d" -#define PRIdFAST16 "d" -#define PRIdFAST32 "d" -#define PRIdFAST64 __PRI64_PREFIX "d" -#define PRIdMAX __PRI64_PREFIX "d" -#define PRIdPTR __PRI64_PREFIX "d" -#define PRIi8 "d" -#define PRIi16 "d" -#define PRIi32 "d" -#define PRIi64 __PRI64_PREFIX "d" -#define PRIiLEAST8 "d" -#define PRIiLEAST16 "d" -#define PRIiLEAST32 "d" -#define PRIiLEAST64 __PRI64_PREFIX "d" -#define PRIiFAST8 "d" -#define PRIiFAST16 "d" -#define PRIiFAST32 "d" -#define PRIiFAST64 __PRI64_PREFIX "d" -#define PRIiMAX __PRI64_PREFIX "d" -#define PRIiPTR __PRI64_PREFIX "d" -#define PRIu8 "u" -#define PRIu16 "u" -#define PRIu32 "u" -#define PRIu64 __PRI64_PREFIX "u" -#define PRIuLEAST8 "u" -#define PRIuLEAST16 "u" -#define PRIuLEAST32 "u" -#define PRIuLEAST64 __PRI64_PREFIX "u" -#define PRIuFAST8 "u" -#define PRIuFAST16 "u" -#define PRIuFAST32 "u" -#define PRIuFAST64 __PRI64_PREFIX "u" -#define PRIuMAX __PRI64_PREFIX "u" -#define PRIuPTR __PRI64_PREFIX "u" -#define PRIx8 "x" -#define PRIx16 "x" -#define PRIx32 "x" -#define PRIx64 __PRI64_PREFIX "x" -#define PRIxLEAST8 "x" -#define PRIxLEAST16 "x" -#define PRIxLEAST32 "x" -#define PRIxLEAST64 __PRI64_PREFIX "x" -#define PRIxFAST8 "x" -#define PRIxFAST16 "x" -#define PRIxFAST32 "x" -#define PRIxFAST64 __PRI64_PREFIX "x" -#define PRIxMAX __PRI64_PREFIX "x" -#define PRIxPTR __PRI64_PREFIX "x" -#define PRIX8 PRIx8 -#define PRIX16 PRIx16 -#define PRIX32 PRIx32 -#define PRIX64 PRIx64 -#define PRIXMAX PRIxMAX -#define PRIXPTR PRIxPTR - -#endif \ No newline at end of file diff --git a/libs/libc/include/libgen.h b/libs/libc/include/libgen.h deleted file mode 100644 index a6479447..00000000 --- a/libs/libc/include/libgen.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _LIBGEN_H -#define _LIBGEN_H - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Returns the last component of a path. This function is allowed to modify the string passed to it, so it should - * probably be a copy of another string. */ - char* basename(char* path); - - /* Returns the parent directory of a path. This function is allowed to modify the string passed to it, so it should - * probably be a copy of another string. */ - char* dirname(char* path); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/locale.h b/libs/libc/include/locale.h deleted file mode 100644 index c2182e6a..00000000 --- a/libs/libc/include/locale.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _LOCALE_H -#define _LOCALE_H - -#define LC_ALL 0 -#define LC_CTYPE 1 -#define LC_COLLATE 2 -#define LC_NUMERIC 3 -#define LC_MONETARY 4 -#define LC_TIME 5 - -/* Structure representing numeric formatting information for the current locale. */ -struct lconv -{ - char* decimal_point; - char* thousands_sep; - char* grouping; - char* int_curr_symbol; - char* currency_symbol; - char* mon_decimal_point; - char* mon_thousands_sep; - char* mon_grouping; - char* positive_sign; - char* negative_sign; - char int_frac_digits; - char frac_digits; - char p_cs_precedes; - char p_sep_by_space; - char n_cs_precedes; - char n_sep_by_space; - char p_sign_posn; - char n_sign_posn; -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Set or query the current locale. */ - char* setlocale(int category, const char* locale); - - /* Retrieve numeric formatting information for the current locale. */ - struct lconv* localeconv(void); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/luna.h b/libs/libc/include/luna.h deleted file mode 100644 index 7ed32c00..00000000 --- a/libs/libc/include/luna.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _LUNA_H -#define _LUNA_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Returns a numeric identifier associated with the current process, depending on field. */ - long getprocid(int field); - - /* Sleeps for ms milliseconds. */ - unsigned int msleep(unsigned int ms); - - /* Prints a message to standard error and aborts the program. */ - __lc_noreturn void __luna_abort(const char* message); - -#ifdef __cplusplus -} -#endif - -#define NOT_IMPLEMENTED(message) __luna_abort("not implemented: " message "\n") - -#endif \ No newline at end of file diff --git a/libs/libc/include/luna/dirent.h b/libs/libc/include/luna/dirent.h deleted file mode 100644 index 6b7f3237..00000000 --- a/libs/libc/include/luna/dirent.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _LUNA_DIRENT_H -#define _LUNA_DIRENT_H - -#include -#include - -struct luna_dirent -{ - ino_t inode; - char name[NAME_MAX]; - size_t total; - off_t offset; -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Retrieve directory entries from the kernel. This is the raw interface, use readdir() instead. */ - ssize_t getdents(int fd, struct luna_dirent* buf, size_t count); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/luna/os-limits.h b/libs/libc/include/luna/os-limits.h deleted file mode 100644 index 6e62f706..00000000 --- a/libs/libc/include/luna/os-limits.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _LUNA_OS_LIMITS_H -#define _LUNA_OS_LIMITS_H - -#define OPEN_MAX 32 -#define ATEXIT_MAX 32 - -#define NAME_MAX 64 -#define PATH_MAX 4096 - -#define PAGESIZE 4096 -#define PAGE_SIZE 4096 - -#endif \ No newline at end of file diff --git a/libs/libc/include/luna/pstat.h b/libs/libc/include/luna/pstat.h deleted file mode 100644 index fe6e4295..00000000 --- a/libs/libc/include/luna/pstat.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _LUNA_PSTAT_H -#define _LUNA_PSTAT_H - -#include - -struct pstat -{ - pid_t pt_pid; - pid_t pt_ppid; - char pt_name[128]; - int pt_state; - long pt_time; - uid_t pt_uid; - gid_t pt_gid; -}; - -#define PT_IDLE 0 -#define PT_RUNNING 1 -#define PT_SLEEPING 2 -#define PT_ZOMBIE 3 -#define PT_WAITING 4 - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Returns information about the process with PID pid in buf, if buf is non-null. Luna-specific. */ - pid_t pstat(pid_t pid, struct pstat* buf); - - /* Returns a string representation of the process state in buf. */ - const char* pstatname(struct pstat* buf); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/luna/syscall.h b/libs/libc/include/luna/syscall.h deleted file mode 100644 index 850d1007..00000000 --- a/libs/libc/include/luna/syscall.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _LUNA_SYSCALL_H -#define _LUNA_SYSCALL_H - -#include - -typedef unsigned long sysarg_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - - long __luna_syscall0(long sys_num); - long __luna_syscall1(long sys_num, sysarg_t arg0); - long __luna_syscall2(long sys_num, sysarg_t arg0, sysarg_t arg1); - long __luna_syscall3(long sys_num, sysarg_t arg0, sysarg_t arg1, sysarg_t arg2); - long __luna_syscall4(long sys_num, sysarg_t arg0, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3); - long __luna_syscall5(long sys_num, sysarg_t arg0, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4); - - inline long __fast_syscall0(long number) - { - long result = __luna_syscall0(number); - _RETURN_WITH_ERRNO(result, long); - } - - inline long __fast_syscall1(long number, sysarg_t arg0) - { - long result = __luna_syscall1(number, arg0); - _RETURN_WITH_ERRNO(result, long); - } - - inline long __fast_syscall2(long number, sysarg_t arg0, sysarg_t arg1) - { - long result = __luna_syscall2(number, arg0, arg1); - _RETURN_WITH_ERRNO(result, long); - } - - inline long __fast_syscall3(long number, sysarg_t arg0, sysarg_t arg1, sysarg_t arg2) - { - long result = __luna_syscall3(number, arg0, arg1, arg2); - _RETURN_WITH_ERRNO(result, long); - } - - inline long __fast_syscall4(long number, sysarg_t arg0, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) - { - long result = __luna_syscall4(number, arg0, arg1, arg2, arg3); - _RETURN_WITH_ERRNO(result, long); - } - - inline long __fast_syscall5(long number, sysarg_t arg0, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) - { - long result = __luna_syscall5(number, arg0, arg1, arg2, arg3, arg4); - _RETURN_WITH_ERRNO(result, long); - } - -#define __lc_fast_syscall0(number) __fast_syscall0(number) -#define __lc_fast_syscall1(number, arg0) __fast_syscall1(number, (sysarg_t)arg0) -#define __lc_fast_syscall2(number, arg0, arg1) __fast_syscall2(number, (sysarg_t)arg0, (sysarg_t)arg1) -#define __lc_fast_syscall3(number, arg0, arg1, arg2) \ - __fast_syscall3(number, (sysarg_t)arg0, (sysarg_t)arg1, (sysarg_t)arg2) -#define __lc_fast_syscall4(number, arg0, arg1, arg2, arg3) \ - __fast_syscall4(number, (sysarg_t)arg0, (sysarg_t)arg1, (sysarg_t)arg2, (sysarg_t)arg3) -#define __lc_fast_syscall5(number, arg0, arg1, arg2, arg3, arg4) \ - __fast_syscall5(number, (sysarg_t)arg0, (sysarg_t)arg1, (sysarg_t)arg2, (sysarg_t)arg3, (sysarg_t)arg4) - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/luna/vfs.h b/libs/libc/include/luna/vfs.h deleted file mode 100644 index e34c83eb..00000000 --- a/libs/libc/include/luna/vfs.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _LUNA_VFS_H -#define _LUNA_VFS_H - -#define __VFS_FILE 0x0 -#define __VFS_DIRECTORY 0x1 -#define __VFS_DEVICE 0x2 - -#define __VFS_TO_IFMT(type) ((1 << type) * 010000) - -#endif \ No newline at end of file diff --git a/libs/libc/include/math.h b/libs/libc/include/math.h deleted file mode 100644 index ced52044..00000000 --- a/libs/libc/include/math.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef _MATH_H -#define _MATH_H - -typedef float float_t; -typedef double double_t; - -#define FP_NAN 0 -#define FP_INFINITE 1 -#define FP_ZERO 2 -#define FP_SUBNORMAL 3 -#define FP_NORMAL 4 -#define fpclassify(x) __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_ZERO, x) - -#ifdef __cplusplus -extern "C" -{ -#endif - - double cos(double val); - float cosf(float val); - long double cosl(long double val); - double sin(double val); - float sinf(float val); - long double sinl(long double val); - double tan(double val); - float tanf(float val); - long double tanl(long double val); - double acos(double val); - float acosf(float val); - long double acosl(long double val); - double asin(double val); - float asinf(float val); - long double asinl(long double val); - double atan(double val); - float atanf(float val); - long double atanl(long double val); - double cosh(double val); - float coshf(float val); - long double coshl(long double val); - double sinh(double val); - float sinhf(float val); - long double sinhl(long double val); - double tanh(double val); - float tanhf(float val); - long double tanhl(long double val); - double log(double val); - float logf(float val); - long double logl(long double val); - double exp(double val); - float expf(float val); - long double expl(long double val); - double sqrt(double val); - float sqrtf(float val); - long double sqrtl(long double val); - double fabs(double val); - float fabsf(float val); - long double fabsl(long double val); - double floor(double val); - float floorf(float val); - long double floorl(long double val); - double ceil(double val); - float ceilf(float val); - long double ceill(long double val); - double log10(double val); - float log10f(float val); - long double log10l(long double val); - double fmod(double val1, double val2); - float fmodf(float val1, float val2); - long double fmodl(long double val1, long double val2); - double pow(double val1, double val2); - float powf(float val1, float val2); - long double powl(long double val1, long double val2); - double atan2(double val1, double val2); - float atan2f(float val1, float val2); - long double atan2l(long double val1, long double val2); - double frexp(double val1, int* val2); - float frexpf(float val1, int* val2); - long double frexpl(long double val1, int* val2); - double ldexp(double val1, int val2); - float ldexpf(float val1, int val2); - long double ldexpl(long double val1, int val2); - double modf(double val1, double* val2); - float modff(float val1, float* val2); - long double modfl(long double val1, long double* val2); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/memory.h b/libs/libc/include/memory.h deleted file mode 100644 index e69de29b..00000000 diff --git a/libs/libc/include/pwd.h b/libs/libc/include/pwd.h deleted file mode 100644 index 517a5f38..00000000 --- a/libs/libc/include/pwd.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _PWD_H -#define _PWD_H - -#include - -/* Structure representing a password file entry. */ -struct passwd -{ - char* pw_name; - char* pw_passwd; - uid_t pw_uid; - gid_t pw_gid; - char* pw_gecos; - char* pw_dir; - char* pw_shell; -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Returns the next password file entry. */ - struct passwd* getpwent(void); - - /* Returns the first password file entry with a login name matching name, or NULL if there are none. */ - struct passwd* getpwnam(const char* name); - - /* Returns the first password file entry with a user ID matching uid, or NULL if there are none. */ - struct passwd* getpwuid(uid_t uid); - - /* Rewinds to the first password file entry. */ - void setpwent(void); - - /* Ends password file processing. */ - void endpwent(void); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/sched.h b/libs/libc/include/sched.h deleted file mode 100644 index baebea5a..00000000 --- a/libs/libc/include/sched.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _SCHED_H -#define _SCHED_H - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Yield the processor. */ - int sched_yield(void); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/setjmp.h b/libs/libc/include/setjmp.h deleted file mode 100644 index d42054aa..00000000 --- a/libs/libc/include/setjmp.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _SETJMP_H -#define _SETJMP_H - -#include -#include - -typedef uintptr_t jmp_buf[8]; -typedef uintptr_t sigjmp_buf[8]; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Saves the current execution state in env. Returns 0 when called from the first time, or nonzero when returning - * from longjmp. */ - int setjmp(jmp_buf env); - - /* Right now, does the exact same as setjmp() (savesigs is ignored), since signals are not implemented. */ - int sigsetjmp(sigjmp_buf env, int savesigs); - - /* Restores the execution state saved in env by a setjmp() call. */ - __lc_noreturn void longjmp(jmp_buf env, int val); - - /* Right now, does the exact same as longjmp(), since signals are not implemented. */ - __lc_noreturn void siglongjmp(sigjmp_buf env, int val); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/signal.h b/libs/libc/include/signal.h deleted file mode 100644 index 691bf0bc..00000000 --- a/libs/libc/include/signal.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _SIGNAL_H -#define _SIGNAL_H - -typedef int sig_atomic_t; // On the x86, writes to aligned 32-bit and 64-bit integers are always atomic. (Or that's what - // I understood) - -#define SIGINT 1 // Not implemented. - -#ifdef __cplusplus -extern "C" -{ -#endif - - void (*signal(int sig, void (*func)(int)))(int); // Not implemented. - int raise(int sig); // Not implemented. - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/stdio.h b/libs/libc/include/stdio.h deleted file mode 100644 index df882d0b..00000000 --- a/libs/libc/include/stdio.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef _STDIO_H -#define _STDIO_H - -#include -#include -#include - -#include - -#define FOPEN_MAX 32 // Maximum number of files that can be simultaneously opened with fopen(). -#define BUFSIZ 1024 // Standard buffer size. -#define FILENAME_MAX 1024 // Dummy value, we don't have a limit for filenames right now. - -/* A stream representing a file. */ -typedef struct -{ - int f_fd; - int f_eof; - int f_err; - char* f_buf; - long f_bufsize; - long f_bufoff; - long f_bufrsize; -} FILE; - -extern FILE* stderr; -extern FILE* stdout; -extern FILE* stdin; - -#define stdin stdin // The standard input stream. -#define stdout stdout // The standard output stream. -#define stderr stderr // The standard error stream. - -#define EOF -1 // End of file. - -#define _IONBF 0 // Not buffered. -#define _IOLBF 1 // Line buffered. -#define _IOFBF 2 // Fully buffered. - -typedef off_t fpos_t; // An offset into a file. - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Closes the file handle stream. */ - int fclose(FILE* stream); - - /* Does not do anything for now, since buffered IO is not implemented yet. */ - int fflush(FILE* stream); - - /* Opens the file specified by pathname. Returns the file handle on success, or NULL on error. */ - FILE* fopen(const char* pathname, const char* mode); - - /* Returns a new file associated with the file descriptor fd. */ - FILE* fdopen(int fd, const char* mode); - - /* Opens the file specified by pathname and points the file handle stream to it. */ - FILE* freopen(const char* pathname, const char* mode, FILE* stream); - - /* Returns the file descriptor associated with the file stream. */ - int fileno(FILE* stream); - - /* Writes formatted output according to the string format to the file stream. */ - int fprintf(FILE* stream, const char* format, ...); - - /* Reads nmemb items of size size from the file stream into buf. */ - size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream); - - /* Moves stream's read/write offset by offset, depending on whence. */ - int fseek(FILE* stream, long offset, int whence); - - /* Moves stream's read/write offset by offset, depending on whence. */ - int fseeko(FILE* stream, off_t offset, int whence); - - /* Moves stream's read/write offset to the offset stored in the pos structure. */ - int fsetpos(FILE* stream, const fpos_t* pos); - - /* Returns the current offset for stream. */ - long ftell(FILE* stream); - - /* Returns the current offset for stream. */ - off_t ftello(FILE* stream); - - /* Stores the current offset for stream in the pos structure. */ - int fgetpos(FILE* stream, fpos_t* pos); - - /* Rewinds stream's offset to start of file. */ - void rewind(FILE* stream); - - /* Writes nmemb items of size size from buf into the file stream. */ - size_t fwrite(const void* buf, size_t size, size_t nmemb, FILE* stream); - - /* Reads a line from stream into buf. */ - char* fgets(char* buf, int size, FILE* stream); - - /* Retrieves a character from stream. */ - int fgetc(FILE* stream); - - /* Retrieves a character from stream. */ - int getc(FILE* stream); - - int ungetc(int, FILE*); // Not implemented. - - /* Retrieves a character from standard input. */ - int getchar(); - - /* Returns nonzero if the error flag in stream was set. */ - int ferror(FILE* stream); - - /* Returns nonzero if the end-of-file flag in stream was set. */ - int feof(FILE* stream); - - /* Clears the error and end-of-file flags from stream. */ - void clearerr(FILE* stream); - - void setbuf(FILE*, char*); // Not implemented. - int setvbuf(FILE*, char*, int, size_t); // Not implemented. - - /* Writes formatted output according to the string format to the file stream. */ - int vfprintf(FILE* stream, const char* format, va_list ap); - - /* Writes formatted output according to the string format to standard output. */ - int printf(const char* format, ...); - - /* Writes formatted output according to the string format to standard output. */ - int vprintf(const char* format, va_list ap); - - /* Writes formatted output according to the string format to the string str. This function is unsafe, use snprintf - * instead. */ - int sprintf(char* str, const char* format, ...); - - /* Writes at most max bytes of formatted output according to the string format to the string str.*/ - int snprintf(char* str, size_t max, const char* format, ...); - - /* Writes formatted output according to the string format to the string str. This function is unsafe, use vsnprintf - * instead. */ - int vsprintf(char* str, const char* format, va_list ap); - - /* Writes at most max bytes of formatted output according to the string format to the string str. */ - int vsnprintf(char* str, size_t max, const char* format, va_list ap); - - int sscanf(const char*, const char*, ...); // Not implemented. - int fscanf(FILE*, const char*, ...); // Not implemented. - int scanf(const char*, ...); // Not implemented. - - /* Writes the string str followed by a trailing newline to stdout. */ - int puts(const char* str); - - /* Writes the string str to the file stream. */ - int fputs(const char* str, FILE* stream); - - /* Writes the character c to the file stream. */ - int fputc(int c, FILE* stream); - - /* Writes the character c to the file stream. */ - int putc(int c, FILE* stream); - - /* Writes the character c to standard output. */ - int putchar(int c); - - /* Prints a message to standard error consisting of the string str followed by a colon and the string representation - * of the last error encountered during a call to a system or library function. */ - void perror(const char* str); - - int remove(const char* pathname); // Not implemented. - int rename(const char* oldpath, const char* newpath); // Not implemented. - - FILE* tmpfile(void); // Not implemented. - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/stdlib.h b/libs/libc/include/stdlib.h deleted file mode 100644 index a665c356..00000000 --- a/libs/libc/include/stdlib.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef _STDLIB_H -#define _STDLIB_H - -#include -#include -#include - -#define EXIT_SUCCESS 0 // Value to use when calling exit() to represent successful execution. -#define EXIT_FAILURE 1 // Value to use when calling exit() to represent failed execution. - -#define RAND_MAX INT_MAX // Maximum number returned by rand(). - -#define MB_CUR_MAX 1 // Maximum length of multibyte characters in the current locale. - -// Return type for an integer division. -typedef struct -{ - int quot; - int rem; -} div_t; - -// Return type for a long integer division. -typedef struct -{ - long quot; - long rem; -} ldiv_t; - -// Return type for a long integer division. -typedef struct -{ - long long quot; - long long rem; -} lldiv_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Aborts the program. */ - __lc_noreturn void abort(void); - - /* Normally exits the program with the specified status code. */ - __lc_noreturn void exit(int status); - - /* Abnormally exits the program with the specified status code. */ - __lc_noreturn void _Exit(int status); - - /* Registers a handler function to be run at normal program termination. */ - int atexit(void (*handler)(void)); - - /* Returns a floating point number parsed from the string str. */ - float atof(const char* str); - - /* Returns an integer (of type int) parsed from the string str. */ - int atoi(const char* str); - - /* Returns an integer (of type long) parsed from the string str. */ - long atol(const char* str); - - /* Returns an integer (of type long long) parsed from the string str. */ - long long atoll(const char* str); - - /* Returns an integer (of type unsigned long) parsed from the string str. */ - unsigned long strtoul(const char* str, char** endptr, int base); - - double strtod(const char* str, char** endptr); // Not implemented. - - /* Returns an integer (of type long) parsed from the string str. */ - long strtol(const char* str, char** endptr, int base); - - /* Not implemented. */ - char* getenv(const char*); - - /* Allocates n bytes of memory and returns a pointer to it. This memory should be freed by calling free() when it is - * not in use anymore. */ - void* malloc(size_t n); - - /* Allocates enough bytes of memory for an array containing nmemb items of size n and returns a pointer to it. This - * memory should be freed by calling free() when it is not in use anymore. */ - void* calloc(size_t nmemb, size_t n); - - /* Resizes memory allocated by malloc() or calloc() to n bytes. Returns a pointer to the new resized region of - * memory, which should be used instead of the old one. This memory should be freed by calling free() when it is not - * in use anymore. */ - void* realloc(void* ptr, size_t n); - - /* Frees a pointer to memory allocated by malloc(), calloc() or realloc(). Accessing the contents of ptr afterwards - * is undefined behavior. */ - void free(void* ptr); - - /* Returns a random number. */ - int rand(void); - - /* Seeds the random number generator with the specified seed. */ - void srand(unsigned int seed); - - /* Returns the absolute value of an integer. */ - int abs(int val); - - /* Returns the absolute value of an integer. */ - long labs(long val); - - /* Returns the absolute value of an integer. */ - long long llabs(long long val); - - /* Returns the result of dividing a by b. */ - div_t div(int a, int b); - - /* Returns the result of dividing a by b. */ - ldiv_t ldiv(long a, long b); - - /* Returns the result of dividing a by b. */ - lldiv_t lldiv(long long a, long long b); - - /* Runs a shell command. */ - int system(const char* command); - - /* Sorts the array pointed to by base of nmemb items of the specified size using the comparison function compar. */ - void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)); - - /* Searches the sorted array base of nmemb items of the specified size for the given key using the comparison - * function compar. */ - void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, - int (*compar)(const void*, const void*)); - - size_t mbstowcs(wchar_t* dest, const char* src, - size_t n); // Not implemented. - - /* Generate a unique filename from the template string str. The last 6 bytes of str must be 'XXXXXX', and they will - * be replaced with random characters. This function is deprecated due to race conditions; between the name being - * generated and creating a file with that name, that filename could have already been used. */ - __lc_is_deprecated char* mktemp(char* str); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/string.h b/libs/libc/include/string.h deleted file mode 100644 index cdfb4dee..00000000 --- a/libs/libc/include/string.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef _STRING_H -#define _STRING_H - -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Copies n bytes from src to dst. */ - void* memcpy(void* dest, const void* src, size_t n); - - /* Sets n bytes of buf to c, cast to a character. */ - void* memset(void* buf, int c, size_t n); - - /* Searches for the character c in n bytes of buf. */ - void* memchr(const void* buf, int c, size_t n); - - /* Compares n bytes of memory at a and b. */ - int memcmp(const void* a, const void* b, size_t n); - - /* Copies n bytes from src to dst. Can be used if src and dst overlap. */ - void* memmove(void* dest, const void* src, size_t n); - - /* Returns a heap-allocated copy of the string str. Should be freed when it is not used anymore. */ - char* strdup(const char* str); - - /* Returns a heap-allocated copy of the string str, copying at maximum max bytes. Should be freed when it is not - * used anymore. */ - char* strndup(const char* str, size_t max); - - /* Returns the length of the string str. */ - size_t strlen(const char* str); - - /* Returns the length of the string str, while examining at most max bytes of str. */ - size_t strnlen(const char* str, size_t max); - - /* Copies at most size-1 bytes from the string src into dest, null-terminating the result. */ - size_t strlcpy(char* dst, const char* src, size_t size); - - /* Copies at most max bytes from the string src into dest. */ - char* strncpy(char* dest, const char* src, size_t max); - - /* Returns a pointer to the first occurrence of the character c in str, or NULL if it is not found. */ - char* strchr(const char* str, int c); - - /* Returns a pointer to the last occurrence of the character c in str, or NULL if it is not found. */ - char* strrchr(const char* str, int c); - - /* Returns a pointer to the first occurrence of the character c in str, or a pointer to the terminating null byte of - * str if it is not found. */ - char* strchrnul(const char* str, int c); - - /* Concatenates at most max bytes of the string src into dest. */ - char* strncat(char* dest, const char* src, size_t max); - - /* Returns the length of the initial segment of str which consists entirely of bytes not in reject. */ - size_t strcspn(const char* str, const char* reject); - - /* Returns the length of the initial segment of str which consists entirely of bytes in accept. */ - size_t strspn(const char* str, const char* accept); - - /* Returns a pointer to the first occurrence of any character of b in a. */ - char* strpbrk(const char* a, const char* b); - - /* Compares strings a and b. You might prefer to use the safer strncmp function. */ - int strcmp(const char* a, const char* b); - - /* Compares at most max bytes of the strings a and b. */ - int strncmp(const char* a, const char* b, size_t max); - - /* Compares a and b based on the current locale. */ - int strcoll(const char* a, const char* b); - - /* Transforms src based on the current locale and stores n bytes of it in dest. */ - size_t strxfrm(char* dest, const char* src, size_t n); - - /* Searches for the needle string in the haystack string. */ - char* strstr(const char* haystack, const char* needle); - - /* Returns the error string associated with the error number err. */ - char* strerror(int err); - - /* Copies the string src into dest. This function is unsafe, use strlcpy instead. */ - __lc_deprecated("strcpy is unsafe and should not be used; use strlcpy instead") char* strcpy(char* dest, - const char* src); - - /* Concatenates the string src into dest. This function is unsafe, use strncat instead. */ - __lc_deprecated("strcat is unsafe and should not be used; use strncat instead") char* strcat(char* dest, - const char* src); - -#ifdef _GNU_SOURCE - /* Copies the string src into dest, returning a pointer to the end of dest. */ - __lc_is_deprecated char* stpcpy(char* dest, const char* src); -#endif - - char* strtok(char* str, const char* delim); // Not implemented. - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/strings.h b/libs/libc/include/strings.h deleted file mode 100644 index dd0952ad..00000000 --- a/libs/libc/include/strings.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _STRINGS_H -#define _STRINGS_H - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Clears n bytes of buf. */ - void bzero(void* buf, size_t n); - - /* Copies n bytes of src into dest. */ - void bcopy(void* dest, const void* src, size_t n); - - /* Compares strings a and b while treating uppercase and lowercase characters as the same. */ - int strcasecmp(const char* a, const char* b); - - /* Compares at most max bytes of strings a and b while treating uppercase and lowercase characters as the same. */ - int strncasecmp(const char* a, const char* b, size_t max); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/sys/ioctl.h b/libs/libc/include/sys/ioctl.h deleted file mode 100644 index 2de4dac5..00000000 --- a/libs/libc/include/sys/ioctl.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _SYS_IOCTL_H -#define _SYS_IOCTL_H - -#include - -/* Get the width of a framebuffer device. */ -#define FB_GET_WIDTH 0 -/* Get the height of a framebuffer device. */ -#define FB_GET_HEIGHT 1 -/* Get the scanline of a framebuffer device. */ -#define FB_GET_SCANLINE 2 - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Perform an arbitrary operation on an open file descriptor. Many operations are device-specific. */ - int ioctl(int fd, int cmd, ...); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/sys/mman.h b/libs/libc/include/sys/mman.h deleted file mode 100644 index e2b86308..00000000 --- a/libs/libc/include/sys/mman.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _SYS_MMAN_H -#define _SYS_MMAN_H - -#include -#include // for off_t - -/* Address returned by mmap when it fails. */ -#define MAP_FAILED (void*)-1 - -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 - -#define PAGE_SIZE 4096 - -#define MAP_PRIVATE 0 -#define MAP_SHARED 1 -#define MAP_ANONYMOUS 2 - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Maps size bytes of memory (rounded up to the nearest page-aligned size) into the current process's address - * space at addr. If addr is null, the kernel will choose an address. */ - void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset); - - /* Unmaps size bytes of memory (rounded up to the nearest page-aligned size) at addr from the current process's - * address space. */ - int munmap(void* addr, size_t size); - - /* Changes the permissions of size bytes of memory at addr zaccording to the prot argument. */ - int mprotect(void* addr, size_t size, int prot); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/sys/param.h b/libs/libc/include/sys/param.h deleted file mode 100644 index e69de29b..00000000 diff --git a/libs/libc/include/sys/stat.h b/libs/libc/include/sys/stat.h deleted file mode 100644 index 7c54a3e0..00000000 --- a/libs/libc/include/sys/stat.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _SYS_STAT_H -#define _SYS_STAT_H - -#include -#include - -struct stat // FIXME: This struct is quite stubbed out. -{ - ino_t st_ino; - mode_t st_mode; - off_t st_size; - int st_dev; // Not implemented. - int st_nlink; // Not implemented. - uid_t st_uid; - gid_t st_gid; - time_t st_atime; - time_t st_mtime; - time_t st_ctime; -}; - -/* Type of file. */ -#define S_IFMT 070000 -/* Directory. */ -#define S_IFDIR __VFS_TO_IFMT(__VFS_DIRECTORY) -/* Regular file. */ -#define S_IFREG __VFS_TO_IFMT(__VFS_FILE) -/* Character device. */ -#define S_IFCHR __VFS_TO_IFMT(__VFS_DEVICE) - -#define __S_IFCMP(mode, value) (mode & S_IFMT) == value - -/* Is it a directory? */ -#define S_ISDIR(mode) (__S_IFCMP((mode), S_IFDIR)) -/* Is it a regular file? */ -#define S_ISREG(mode) (__S_IFCMP((mode), S_IFREG)) -/* Is it a character device? */ -#define S_ISCHR(mode) (__S_IFCMP((mode), S_IFCHR)) - -// Not implemented. -#define S_ISBLK(mode) ((mode)&0) -#define S_ISFIFO(mode) ((mode)&0) - -#define S_IRWXU 0700 -#define S_IRUSR 0400 -#define S_IWUSR 0200 -#define S_IXUSR 0100 -#define S_IRWXG 070 -#define S_IRGRP 040 -#define S_IWGRP 020 -#define S_IXGRP 010 -#define S_IRWXO 07 -#define S_IROTH 04 -#define S_IWOTH 02 -#define S_IXOTH 01 -#define S_ISUID 04000 -#define S_ISGID 02000 - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Creates a new directory at the path pathname with the specified mode. */ - int mkdir(const char* pathname, mode_t mode); - - /* Returns information about the file pointed to by fd in buf. */ - int fstat(int fd, struct stat* buf); - - /* Returns information about the file pointed at path in buf. */ - int stat(const char* pathname, struct stat* buf); - - /* Changes the current process' file creation mask. */ - mode_t umask(mode_t cmask); - - int chmod(const char* pathname, mode_t mode); // Not implemented. - int fchmod(int fd, mode_t mode); // Not implemented. - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/sys/syscall.h b/libs/libc/include/sys/syscall.h deleted file mode 100644 index 27842925..00000000 --- a/libs/libc/include/sys/syscall.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _SYS_SYSCALL_H -#define _SYS_SYSCALL_H - -#define SYS_exit 0 -#define SYS_yield 1 -#define SYS_sleep 2 -#define SYS_write 3 -#define SYS_getprocid 4 -#define SYS_mmap 5 -#define SYS_munmap 6 -#define SYS_open 7 -#define SYS_read 8 -#define SYS_close 9 -#define SYS_seek 10 -#define SYS_execv 11 -#define SYS_fcntl 12 -#define SYS_mprotect 13 -#define SYS_clock_gettime 14 -#define SYS_mkdir 15 -#define SYS_fork 16 -#define SYS_waitpid 17 -#define SYS_access 18 -#define SYS_fstat 19 -#define SYS_pstat 20 -#define SYS_getdents 21 -#define SYS_stat 22 -#define SYS_dup2 23 -#define SYS_setuid 24 -#define SYS_setgid 25 -#define SYS_umask 26 -#define SYS_ioctl 27 -#define SYS_seteuid 28 -#define SYS_setegid 29 - -#endif \ No newline at end of file diff --git a/libs/libc/include/sys/time.h b/libs/libc/include/sys/time.h deleted file mode 100644 index 39f5707f..00000000 --- a/libs/libc/include/sys/time.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _SYS_TIME_H -#define _SYS_TIME_H - -#include -#include - -// Captures elapsed time with microsecond precision. -struct timeval -{ - time_t tv_sec; - suseconds_t tv_usec; -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Retrieves the current time and stores it in tp. */ - __lc_is_deprecated int gettimeofday(struct timeval* tp, void* tzp); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/sys/types.h b/libs/libc/include/sys/types.h deleted file mode 100644 index 9e96a25f..00000000 --- a/libs/libc/include/sys/types.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _SYS_TYPES_H -#define _SYS_TYPES_H - -/* The type of a process identifier. */ -typedef long int pid_t; - -/* The type returned by sizeof(). */ -typedef unsigned long int size_t; - -/* Signed version of size_t. */ -typedef long int ssize_t; - -/* The type of an offset into a file. */ -typedef long int off_t; - -/* The type of a file's mode. */ -typedef unsigned short mode_t; - -/* The type of a filesystem inode. */ -typedef unsigned long ino_t; - -/* Value representing a time unit since the start of the current program. */ -typedef long int clock_t; - -/* Value representing time in seconds. */ -typedef long int time_t; - -/* Type representing signed time in microseconds. */ -typedef long int suseconds_t; - -/* Type representing a user ID. */ -typedef int uid_t; - -/* Type representing a group ID. */ -typedef int gid_t; - -/* Type representing a system clock. */ -typedef int clockid_t; - -#endif \ No newline at end of file diff --git a/libs/libc/include/sys/wait.h b/libs/libc/include/sys/wait.h deleted file mode 100644 index 792ad645..00000000 --- a/libs/libc/include/sys/wait.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _SYS_WAIT_H -#define _SYS_WAIT_H - -#include - -/* Has the child process exited by calling exit() or _exit()? */ -#define WIFEXITED(status) ((status) || 1) - -/* What was the child's exit status? */ -#define WEXITSTATUS(status) (char)((status)&0xff) - -/* Do not block the current process if no child has exited. */ -#define WNOHANG 1 - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Waits for the child process to finish running. */ - pid_t waitpid(pid_t pid, int* wstatus, int options); - - /* Waits for any child process to finish running. */ - pid_t wait(int* wstatus); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/time.h b/libs/libc/include/time.h deleted file mode 100644 index 1e66f35a..00000000 --- a/libs/libc/include/time.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef _TIME_H -#define _TIME_H - -#include -#include -#include - -// Structure representing broken-down time. -struct tm -{ - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; -}; - -// Captures elapsed time with nanosecond precision. -struct timespec -{ - time_t tv_sec; - long tv_nsec; -}; - -#define CLOCKS_PER_SEC 10000000 // Number of clock_t per second. - -#define CLOCK_REALTIME 0 -#define CLOCK_MONOTONIC 1 -#define CLOCK_PROCTIME 2 - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Returns a number representing how much CPU time has been used by this process. Divide this by CLOCKS_PER_SEC to - * get the value in seconds. */ - clock_t clock(void); - - /* Returns the current UNIX time in seconds, which is also stored in tloc if it is nonnull. */ - time_t time(time_t* tloc); - - /* Retrieves precise time from a specific system clock. */ - int clock_gettime(clockid_t clock_id, struct timespec* tp); - - /* Converts the UNIX timestamp time to broken-down time in UTC. */ - struct tm* gmtime(const time_t* time); - - /* Converts the UNIX timestamp time to broken-down time in UTC. Thread-safe. */ - struct tm* gmtime_r(const time_t* time, struct tm* result); - - /* Converts the UNIX timestamp time to broken-down time in local time. */ - struct tm* localtime(const time_t* time); - - /* Converts the UNIX timestamp time to broken-down time in local time. Thread-safe. */ - struct tm* localtime_r(const time_t* time, struct tm* result); - - /* Returns a string representation of the broken-down time in the time structure. */ - char* asctime(const struct tm* time); - - /* Fills buf with the string representation of the broken-down time in the time structure. Thread-safe. */ - char* asctime_r(const struct tm* time, char buf[26]); - - /* Returns a string representation of time. */ - char* ctime(const time_t* time); - - /* Fills buf with a string representation of time. Thread-safe. */ - char* ctime_r(const time_t* time, char buf[26]); - - /* Returns the UNIX timestamp representation of the broken-down time in the time structure. */ - time_t mktime(struct tm* time); - - /* Fills str with a formatted string representation of time according to the format string. */ - size_t strftime(char* str, size_t max, const char* format, const struct tm* time); - - /* Returns the difference between two times. */ - double difftime(time_t time2, time_t time1); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/unistd.h b/libs/libc/include/unistd.h deleted file mode 100644 index aaa87201..00000000 --- a/libs/libc/include/unistd.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef _UNISTD_H -#define _UNISTD_H - -#include -#include -#include -#include - -// Standard IO streams. -#define STDIN_FILENO 0 // The standard input stream. -#define STDOUT_FILENO 1 // The standard output stream. -#define STDERR_FILENO 2 // The standard error stream. - -// Possible arguments to access() -#define F_OK 0 // Check for a file's existence. -#define R_OK 1 // Check whether a file is readable. -#define W_OK 2 // Check whether a file is writable. -#define X_OK 4 // Check whether a file is executable. - -// Name values for pathconf() -#define _PC_PATH_MAX 0 // Maximum length of a path relative to the provided name. - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Executes the program program, passing the arguments in the argument list argv. On success, does not return. */ - int execv(const char* program, char* const argv[]); - - /* Not implemented. */ - int execve(const char*, char* const[], char* const[]); - /* Not implemented. */ - int execvp(const char*, char* const[]); - - /* Creates an identical copy (child) of the current process (parent). Returns 0 to the child, and the child's PID to - * the parent. */ - pid_t fork(void); - - /* Returns the current process' process ID. */ - pid_t getpid(void); - - /* Returns the current process' parent's process ID. */ - pid_t getppid(void); - - /* Returns the current process' real user ID. */ - uid_t getuid(void); - - /* Returns the current process' effective user ID. */ - uid_t geteuid(void); - - /* Returns the current process' real group ID. */ - gid_t getgid(void); - - /* Returns the current process' effective group ID. */ - gid_t getegid(void); - - /* Sets the current process' real and effective user IDs. */ - int setuid(uid_t uid); - - /* Sets the current process' effective user ID. */ - int seteuid(uid_t euid); - - /* Sets the current process' real and effective group IDs. */ - int setgid(gid_t gid); - - /* Sets the current process' effective group ID. */ - int setegid(gid_t egid); - - /* Terminates the program with the status code status. */ - __lc_noreturn void _exit(int status); - - /* Calls the kernel for a specific service, determined by number. */ - long syscall(long number, ...); - - /* Suspends execution for a chosen amount of seconds. */ - unsigned int sleep(unsigned int seconds); - - /* Reads count bytes from the file descriptor fd into the memory at buf. */ - ssize_t read(int fd, void* buf, size_t count); - - /* Writes count bytes of the memory at buf to the file descriptor fd. */ - ssize_t write(int fd, const void* buf, size_t count); - - /* Closes the file descriptor fd. */ - int close(int fd); - - /* Moves the read/write file offset for fd to offset, depending on whence. */ - off_t lseek(int fd, off_t offset, int whence); - - /* Returns a copy of the file descriptor fd. */ - int dup(int fd); - - /* Causes the file descriptor fd2 to refer to the file descriptor fd. */ - int dup2(int fd, int fd2); - - /* Checks if the current program can access the file or directory at path. */ - int access(const char* path, int amode); - - /* Checks if the file descriptor fd refers to a terminal. */ - int isatty(int fd); - - /* Writes the current process's current working directory to buf. */ - char* getcwd(char* buf, size_t size); - - int unlink(const char* path); // Not implemented. - int rmdir(const char* path); // Not implemented. - int chdir(const char* path); // Not implemented. - int pipe(int fd[2]); // Not implemented. - - /* Returns a configuration value for the file at path. */ - long pathconf(const char* path, int name); - - /* Returns the maximum number of file descriptors a process can have open at the same time. */ - int getdtablesize(void); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/utime.h b/libs/libc/include/utime.h deleted file mode 100644 index 6111ecdb..00000000 --- a/libs/libc/include/utime.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _UTIME_H -#define _UTIME_H - -#include - -struct utimbuf -{ - time_t actime; - time_t modtime; -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - - int utime(const char*, const struct utimbuf*); // Not implemented. - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/include/wchar.h b/libs/libc/include/wchar.h deleted file mode 100644 index a206751e..00000000 --- a/libs/libc/include/wchar.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _WCHAR_H -#define _WCHAR_H - -#include -#include - -typedef unsigned int wint_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Return the length of a wide-character string. */ - size_t wcslen(const wchar_t* str); - - /* Concatenates the wide-character string src into dest. */ - __lc_is_deprecated wchar_t* wcscat(wchar_t* dest, const wchar_t* src); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/libs/libc/src/assert.cpp b/libs/libc/src/assert.cpp deleted file mode 100644 index c0c64a1c..00000000 --- a/libs/libc/src/assert.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include - -extern "C" -{ - __lc_noreturn bool __assertion_failed(const char* file, int line, const char* function, const char* expr) - { - fprintf(stderr, "%s:%d: %s: Assertion '%s' failed.", file, line, function, expr); - abort(); - } -} \ No newline at end of file diff --git a/libs/libc/src/atexit.cpp b/libs/libc/src/atexit.cpp deleted file mode 100644 index a27b81f2..00000000 --- a/libs/libc/src/atexit.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#define ATEXIT_MAX_FUNCS 32 - -typedef void (*atexit_func_t)(void); - -atexit_func_t atexit_functions[ATEXIT_MAX_FUNCS]; -int atexit_function_count = 0; - -extern "C" -{ - int atexit(atexit_func_t handler) - { - if (atexit_function_count >= ATEXIT_MAX_FUNCS) return -1; - atexit_functions[atexit_function_count++] = handler; - return 0; - } - - __lc_noreturn void exit(int status) - { - for (int i = 0; i < atexit_function_count; i++) { atexit_functions[i](); } - _exit(status); - } -} \ No newline at end of file diff --git a/libs/libc/src/bits/bindings.c b/libs/libc/src/bits/bindings.c deleted file mode 100644 index 40bdca95..00000000 --- a/libs/libc/src/bits/bindings.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -int liballoc_lock() -{ - return 0; -} - -int liballoc_unlock() -{ - return 0; -} - -void* liballoc_alloc(size_t size) -{ - void* result = mmap(NULL, size * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); - if (result == MAP_FAILED) return 0; - return (void*)result; -} - -int liballoc_free(void* address, size_t size) -{ - return munmap(address, size * PAGE_SIZE); -} \ No newline at end of file diff --git a/libs/libc/src/bits/liballoc.c b/libs/libc/src/bits/liballoc.c deleted file mode 100644 index e5bdabef..00000000 --- a/libs/libc/src/bits/liballoc.c +++ /dev/null @@ -1,748 +0,0 @@ -#include - -#pragma GCC push_options -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" // FIXME: Actually solve these warnings. - -#include -#include - -/** Durand's Amazing Super Duper Memory functions. */ - -#define VERSION "1.1" -#define ALIGNMENT \ - 16ul // 4ul ///< This is the byte alignment that memory must be allocated on. IMPORTANT for GTK and - // other stuff. - -#define ALIGN_TYPE char /// unsigned char[16] /// unsigned short -#define ALIGN_INFO \ - sizeof(ALIGN_TYPE) * 16 ///< Alignment information is stored right before the pointer. This is the number of bytes - ///< of information stored there. - -#define USE_CASE1 -#define USE_CASE2 -#define USE_CASE3 -#define USE_CASE4 -#define USE_CASE5 - -/** This macro will conveniently align our pointer upwards */ -#define ALIGN(ptr) \ - if (ALIGNMENT > 1) \ - { \ - uintptr_t align_diff; \ - ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \ - align_diff = (uintptr_t)ptr & (ALIGNMENT - 1); \ - if (align_diff != 0) \ - { \ - align_diff = ALIGNMENT - align_diff; \ - ptr = (void*)((uintptr_t)ptr + align_diff); \ - } \ - *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = align_diff + ALIGN_INFO; \ - } - -#define UNALIGN(ptr) \ - if (ALIGNMENT > 1) \ - { \ - uintptr_t align_diff = *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)); \ - if (align_diff < (ALIGNMENT + ALIGN_INFO)) { ptr = (void*)((uintptr_t)ptr - align_diff); } \ - } - -#define LIBALLOC_MAGIC 0xc001c0de -#define LIBALLOC_DEAD 0xdeaddead - -#if defined DEBUG || defined INFO -#include -#include - -#define FLUSH() fflush(stdout) - -#endif - -/** A structure found at the top of all system allocated - * memory blocks. It details the usage of the memory block. - */ -struct liballoc_major -{ - struct liballoc_major* prev; ///< Linked list information. - struct liballoc_major* next; ///< Linked list information. - unsigned int pages; ///< The number of pages in the block. - unsigned int size; ///< The number of pages in the block. - unsigned int usage; ///< The number of bytes used in the block. - struct liballoc_minor* first; ///< A pointer to the first allocated memory in the block. -}; - -/** This is a structure found at the beginning of all - * sections in a major block which were allocated by a - * malloc, calloc, realloc call. - */ -struct liballoc_minor -{ - struct liballoc_minor* prev; ///< Linked list information. - struct liballoc_minor* next; ///< Linked list information. - struct liballoc_major* block; ///< The owning block. A pointer to the major structure. - unsigned int magic; ///< A magic number to idenfity correctness. - unsigned int size; ///< The size of the memory allocated. Could be 1 byte or more. - unsigned int req_size; ///< The size of memory requested. -}; - -static struct liballoc_major* l_memRoot = NULL; ///< The root memory block acquired from the system. -static struct liballoc_major* l_bestBet = NULL; ///< The major with the most free memory. - -static unsigned int l_pageSize = 4096; ///< The size of an individual page. Set up in liballoc_init. -static unsigned int l_pageCount = 16; ///< The number of pages to request per chunk. Set up in liballoc_init. -static unsigned long long l_allocated = 0; ///< Running total of allocated memory. -static unsigned long long l_inuse = 0; ///< Running total of used memory. - -static long long l_warningCount = 0; ///< Number of warnings encountered -static long long l_errorCount = 0; ///< Number of actual errors -static long long l_possibleOverruns = 0; ///< Number of possible overruns - -// *********** HELPER FUNCTIONS ******************************* - -static void* liballoc_memset(void* s, int c, size_t n) -{ - unsigned int i; - for (i = 0; i < n; i++) ((char*)s)[i] = c; - - return s; -} -static void* liballoc_memcpy(void* s1, const void* s2, size_t n) -{ - char* cdest; - const char* csrc; - unsigned int* ldest = (unsigned int*)s1; - const unsigned int* lsrc = (const unsigned int*)s2; - - while (n >= sizeof(unsigned int)) - { - *ldest++ = *lsrc++; - n -= sizeof(unsigned int); - } - - cdest = (char*)ldest; - csrc = (const char*)lsrc; - - while (n > 0) - { - *cdest++ = *csrc++; - n -= 1; - } - - return s1; -} - -#if defined DEBUG || defined INFO -static void liballoc_dump() -{ -#ifdef DEBUG - struct liballoc_major* maj = l_memRoot; - struct liballoc_minor* min = NULL; -#endif - - printf("liballoc: ------ Memory data ---------------\n"); - printf("liballoc: System memory allocated: %i bytes\n", l_allocated); - printf("liballoc: Memory in used (malloc'ed): %i bytes\n", l_inuse); - printf("liballoc: Warning count: %i\n", l_warningCount); - printf("liballoc: Error count: %i\n", l_errorCount); - printf("liballoc: Possible overruns: %i\n", l_possibleOverruns); - -#ifdef DEBUG - while (maj != NULL) - { - printf("liballoc: %x: total = %i, used = %i\n", maj, maj->size, maj->usage); - - min = maj->first; - while (min != NULL) - { - printf("liballoc: %x: %i bytes\n", min, min->size); - min = min->next; - } - - maj = maj->next; - } -#endif - - FLUSH(); -} -#endif - -// *************************************************************** - -static struct liballoc_major* allocate_new_page(unsigned int size) -{ - unsigned int st; - struct liballoc_major* maj; - - // This is how much space is required. - st = size + sizeof(struct liballoc_major); - st += sizeof(struct liballoc_minor); - - // Perfect amount of space? - if ((st % l_pageSize) == 0) st = st / (l_pageSize); - else - st = st / (l_pageSize) + 1; - // No, add the buffer. - - // Make sure it's >= the minimum size. - if (st < l_pageCount) st = l_pageCount; - - maj = (struct liballoc_major*)liballoc_alloc(st); - - if (maj == NULL) - { - l_warningCount += 1; -#if defined DEBUG || defined INFO - printf("liballoc: WARNING: liballoc_alloc( %i ) return NULL\n", st); - FLUSH(); -#endif - return NULL; // uh oh, we ran out of memory. - } - - maj->prev = NULL; - maj->next = NULL; - maj->pages = st; - maj->size = st * l_pageSize; - maj->usage = sizeof(struct liballoc_major); - maj->first = NULL; - - l_allocated += maj->size; - -#ifdef DEBUG - printf("liballoc: Resource allocated %x of %i pages (%i bytes) for %i size.\n", maj, st, maj->size, size); - - printf("liballoc: Total memory usage = %i KB\n", (int)((l_allocated / (1024)))); - FLUSH(); -#endif - - return maj; -} - -void* PREFIX(malloc)(size_t req_size) -{ - int startedBet = 0; - unsigned long long bestSize = 0; - void* p = NULL; - uintptr_t diff; - struct liballoc_major* maj; - struct liballoc_minor* min; - struct liballoc_minor* new_min; - unsigned long size = req_size; - - // For alignment, we adjust size so there's enough space to align. - if (ALIGNMENT > 1) { size += ALIGNMENT + ALIGN_INFO; } - // So, ideally, we really want an alignment of 0 or 1 in order - // to save space. - - liballoc_lock(); - - if (size == 0) - { - l_warningCount += 1; -#if defined DEBUG || defined INFO - printf("liballoc: WARNING: alloc( 0 ) called from %x\n", __builtin_return_address(0)); - FLUSH(); -#endif - liballoc_unlock(); - return PREFIX(malloc)(1); - } - - if (l_memRoot == NULL) - { -#if defined DEBUG || defined INFO -#ifdef DEBUG - printf("liballoc: initialization of liballoc " VERSION "\n"); -#endif - atexit(liballoc_dump); - FLUSH(); -#endif - - // This is the first time we are being used. - l_memRoot = allocate_new_page(size); - if (l_memRoot == NULL) - { - liballoc_unlock(); -#ifdef DEBUG - printf("liballoc: initial l_memRoot initialization failed\n", p); - FLUSH(); -#endif - return NULL; - } - -#ifdef DEBUG - printf("liballoc: set up first memory major %x\n", l_memRoot); - FLUSH(); -#endif - } - -#ifdef DEBUG - printf("liballoc: %x PREFIX(malloc)( %i ): ", __builtin_return_address(0), size); - FLUSH(); -#endif - - // Now we need to bounce through every major and find enough space.... - - maj = l_memRoot; - startedBet = 0; - - // Start at the best bet.... - if (l_bestBet != NULL) - { - bestSize = l_bestBet->size - l_bestBet->usage; - - if (bestSize > (size + sizeof(struct liballoc_minor))) - { - maj = l_bestBet; - startedBet = 1; - } - } - - while (maj != NULL) - { - diff = maj->size - maj->usage; - // free memory in the block - - if (bestSize < diff) - { - // Hmm.. this one has more memory then our bestBet. Remember! - l_bestBet = maj; - bestSize = diff; - } - -#ifdef USE_CASE1 - - // CASE 1: There is not enough space in this major block. - if (diff < (size + sizeof(struct liballoc_minor))) - { -#ifdef DEBUG - printf("CASE 1: Insufficient space in block %x\n", maj); - FLUSH(); -#endif - - // Another major block next to this one? - if (maj->next != NULL) - { - maj = maj->next; // Hop to that one. - continue; - } - - if (startedBet == 1) // If we started at the best bet, - { // let's start all over again. - maj = l_memRoot; - startedBet = 0; - continue; - } - - // Create a new major block next to this one and... - maj->next = allocate_new_page(size); // next one will be okay. - if (maj->next == NULL) break; // no more memory. - maj->next->prev = maj; - maj = maj->next; - - // .. fall through to CASE 2 .. - } - -#endif - -#ifdef USE_CASE2 - - // CASE 2: It's a brand new block. - if (maj->first == NULL) - { - maj->first = (struct liballoc_minor*)((uintptr_t)maj + sizeof(struct liballoc_major)); - - maj->first->magic = LIBALLOC_MAGIC; - maj->first->prev = NULL; - maj->first->next = NULL; - maj->first->block = maj; - maj->first->size = size; - maj->first->req_size = req_size; - maj->usage += size + sizeof(struct liballoc_minor); - - l_inuse += size; - - p = (void*)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor)); - - ALIGN(p); - -#ifdef DEBUG - printf("CASE 2: returning %x\n", p); - FLUSH(); -#endif - liballoc_unlock(); // release the lock - return p; - } - -#endif - -#ifdef USE_CASE3 - - // CASE 3: Block in use and enough space at the start of the block. - diff = (uintptr_t)(maj->first); - diff -= (uintptr_t)maj; - diff -= sizeof(struct liballoc_major); - - if (diff >= (size + sizeof(struct liballoc_minor))) - { - // Yes, space in front. Squeeze in. - maj->first->prev = (struct liballoc_minor*)((uintptr_t)maj + sizeof(struct liballoc_major)); - maj->first->prev->next = maj->first; - maj->first = maj->first->prev; - - maj->first->magic = LIBALLOC_MAGIC; - maj->first->prev = NULL; - maj->first->block = maj; - maj->first->size = size; - maj->first->req_size = req_size; - maj->usage += size + sizeof(struct liballoc_minor); - - l_inuse += size; - - p = (void*)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor)); - ALIGN(p); - -#ifdef DEBUG - printf("CASE 3: returning %x\n", p); - FLUSH(); -#endif - liballoc_unlock(); // release the lock - return p; - } - -#endif - -#ifdef USE_CASE4 - - // CASE 4: There is enough space in this block. But is it contiguous? - min = maj->first; - - // Looping within the block now... - while (min != NULL) - { - // CASE 4.1: End of minors in a block. Space from last and end? - if (min->next == NULL) - { - // the rest of this block is free... is it big enough? - diff = (uintptr_t)(maj) + maj->size; - diff -= (uintptr_t)min; - diff -= sizeof(struct liballoc_minor); - diff -= min->size; - // minus already existing usage.. - - if (diff >= (size + sizeof(struct liballoc_minor))) - { - // yay.... - min->next = (struct liballoc_minor*)((uintptr_t)min + sizeof(struct liballoc_minor) + min->size); - min->next->prev = min; - min = min->next; - min->next = NULL; - min->magic = LIBALLOC_MAGIC; - min->block = maj; - min->size = size; - min->req_size = req_size; - maj->usage += size + sizeof(struct liballoc_minor); - - l_inuse += size; - - p = (void*)((uintptr_t)min + sizeof(struct liballoc_minor)); - ALIGN(p); - -#ifdef DEBUG - printf("CASE 4.1: returning %x\n", p); - FLUSH(); -#endif - liballoc_unlock(); // release the lock - return p; - } - } - - // CASE 4.2: Is there space between two minors? - if (min->next != NULL) - { - // is the difference between here and next big enough? - diff = (uintptr_t)(min->next); - diff -= (uintptr_t)min; - diff -= sizeof(struct liballoc_minor); - diff -= min->size; - // minus our existing usage. - - if (diff >= (size + sizeof(struct liballoc_minor))) - { - // yay...... - new_min = (struct liballoc_minor*)((uintptr_t)min + sizeof(struct liballoc_minor) + min->size); - - new_min->magic = LIBALLOC_MAGIC; - new_min->next = min->next; - new_min->prev = min; - new_min->size = size; - new_min->req_size = req_size; - new_min->block = maj; - min->next->prev = new_min; - min->next = new_min; - maj->usage += size + sizeof(struct liballoc_minor); - - l_inuse += size; - - p = (void*)((uintptr_t)new_min + sizeof(struct liballoc_minor)); - ALIGN(p); - -#ifdef DEBUG - printf("CASE 4.2: returning %x\n", p); - FLUSH(); -#endif - - liballoc_unlock(); // release the lock - return p; - } - } // min->next != NULL - - min = min->next; - } // while min != NULL ... - -#endif - -#ifdef USE_CASE5 - - // CASE 5: Block full! Ensure next block and loop. - if (maj->next == NULL) - { -#ifdef DEBUG - printf("CASE 5: block full\n"); - FLUSH(); -#endif - - if (startedBet == 1) - { - maj = l_memRoot; - startedBet = 0; - continue; - } - - // we've run out. we need more... - maj->next = allocate_new_page(size); // next one guaranteed to be okay - if (maj->next == NULL) break; // uh oh, no more memory..... - maj->next->prev = maj; - } - -#endif - - maj = maj->next; - } // while (maj != NULL) - - liballoc_unlock(); // release the lock - -#ifdef DEBUG - printf("All cases exhausted. No memory available.\n"); - FLUSH(); -#endif -#if defined DEBUG || defined INFO - printf("liballoc: WARNING: PREFIX(malloc)( %i ) returning NULL.\n", size); - liballoc_dump(); - FLUSH(); -#endif - return NULL; -} - -void PREFIX(free)(void* ptr) -{ - struct liballoc_minor* min; - struct liballoc_major* maj; - - if (ptr == NULL) - { - l_warningCount += 1; -#if defined DEBUG || defined INFO - printf("liballoc: WARNING: PREFIX(free)( NULL ) called from %x\n", __builtin_return_address(0)); - FLUSH(); -#endif - return; - } - - UNALIGN(ptr); - - liballoc_lock(); // lockit - - min = (struct liballoc_minor*)((uintptr_t)ptr - sizeof(struct liballoc_minor)); - - if (min->magic != LIBALLOC_MAGIC) - { - l_errorCount += 1; - - // Check for overrun errors. For all bytes of LIBALLOC_MAGIC - if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) || - ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) || ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) - { - l_possibleOverruns += 1; -#if defined DEBUG || defined INFO - printf("liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n", min->magic, LIBALLOC_MAGIC); - FLUSH(); -#endif - } - - if (min->magic == LIBALLOC_DEAD) - { -#if defined DEBUG || defined INFO - printf("liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n", ptr, - __builtin_return_address(0)); - FLUSH(); -#endif - } - else - { -#if defined DEBUG || defined INFO - printf("liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n", ptr, __builtin_return_address(0)); - FLUSH(); -#endif - } - - // being lied to... - liballoc_unlock(); // release the lock - return; - } - -#ifdef DEBUG - printf("liballoc: %x PREFIX(free)( %x ): ", __builtin_return_address(0), ptr); - FLUSH(); -#endif - - maj = min->block; - - l_inuse -= min->size; - - maj->usage -= (min->size + sizeof(struct liballoc_minor)); - min->magic = LIBALLOC_DEAD; // No mojo. - - if (min->next != NULL) min->next->prev = min->prev; - if (min->prev != NULL) min->prev->next = min->next; - - if (min->prev == NULL) maj->first = min->next; - // Might empty the block. This was the first - // minor. - - // We need to clean up after the majors now.... - - if (maj->first == NULL) // Block completely unused. - { - if (l_memRoot == maj) l_memRoot = maj->next; - if (l_bestBet == maj) l_bestBet = NULL; - if (maj->prev != NULL) maj->prev->next = maj->next; - if (maj->next != NULL) maj->next->prev = maj->prev; - l_allocated -= maj->size; - - liballoc_free(maj, maj->pages); - } - else - { - if (l_bestBet != NULL) - { - int bestSize = l_bestBet->size - l_bestBet->usage; - int majSize = maj->size - maj->usage; - - if (majSize > bestSize) l_bestBet = maj; - } - } - -#ifdef DEBUG - printf("OK\n"); - FLUSH(); -#endif - - liballoc_unlock(); // release the lock -} - -void* PREFIX(calloc)(size_t nobj, size_t size) -{ - int real_size; - void* p; - - real_size = nobj * size; - - p = PREFIX(malloc)(real_size); - - liballoc_memset(p, 0, real_size); - - return p; -} - -void* PREFIX(realloc)(void* p, size_t size) -{ - void* ptr; - struct liballoc_minor* min; - unsigned int real_size; - - // Honour the case of size == 0 => free old and return NULL - if (size == 0) - { - PREFIX(free)(p); - return NULL; - } - - // In the case of a NULL pointer, return a simple malloc. - if (p == NULL) return PREFIX(malloc)(size); - - // Unalign the pointer if required. - ptr = p; - UNALIGN(ptr); - - liballoc_lock(); // lockit - - min = (struct liballoc_minor*)((uintptr_t)ptr - sizeof(struct liballoc_minor)); - - // Ensure it is a valid structure. - if (min->magic != LIBALLOC_MAGIC) - { - l_errorCount += 1; - - // Check for overrun errors. For all bytes of LIBALLOC_MAGIC - if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) || - ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) || ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) - { - l_possibleOverruns += 1; -#if defined DEBUG || defined INFO - printf("liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n", min->magic, LIBALLOC_MAGIC); - FLUSH(); -#endif - } - - if (min->magic == LIBALLOC_DEAD) - { -#if defined DEBUG || defined INFO - printf("liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n", ptr, - __builtin_return_address(0)); - FLUSH(); -#endif - } - else - { -#if defined DEBUG || defined INFO - printf("liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n", ptr, __builtin_return_address(0)); - FLUSH(); -#endif - } - - // being lied to... - liballoc_unlock(); // release the lock - return NULL; - } - - // Definitely a memory block. - - real_size = min->req_size; - - if (real_size >= size) - { - min->req_size = size; - liballoc_unlock(); - return p; - } - - liballoc_unlock(); - - // If we got here then we're reallocating to a block bigger than us. - ptr = PREFIX(malloc)(size); // We need to allocate new memory - liballoc_memcpy(ptr, p, real_size); - PREFIX(free)(p); - - return ptr; -} - -#pragma GCC pop_options diff --git a/libs/libc/src/ctype.cpp b/libs/libc/src/ctype.cpp deleted file mode 100644 index 8610ce6b..00000000 --- a/libs/libc/src/ctype.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include - -extern "C" -{ - int isalnum(int c) - { - return isalpha(c) || isdigit(c); - } - - int isalpha(int c) - { - return islower(c) || isupper(c); - } - - int isascii(int c) - { - return !(c & ~0x7f); - } - - int isblank(int c) - { - return c == ' ' || c == '\t'; - } - - int iscntrl(int c) - { - return (unsigned int)c < 0x20 || c == 0x7f; - } - - int isdigit(int c) - { - return c >= '0' && c < ':'; - } - - int isgraph(int c) - { - return (unsigned int)c - 0x21 < 0x5e; - } - - int islower(int c) - { - return c >= 'a' && c < '{'; - } - - int isprint(int c) - { - return (unsigned int)c - 0x20 < 0x5f; - } - - int ispunct(int c) - { - return isgraph(c) && !isalnum(c); - } - - int isspace(int c) - { - return c == ' ' || (unsigned int)c - '\t' < 5; - } - - int isupper(int c) - { - return c >= 'A' && c < '['; - } - - int isxdigit(int c) - { - return isdigit(c) || ((unsigned int)c | 32) - 'a' < 6; - } - - int tolower(int c) - { - if (isupper(c)) return c | 32; - return c; - } - - int toupper(int c) - { - if (islower(c)) return c & 0x5f; - return c; - } - - int toascii(int c) - { - return c & 0x7f; - } -} \ No newline at end of file diff --git a/libs/libc/src/cxxabi.cpp b/libs/libc/src/cxxabi.cpp deleted file mode 100644 index 47734a45..00000000 --- a/libs/libc/src/cxxabi.cpp +++ /dev/null @@ -1,50 +0,0 @@ -typedef void* (*cxa_atexit_func_t)(void*); - -struct cxa_atexit_entry -{ - cxa_atexit_func_t function; - void* argument; - void* dso_handle; -}; - -#define CXA_ATEXIT_MAX 64 - -int cxa_atexit_entry_count = 0; - -cxa_atexit_entry cxa_atexit_entries[CXA_ATEXIT_MAX]; - -extern "C" -{ - int __cxa_atexit(cxa_atexit_func_t func, void* arg, void* dso) - { - if (cxa_atexit_entry_count >= CXA_ATEXIT_MAX) return -1; - cxa_atexit_entries[cxa_atexit_entry_count].function = func; - cxa_atexit_entries[cxa_atexit_entry_count].argument = arg; - cxa_atexit_entries[cxa_atexit_entry_count].dso_handle = dso; - cxa_atexit_entry_count++; - return 0; - } - - void __cxa_finalize(void* f) - { - int i = cxa_atexit_entry_count; - if (!f) - { - while (i--) - { - if (cxa_atexit_entries[i].function) { cxa_atexit_entries[i].function(cxa_atexit_entries[i].argument); } - } - } - else - { - while (i--) - { - if (cxa_atexit_entries[i].function == (cxa_atexit_func_t)f) - { - cxa_atexit_entries[i].function(cxa_atexit_entries[i].argument); - cxa_atexit_entries[i].function = 0; - } - } - } - } -} \ No newline at end of file diff --git a/libs/libc/src/dirent.cpp b/libs/libc/src/dirent.cpp deleted file mode 100644 index 48523a19..00000000 --- a/libs/libc/src/dirent.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern "C" -{ - DIR* opendir(const char* path) - { - int fd = open(path, O_RDONLY | O_DIRECTORY); - if (fd < 0) return NULL; - return fdopendir(fd); - } - - DIR* fdopendir(int fd) - { - if (fd < 0) return NULL; - DIR* result = (DIR*)malloc(sizeof(DIR)); - if (!result) return NULL; - result->d_dirfd = fd; - return result; - } - - int closedir(DIR* stream) - { - int status = close(stream->d_dirfd); - if (status < 0) - { - int savederr = errno; - free(stream); - errno = savederr; // free might reset errno. We don't want that. - } - else { free(stream); } - return status; - } - - struct dirent* readdir(DIR* stream) - { - static struct dirent result; - struct luna_dirent ent; - ssize_t nread = getdents(stream->d_dirfd, &ent, 1); // FIXME: Use a buffer to avoid too many system calls. - if (nread <= 0) return NULL; // Either EOF or error. - result.d_ino = ent.inode; - result.d_reclen = sizeof(result); - result.d_off = ent.offset; - result.d_type = DT_UNKNOWN; - strlcpy(result.d_name, ent.name, NAME_MAX); - return &result; - } - - int dirfd(DIR* stream) - { - return stream->d_dirfd; - } - - void rewinddir(DIR* stream) - { - lseek(stream->d_dirfd, 0, SEEK_SET); - } - - long telldir(DIR* stream) - { - return lseek(stream->d_dirfd, 0, SEEK_CUR); - } - - void seekdir(DIR* stream, long offset) - { - lseek(stream->d_dirfd, offset, SEEK_SET); - } -} \ No newline at end of file diff --git a/libs/libc/src/errno.cpp b/libs/libc/src/errno.cpp deleted file mode 100644 index ccd33dd5..00000000 --- a/libs/libc/src/errno.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include - -int errno; -char* program_invocation_name; \ No newline at end of file diff --git a/libs/libc/src/fcntl.cpp b/libs/libc/src/fcntl.cpp deleted file mode 100644 index c6a7d64d..00000000 --- a/libs/libc/src/fcntl.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -extern "C" -{ - int open(const char* pathname, int flags, ...) - { - va_list ap; - va_start(ap, flags); - long result = __lc_fast_syscall3(SYS_open, pathname, flags, va_arg(ap, unsigned int)); - va_end(ap); - return (int)result; - } - - int creat(const char* pathname, mode_t mode) - { - return (int)__lc_fast_syscall3(SYS_open, pathname, O_WRONLY | O_CREAT | O_TRUNC, - mode); // we don't need to pass this through to open(), we can avoid variadic - // stuff since we're sure mode exists. - } - - int fcntl(int fd, int cmd, ...) - { - va_list ap; - va_start(ap, cmd); - long result = __lc_fast_syscall3(SYS_fcntl, fd, cmd, va_arg(ap, uintptr_t)); - va_end(ap); - return (int)result; - } -} \ No newline at end of file diff --git a/libs/libc/src/file.cpp b/libs/libc/src/file.cpp deleted file mode 100644 index d686d8da..00000000 --- a/libs/libc/src/file.cpp +++ /dev/null @@ -1,305 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -FILE* stderr; -FILE* stdout; -FILE* stdin; - -static void file_read_buf(FILE* stream) -{ - if (!stream->f_buf) - { - stream->f_buf = (char*)malloc(BUFSIZ); // FIXME: Handle errors. - stream->f_bufrsize = BUFSIZ; - } - stream->f_bufoff = 0; - ssize_t nread = read(stream->f_fd, stream->f_buf, stream->f_bufrsize); - if (nread < 0) - { - stream->f_err = 1; - return; - } - if (nread == 0) - { - stream->f_eof = 1; - return; - } - stream->f_bufsize = nread; -} - -static int file_parse_mode(const char* mode) -{ - int flags = 0; - switch (mode[0]) - { - case 'r': flags |= O_RDONLY; break; - case 'w': - flags |= O_WRONLY; - flags |= O_CREAT; - flags |= O_TRUNC; - break; - case 'a': - flags |= O_WRONLY; - flags |= O_CREAT; - flags |= O_APPEND; - break; - default: errno = EINVAL; return -1; - } - - if (strchr(mode, '+')) flags |= O_RDWR; - return flags; -} - -extern "C" -{ - int fclose(FILE* stream) - { - if (stream->f_buf) free(stream->f_buf); - int status = close(stream->f_fd); - if (status < 0) - { - int savederr = errno; - free(stream); // We do not want to leak memory. man fclose(3) says that whether fclose() fails or not, any - // further operation on the stream results in undefined behavior. So we are free to free the - // stream. - errno = savederr; // free might reset errno. We don't want that. - } - else { free(stream); } - return status; - } - - int fflush(FILE*) - { - return 0; // FIXME: Implement buffered IO. - } - - FILE* fopen(const char* pathname, const char* mode) - { - int flags = file_parse_mode(mode); - if (flags < 0) return NULL; - int fd = open(pathname, flags, 0666); // If we create the file, create it as rw-rw-rw-. - if (fd < 0) { return 0; } - return fdopen(fd, mode); - } - - FILE* fdopen(int fd, const char*) - { - if (fd < 0) // FIXME: Also check if the mode string is compatible with how fd was opened. - { - errno = EBADF; - return 0; - } - FILE* stream = (FILE*)malloc(sizeof(FILE)); - if (!stream) { return 0; } - stream->f_fd = fd; - clearerr(stream); - stream->f_buf = 0; - stream->f_bufoff = 0; - stream->f_bufsize = 0; - return stream; - } - - FILE* freopen(const char* pathname, const char* mode, - FILE* stream) // FIXME: If pathname is NULL, open the original file with the new mode. - { - int flags = file_parse_mode(mode); - if (flags < 0) return NULL; - int fd = open(pathname, flags, 0666); // If we create the file, create it as rw-rw-rw-. - if (fd < 0) { return 0; } - - fflush(stream); // To make it future-proof. - fclose(stream); - - stream->f_fd = fd; - clearerr(stream); - return stream; - } - - int fileno(FILE* stream) - { - return stream->f_fd; - } - - size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream) - { - size_t rsize = size * nmemb; - ssize_t status = read(stream->f_fd, buf, rsize); - if (status < 0) - { - stream->f_err = 1; - return 0; - } - if (status == 0 && rsize) stream->f_eof = 1; - if (status == 0) return (size_t)status; - return (size_t)status / size; - } - - char* fgets(char* buf, int size, FILE* stream) - { - char* s = buf; - int original_size = size; - while (size > 1) - { - if (stream->f_bufoff < stream->f_bufsize) - { - *buf = *(stream->f_buf + stream->f_bufoff); - stream->f_bufoff++; - if (*buf == '\n') - { - buf++; - break; - } - if (*buf == '\b') - { - if (size != original_size) - { - buf--; - size++; - } - } - else - { - buf++; - size--; - } - } - else - { - file_read_buf(stream); - if (ferror(stream)) return NULL; - if (feof(stream)) break; - } - } - if (size == original_size && feof(stream)) return NULL; // EOF while reading the first character - *buf = 0; - return s; - } - - int fgetc(FILE* stream) - { - char result; - read: - if (stream->f_bufoff < stream->f_bufsize) - { - result = *(stream->f_buf + stream->f_bufoff); - stream->f_bufoff++; - } - else - { - file_read_buf(stream); - if (ferror(stream)) return EOF; - if (feof(stream)) return EOF; - goto read; - } - return (int)result; - } - - int getc(FILE* stream) - { - return fgetc(stream); - } - - int getchar() - { - return fgetc(stdin); - } - - int ungetc(int c, FILE* stream) - { - if (stream->f_bufoff > 0) - { - stream->f_bufoff--; - stream->f_buf[stream->f_bufoff] = (char)c; - return c; - } - else - { - return EOF; // FIXME: Handle this case properly. - } - } - - int ferror(FILE* stream) - { - return stream->f_err; - } - - int feof(FILE* stream) - { - return stream->f_eof; - } - - void clearerr(FILE* stream) - { - stream->f_err = stream->f_eof = 0; - } - - int fseek(FILE* stream, long offset, int whence) - { - long result = lseek(stream->f_fd, offset, whence); - if (result < 0) { return -1; } - return 0; - } - - int fseeko(FILE* stream, off_t offset, int whence) - { - return fseek(stream, offset, whence); - } - - int fsetpos(FILE* stream, const fpos_t* pos) - { - return fseek(stream, *pos, SEEK_SET); - } - - long ftell(FILE* stream) - { - return lseek(stream->f_fd, 0, SEEK_CUR); - } - - off_t ftello(FILE* stream) - { - return ftell(stream); - } - - int fgetpos(FILE* stream, fpos_t* pos) - { - long result = ftell(stream); - if (result < 0) { return -1; } - *pos = result; - return 0; - } - - void rewind(FILE* stream) - { - lseek(stream->f_fd, 0, SEEK_SET); - clearerr(stream); - } - - size_t fwrite(const void* buf, size_t size, size_t nmemb, FILE* stream) - { - size_t rsize = size * nmemb; - ssize_t status = write(stream->f_fd, buf, rsize); - if (status < 0) - { - stream->f_err = 1; - return 0; - } - if (status == 0 && rsize) stream->f_eof = 1; - if (status == 0) return (size_t)status; - return (size_t)status / size; - } - - void setbuf(FILE*, char*) - { - NOT_IMPLEMENTED("setbuf"); - } - - int setvbuf(FILE*, char*, int, size_t) - { - NOT_IMPLEMENTED("setvbuf"); - } -} \ No newline at end of file diff --git a/libs/libc/src/init.cpp b/libs/libc/src/init.cpp deleted file mode 100644 index 00a777d4..00000000 --- a/libs/libc/src/init.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include -#include - -char** environ = {nullptr}; - -static void terminate_libc() -{ - fclose(stdout); - fclose(stderr); - fclose(stdin); -} - -static void initialize_random() -{ - unsigned int seed = 3735928559U; - - int fd = open("/dev/random", O_RDONLY | O_CLOEXEC); // If we somehow fail to close this file, close it on exec. - FILE* fp = fdopen(fd, "r"); - if (!fp) - { - errno = 0; - goto failed_to_read_dev_random; - } - - fread(&seed, sizeof(seed), 1, fp); - if (ferror(fp)) - { - errno = 0; - fclose(fp); - goto failed_to_read_dev_random; - } - - fclose(fp); - -failed_to_read_dev_random: - srand(seed); // If we failed, this will be seeded with a known value. Else, it will be seeded with a random value - // from the kernel. - return; -} - -static void check_for_file(int fd, FILE** target_stream, const char* path, const char* mode) -{ - if (lseek(fd, 0, SEEK_CUR) < 0) - { - if (errno == EBADF) *target_stream = fopen(path, mode); - else - exit(-errno); - if (!*target_stream) exit(-errno); - errno = 0; - } - else { *target_stream = fdopen(fd, mode); } -} - -extern char* program_invocation_name; - -extern "C" void initialize_libc(int, char** argv) -{ - check_for_file(STDIN_FILENO, &stdin, "/dev/console", "r"); - check_for_file(STDOUT_FILENO, &stdout, "/dev/console", "a"); - check_for_file(STDERR_FILENO, &stderr, "/dev/console", "a"); - - if (argv) program_invocation_name = argv[0]; - - initialize_random(); - atexit(terminate_libc); -} \ No newline at end of file diff --git a/libs/libc/src/libgen.cpp b/libs/libc/src/libgen.cpp deleted file mode 100644 index c1bcbfc6..00000000 --- a/libs/libc/src/libgen.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include - -static char dot[] = "."; - -extern "C" -{ - char* basename(char* path) - { - // If path is NULL, or the string's length is 0, return . - if (!path) return dot; - size_t len = strlen(path); - if (!len) return dot; - - // Strip trailing slashes. - char* it = path + len - 1; - while (*it == '/' && it != path) { it--; } - *(it + 1) = 0; - if (it == path) return path; - - // Return path from the first character if there are no more slashes, or from the first character after the last - // slash. - char* beg = strrchr(path, '/'); - if (!beg) return path; - return beg + 1; - } - - char* dirname(char* path) - { - // If path is NULL, or the string's length is 0, return . - if (!path) return dot; - size_t len = strlen(path); - if (!len) return dot; - - // Strip trailing slashes. - char* it = path + len - 1; - while (*it == '/' && it != path) { it--; } - *(char*)(it + 1) = 0; - if (it == path) return path; - - // Search for the last slash. If there is none, return . - // Otherwise, we end the string there and return. - char* end = strrchr(path, '/'); - if (!end) return dot; - if (end != path) *end = 0; - else - *(end + 1) = 0; - return path; - } -} \ No newline at end of file diff --git a/libs/libc/src/locale.cpp b/libs/libc/src/locale.cpp deleted file mode 100644 index 656cfa3b..00000000 --- a/libs/libc/src/locale.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include - -static char default_locale[] = "C"; - -static char dot[] = "."; -static char empty[] = ""; - -static struct lconv default_lconv = {dot, empty, empty, empty, empty, empty, - empty, empty, empty, empty, CHAR_MAX, CHAR_MAX, - CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX}; - -extern "C" -{ - char* setlocale(int, const char*) - { - return default_locale; - } - - struct lconv* localeconv(void) - { - return &default_lconv; - } -} \ No newline at end of file diff --git a/libs/libc/src/luna.cpp b/libs/libc/src/luna.cpp deleted file mode 100644 index 48dc1285..00000000 --- a/libs/libc/src/luna.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include -#include -#include -#include - -extern "C" -{ - long getprocid(int field) - { - return __lc_fast_syscall1(SYS_getprocid, field); - } - - unsigned int msleep(unsigned int ms) - { - return (unsigned int)__lc_fast_syscall1(SYS_sleep, ms); - } - - __lc_noreturn void __luna_abort(const char* message) - { - fputs(message, stderr); - abort(); - } -} \ No newline at end of file diff --git a/libs/libc/src/luna/dirent.cpp b/libs/libc/src/luna/dirent.cpp deleted file mode 100644 index 967e2e5b..00000000 --- a/libs/libc/src/luna/dirent.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include -#include - -extern "C" -{ - ssize_t getdents(int fd, struct luna_dirent* buf, size_t count) - { - return __lc_fast_syscall3(SYS_getdents, fd, buf, count); - } -} \ No newline at end of file diff --git a/libs/libc/src/luna/pstat.cpp b/libs/libc/src/luna/pstat.cpp deleted file mode 100644 index 1221b6de..00000000 --- a/libs/libc/src/luna/pstat.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include - -extern "C" -{ - pid_t pstat(pid_t pid, struct pstat* buf) - { - return __lc_fast_syscall2(SYS_pstat, pid, buf); - } - - const char* pstatname(struct pstat* buf) - { - switch (buf->pt_state) - { - case PT_IDLE: return "Idle"; - case PT_RUNNING: return "Running"; - case PT_SLEEPING: return "Sleeping"; - case PT_WAITING: return "Waiting"; - case PT_ZOMBIE: return "Zombie"; - default: return "Unknown"; - } - } -} \ No newline at end of file diff --git a/libs/libc/src/luna/syscall.asm b/libs/libc/src/luna/syscall.asm deleted file mode 100644 index b6c1797c..00000000 --- a/libs/libc/src/luna/syscall.asm +++ /dev/null @@ -1,50 +0,0 @@ -global __luna_syscall0 -__luna_syscall0: - mov rax, rdi - int 0x42 - ret - -global __luna_syscall1 -__luna_syscall1: - mov rax, rdi - mov rdi, rsi - int 0x42 - ret - -global __luna_syscall2 -__luna_syscall2: - mov rax, rdi - mov rdi, rsi - mov rsi, rdx - int 0x42 - ret - -global __luna_syscall3 -__luna_syscall3: - mov rax, rdi - mov rdi, rsi - mov rsi, rdx - mov rdx, rcx - int 0x42 - ret - -global __luna_syscall4 -__luna_syscall4: - mov rax, rdi - mov rdi, rsi - mov rsi, rdx - mov rdx, rcx - mov r10, r8 - int 0x42 - ret - -global __luna_syscall5 -__luna_syscall5: - mov rax, rdi - mov rdi, rsi - mov rsi, rdx - mov rdx, rcx - mov r10, r8 - mov r8, r9 - int 0x42 - ret \ No newline at end of file diff --git a/libs/libc/src/math.cpp b/libs/libc/src/math.cpp deleted file mode 100644 index 52367eb0..00000000 --- a/libs/libc/src/math.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include - -// FIXME: Provide our own definitions instead of relying on the compiler's builtins. - -#define WRAP_AROUND_BUILTIN(name) \ - double name(double val) \ - { \ - return __builtin_##name(val); \ - } \ - float name##f(float val) \ - { \ - return __builtin_##name##f(val); \ - } \ - long double name##l(long double val) \ - { \ - return __builtin_##name##l(val); \ - } - -#define WRAP_AROUND_BUILTIN2(name) \ - double name(double val1, double val2) \ - { \ - return __builtin_##name(val1, val2); \ - } \ - float name##f(float val1, float val2) \ - { \ - return __builtin_##name##f(val1, val2); \ - } \ - long double name##l(long double val1, long double val2) \ - { \ - return __builtin_##name##l(val1, val2); \ - } - -#define WRAP_AROUND_BUILTIN_WITH_PARAMETER_TYPE(name, type) \ - double name(double val1, type val2) \ - { \ - return __builtin_##name(val1, val2); \ - } \ - float name##f(float val1, type val2) \ - { \ - return __builtin_##name##f(val1, val2); \ - } \ - long double name##l(long double val1, type val2) \ - { \ - return __builtin_##name##l(val1, val2); \ - } - -#define WRAP_AROUND_BUILTIN_WITH_POINTER(name) \ - double name(double val1, double* val2) \ - { \ - return __builtin_##name(val1, val2); \ - } \ - float name##f(float val1, float* val2) \ - { \ - return __builtin_##name##f(val1, val2); \ - } \ - long double name##l(long double val1, long double* val2) \ - { \ - return __builtin_##name##l(val1, val2); \ - } - -extern "C" -{ - WRAP_AROUND_BUILTIN(cos); - - WRAP_AROUND_BUILTIN(sin); - - WRAP_AROUND_BUILTIN(tan); - - WRAP_AROUND_BUILTIN(acos); - - WRAP_AROUND_BUILTIN(asin); - - WRAP_AROUND_BUILTIN(atan); - - WRAP_AROUND_BUILTIN(cosh); - - WRAP_AROUND_BUILTIN(sinh); - - WRAP_AROUND_BUILTIN(tanh); - - WRAP_AROUND_BUILTIN(log); - - WRAP_AROUND_BUILTIN(exp); - - WRAP_AROUND_BUILTIN(sqrt); - - WRAP_AROUND_BUILTIN(fabs); - - WRAP_AROUND_BUILTIN(floor); - - WRAP_AROUND_BUILTIN(ceil); - - WRAP_AROUND_BUILTIN(log10); - - WRAP_AROUND_BUILTIN2(fmod); - - WRAP_AROUND_BUILTIN2(pow); - - WRAP_AROUND_BUILTIN2(atan2); - - WRAP_AROUND_BUILTIN_WITH_PARAMETER_TYPE(frexp, int*); - - WRAP_AROUND_BUILTIN_WITH_PARAMETER_TYPE(ldexp, int); - - WRAP_AROUND_BUILTIN_WITH_POINTER(modf); -} \ No newline at end of file diff --git a/libs/libc/src/printf.cpp b/libs/libc/src/printf.cpp deleted file mode 100644 index 3be32613..00000000 --- a/libs/libc/src/printf.cpp +++ /dev/null @@ -1,331 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef long int ssize_t; - -static void printf_strrev(char* arr, int size) -{ - int left = 0; - int right = size - 1; - for (int i = left; i < right; i++) - { - char temp = arr[i]; - arr[i] = arr[right]; - arr[right] = temp; - right--; - } -} - -template static char* printf_unsigned_to_string(IntegerType number, char* arr, int base) -{ - int i = 0; - - if (number == 0) - { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - while (number != 0) - { - IntegerType r = number % (IntegerType)base; - arr[i] = (char)((r > 9) ? (r - 10) + 'a' : r + '0'); - i++; - number /= base; - } - - printf_strrev(arr, i); - - arr[i] = '\0'; - - return arr; -} - -template static char* printf_signed_to_string(IntegerType number, char* arr, int base) -{ - int i = 0, negative = 0; - - if (number == 0) - { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - if (number < 0 && base == 10) - { - number *= -1; - negative = 1; - } - - while (number != 0) - { - IntegerType r = number % base; - arr[i] = (char)((r > 9) ? (r - 10) + 'a' : r + '0'); - i++; - number /= base; - } - - if (negative) - { - arr[i] = '-'; - i++; - } - - printf_strrev(arr, i); - - arr[i] = '\0'; - - return arr; -} - -#pragma GCC push_options -#pragma GCC optimize("O0") - -template -static int internal_printf(const char* format, PutString put_string_callback, ssize_t max, va_list ap) -{ - char buffer[1025]; // 1024 with null terminator - size_t format_size = strlen(format); - size_t format_index = 0; - size_t buffer_insert_index = 0; - ssize_t max_remaining = max; - size_t written = 0; - - auto flush_buffer = [&]() { - size_t buffer_length = buffer_insert_index; - written += buffer_length; - buffer_insert_index = 0; - if (max_remaining < 0) - { - buffer[buffer_length] = 0; - put_string_callback(buffer); - return; - } - if (max_remaining == 0) { return; } - if (buffer_length <= (size_t)max_remaining) - { - max_remaining -= buffer_length; - buffer[buffer_length] = 0; - put_string_callback(buffer); - } - else - { - buffer[max_remaining] = 0; - max_remaining = 0; - put_string_callback(buffer); - } - }; - - auto append_string = [&](const char* str) { - while (strlen(str) > 1024) - { - flush_buffer(); - memcpy(buffer, str, 1024); - str += 1024; - buffer_insert_index = 1024; - } - if (buffer_insert_index + strlen(str) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, str, strlen(str)); - buffer_insert_index += strlen(str); - if (buffer_insert_index == 1024) flush_buffer(); - }; - - auto append_char = [&](char c) { - buffer[buffer_insert_index++] = c; - if (buffer_insert_index == 1024) flush_buffer(); - }; - - bool is_long = false; - bool is_unsigned_long = false; - - bool preserve_format = false; - - while (format_index < format_size) - { - char current_char = format[format_index]; - if (current_char == '%' || preserve_format) - { - if (!preserve_format && format_index + 1 == format_size) // end of format string - { - format_index++; - continue; - } - else - { - if (!preserve_format) format_index++; - preserve_format = false; - current_char = format[format_index]; - switch (current_char) - { - case 'c': { - append_char((char)va_arg(ap, int)); - break; - } - case '%': { - append_char('%'); - break; - } - case 'z': { - is_unsigned_long = true; - preserve_format = true; - break; - } - case 'l': { - is_long = true; - preserve_format = true; - break; - } - case 'i': - case 'd': { - char result[32]; - if (is_unsigned_long) - { - printf_unsigned_to_string(va_arg(ap, uint64_t), result, 10); - is_unsigned_long = is_long = false; - } - else if (is_long) - { - printf_signed_to_string(va_arg(ap, int64_t), result, 10); - is_unsigned_long = is_long = false; - } - else { printf_signed_to_string(va_arg(ap, int32_t), result, 10); } - append_string(result); - break; - } - case 'u': { - char result[32]; - if (is_unsigned_long || is_long) - { - printf_unsigned_to_string(va_arg(ap, uint64_t), result, 10); - is_unsigned_long = is_long = false; - } - else { printf_unsigned_to_string(va_arg(ap, uint32_t), result, 10); } - append_string(result); - break; - } - case 'x': { - char result[32]; - if (is_unsigned_long || is_long) - { - printf_unsigned_to_string(va_arg(ap, uint64_t), result, 16); - is_unsigned_long = is_long = false; - } - else { printf_unsigned_to_string(va_arg(ap, uint32_t), result, 16); } - append_string(result); - break; - } - case 'p': { - char result[32]; - printf_unsigned_to_string(va_arg(ap, uint64_t), result, 16); - append_string(result); - break; - } - case 'm': { - append_string(strerror(errno)); - break; - } - case 's': { - append_string(va_arg(ap, const char*)); - break; - } - default: { - fputs("printf: unknown format specifier ", stderr); - fputc('%', stderr); - fputc(current_char, stderr); - fputc('\n', stderr); - abort(); - } - } - } - } - else { append_char(current_char); } - format_index++; - } - - if (buffer_insert_index > 0) flush_buffer(); - return (int)written; -} - -#pragma GCC pop_options - -extern "C" -{ - int vprintf(const char* format, va_list ap) - { - return vfprintf(stdout, format, ap); - } - - int vsprintf(char* str, const char* format, va_list ap) - { - if (str) *str = 0; // so strncat starts from the beginning - return internal_printf( - format, - [&](const char* s) { - if (str) strncat(str, s, 1025); - }, - -1, ap); - } - - int vsnprintf(char* str, size_t max, const char* format, va_list ap) - { - if (max && str) *str = 0; // so strncat starts from the beginning - return internal_printf( - format, - [&](const char* s) { - if (str) strncat(str, s, 1025); - }, - max == 0 ? 0 : max - 1, ap); - } - - int snprintf(char* str, size_t max, const char* format, ...) - { - va_list ap; - va_start(ap, format); - int written = vsnprintf(str, max, format, ap); - va_end(ap); - return written; - } - - int sprintf(char* str, const char* format, ...) - { - va_list ap; - va_start(ap, format); - int written = vsprintf(str, format, ap); - va_end(ap); - return written; - } - - int printf(const char* format, ...) - { - va_list ap; - va_start(ap, format); - int written = vfprintf(stdout, format, ap); - va_end(ap); - return written; - } - - int fprintf(FILE* stream, const char* format, ...) - { - va_list ap; - va_start(ap, format); - int written = vfprintf(stream, format, ap); - va_end(ap); - return written; - } - - int vfprintf(FILE* stream, const char* format, va_list ap) - { - return internal_printf( - format, [&](const char* s) { fwrite(s, strlen(s), 1, stream); }, -1, ap); - } -} \ No newline at end of file diff --git a/libs/libc/src/pwd.cpp b/libs/libc/src/pwd.cpp deleted file mode 100644 index e33493fb..00000000 --- a/libs/libc/src/pwd.cpp +++ /dev/null @@ -1,196 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static FILE* pwd_file = nullptr; -static FILE* pwnam_file = nullptr; -static FILE* pwuid_file = nullptr; - -static int initialize_pwd(FILE** stream) -{ - int pwfd = open("/etc/passwd", O_RDONLY | O_CLOEXEC); - if (pwfd < 0) return 0; - FILE* file = fdopen(pwfd, "r"); - if (!file) return 0; - *stream = file; - return 1; -} - -static int pwd_unbuffered_fgetc(FILE* stream) -{ - char c; - fread(&c, 1, 1, stream); - if (ferror(stream) || feof(stream)) return EOF; - return (int)c; -} - -static char* pwd_unbuffered_fgets(char* buf, size_t size, FILE* stream) -{ - char* s = buf; - memset(buf, 0, size); - while (size) - { - int c = pwd_unbuffered_fgetc(stream); - if (c == EOF) - { - if (ferror(stream)) return NULL; - if (feof(stream)) - { - if (s != buf) return s; - else - return NULL; - }; - } - size--; - *buf = (char)c; - buf++; - *buf = 0; - if ((char)c == '\n') return s; - } - return s; -} - -static char* pwd_strchrtok(char* s, char delim) -{ - static char* saved = nullptr; - if (s) saved = s; - else - s = saved; - if (!saved) return nullptr; - char* loc = strchr(saved, delim); - if (loc) - { - saved = loc + 1; - if (*saved == 0) saved = nullptr; - *loc = 0; - } - else { saved = nullptr; } - return s; -} - -static void pwd_strip_newline(char* buf) -{ - size_t len = strlen(buf); - if (buf[len - 1] == '\n') buf[len - 1] = 0; -} - -static struct passwd* internal_getpwent(FILE* stream) -{ -#define PWENT_INVALID \ - do { \ - errno = EINVAL; \ - return NULL; \ - } while (0) - - static struct passwd result; - static char buf[BUFSIZ]; - - if (!pwd_unbuffered_fgets(buf, BUFSIZ, stream)) return NULL; - pwd_strip_newline(buf); - result.pw_name = pwd_strchrtok(buf, ':'); - if (!result.pw_name) PWENT_INVALID; - result.pw_passwd = pwd_strchrtok(NULL, ':'); - if (!result.pw_passwd) PWENT_INVALID; - char* uid_string = pwd_strchrtok(NULL, ':'); - if (!uid_string) PWENT_INVALID; - result.pw_uid = atoi(uid_string); - char* gid_string = pwd_strchrtok(NULL, ':'); - if (!gid_string) PWENT_INVALID; - result.pw_gid = atoi(gid_string); - result.pw_gecos = pwd_strchrtok(NULL, ':'); - if (!result.pw_gecos) PWENT_INVALID; - result.pw_dir = pwd_strchrtok(NULL, ':'); - if (!result.pw_dir) PWENT_INVALID; - result.pw_shell = pwd_strchrtok(NULL, ':'); - if (!result.pw_shell) PWENT_INVALID; - return &result; -} - -extern "C" -{ - struct passwd* getpwent() - { - if (!pwd_file) - { - if (!initialize_pwd(&pwd_file)) return NULL; - } - if (feof(pwd_file)) - { - endpwent(); - return NULL; - } - return internal_getpwent(pwd_file); - } - - struct passwd* getpwnam(const char* name) - { - if (!pwnam_file) - { - if (!initialize_pwd(&pwnam_file)) return NULL; - } - else - rewind(pwnam_file); - struct passwd* pwd = internal_getpwent(pwnam_file); - while (pwd) - { - if (strcmp(pwd->pw_name, name) == 0) break; - if (feof(pwnam_file)) - { - pwd = nullptr; - break; - } - pwd = internal_getpwent(pwnam_file); - } - return pwd; // if we matched one, pwd contains a pointer to it. else it is NULL - } - - struct passwd* getpwuid(uid_t uid) - { - if (!pwuid_file) - { - if (!initialize_pwd(&pwuid_file)) return NULL; - } - else - rewind(pwuid_file); - struct passwd* pwd = internal_getpwent(pwuid_file); - while (pwd) - { - if (pwd->pw_uid == uid) break; - if (feof(pwuid_file)) - { - pwd = nullptr; - break; - } - pwd = internal_getpwent(pwuid_file); - } - return pwd; // if we matched one, pwd contains a pointer to it. else it is NULL - } - - void setpwent() - { - if (pwd_file) rewind(pwd_file); - } - - void endpwent() - { - if (pwd_file) - { - fclose(pwd_file); - pwd_file = nullptr; - } - if (pwuid_file) - { - fclose(pwuid_file); - pwuid_file = nullptr; - } - if (pwnam_file) - { - fclose(pwnam_file); - pwnam_file = nullptr; - } - } -} \ No newline at end of file diff --git a/libs/libc/src/rand.cpp b/libs/libc/src/rand.cpp deleted file mode 100644 index 8398928d..00000000 --- a/libs/libc/src/rand.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include -#include -#include - -typedef uint32_t word_t; -#define STATE_SIZE 624 -#define MIDDLE 397 -#define INIT_SHIFT 30 -#define INIT_FACT 1812433253 -#define TWIST_MASK 0x9908b0df -#define SHIFT1 11 -#define MASK1 0xffffffff -#define SHIFT2 7 -#define MASK2 0x9d2c5680 -#define SHIFT3 15 -#define MASK3 0xefc60000 -#define SHIFT4 18 - -#define LOWER_MASK 0x7fffffff -#define UPPER_MASK (~(word_t)LOWER_MASK) - -static word_t state[STATE_SIZE]; -static size_t index = STATE_SIZE + 1; - -static void twist() -{ - for (size_t i = 0; i < STATE_SIZE; i++) - { - word_t x = (state[i] & UPPER_MASK) | (state[(i + 1) % STATE_SIZE] & LOWER_MASK); - x = (x >> 1) ^ (x & 1 ? TWIST_MASK : 0); - state[i] = state[(i + MIDDLE) % STATE_SIZE] ^ x; - } - index = 0; -} - -extern "C" -{ - int rand() - { - if (index >= STATE_SIZE) - { - assert(index == STATE_SIZE && "Mersenne generator was never seeded"); - twist(); - } - - word_t y = state[index]; - y ^= (y >> SHIFT1) & MASK1; - y ^= (y << SHIFT2) & MASK2; - y ^= (y << SHIFT3) & MASK3; - y ^= y >> SHIFT4; - - index++; - return y; - } - - void srand(unsigned int seed) - { - index = STATE_SIZE; - state[0] = seed; - for (size_t i = 1; i < STATE_SIZE; i++) - state[i] = (word_t)((INIT_FACT * (state[i - 1] ^ (state[i - 1] >> INIT_SHIFT))) + i); - } -} \ No newline at end of file diff --git a/libs/libc/src/sched.cpp b/libs/libc/src/sched.cpp deleted file mode 100644 index 917b17d6..00000000 --- a/libs/libc/src/sched.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include -#include - -extern "C" -{ - int sched_yield() - { - return (int)__lc_fast_syscall0(SYS_yield); - } -} \ No newline at end of file diff --git a/libs/libc/src/setjmp.asm b/libs/libc/src/setjmp.asm deleted file mode 100644 index 21526397..00000000 --- a/libs/libc/src/setjmp.asm +++ /dev/null @@ -1,36 +0,0 @@ -global _setjmp -global setjmp -_setjmp: -setjmp: - mov rsi, 0 - mov [rdi], rbx - mov [rdi+8], r12 - mov [rdi+16], r13 - mov [rdi+24], r14 - mov [rdi+32], r15 - mov [rdi+40], rbp - mov [rdi+48], rsp - mov rax, [rsp] - mov [rdi+56], rax - xor rax, rax - ret - -global _longjmp -global longjmp -_longjmp: -longjmp: - mov rax, rsi - cmp rax, 0 - jne .nonzero - mov rax, 1 -.nonzero: - mov rbx, [rdi] - mov r12, [rdi+8] - mov r13, [rdi+16] - mov r14, [rdi+24] - mov r15, [rdi+32] - mov rbp, [rdi+40] - mov rsp, [rdi+48] - mov rcx, [rdi+56] - mov [rsp], rcx - ret \ No newline at end of file diff --git a/libs/libc/src/setjmp.cpp b/libs/libc/src/setjmp.cpp deleted file mode 100644 index d7d0e226..00000000 --- a/libs/libc/src/setjmp.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -extern "C" -{ - int sigsetjmp(sigjmp_buf env, int) - { - return setjmp(env); - } - - __lc_noreturn void siglongjmp(sigjmp_buf env, int val) - { - longjmp(env, val); - } -} \ No newline at end of file diff --git a/libs/libc/src/signal.cpp b/libs/libc/src/signal.cpp deleted file mode 100644 index a82b3f9d..00000000 --- a/libs/libc/src/signal.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -extern "C" -{ - void (*signal(int, void (*)(int)))(int) - { - NOT_IMPLEMENTED("signal"); - } - - int raise(int) - { - NOT_IMPLEMENTED("raise"); - } -} \ No newline at end of file diff --git a/libs/libc/src/stdio.cpp b/libs/libc/src/stdio.cpp deleted file mode 100644 index 1d6a0542..00000000 --- a/libs/libc/src/stdio.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern "C" -{ - int puts(const char* s) - { - int nwritten = fputs(s, stdout); - if (nwritten < 0) return -1; - if (putchar('\n') < 0) return -1; - return nwritten + 1; - } - - int fputs(const char* s, FILE* stream) - { - int result = (int)fwrite(s, strlen(s), 1, stream); - if (ferror(stream)) return -1; - return result; - } - - int fputc(int c, FILE* stream) - { - char chr = (char)c; - fwrite(&chr, 1, 1, stream); - if (ferror(stream)) { return -1; } - return c; - } - - int putc(int c, FILE* stream) - { - return fputc(c, stream); - } - - int putchar(int c) - { - return fputc(c, stdout); - } - - void perror(const char* s) - { - int savederr = - errno; // This was necessary before, but even more now since we clear errno on successful syscalls now. - if (s && *s) { fprintf(stderr, "%s: ", s); } - fprintf(stderr, "%s\n", strerror(savederr)); - } - - int remove(const char*) - { - NOT_IMPLEMENTED("remove"); - } - - int sscanf(const char*, const char*, ...) - { - NOT_IMPLEMENTED("sscanf"); - } - - int fscanf(FILE*, const char*, ...) - { - NOT_IMPLEMENTED("fscanf"); - } - - int scanf(const char*, ...) - { - NOT_IMPLEMENTED("scanf"); - } - - int rename(const char*, const char*) - { - NOT_IMPLEMENTED("rename"); - } - - FILE* tmpfile() - { - errno = ENOTSUP; - return NULL; - } -} \ No newline at end of file diff --git a/libs/libc/src/stdlib.cpp b/libs/libc/src/stdlib.cpp deleted file mode 100644 index 012f8c27..00000000 --- a/libs/libc/src/stdlib.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -template static T string_to_integer_type(const char* str) -{ - bool neg = false; - T val = 0; - - switch (*str) - { - case '-': - neg = true; - str++; - break; - case '+': str++; break; - default: break; - } - - while (isdigit(*str)) { val = (10 * val) + (*str++ - '0'); } - - return (neg ? -val : val); -} - -template static T string_to_float_type(const char* str) -{ - bool neg = false; - T val = 0; - - T small = 0; - - switch (*str) - { - case '-': - neg = true; - str++; - break; - case '+': str++; break; - default: break; - } - - while (isdigit(*str)) { val = (10 * val) + (T)(*str++ - '0'); } - if (*str == '.') - { - str++; - T div = 10; - while (isdigit(*str)) - { - small = small + (T)(*str++ - '0') / div; - div *= 10; - } - - val += small; - } - - return (neg ? -val : val); -} - -template static inline Struct common_div(Arg a, Arg b) -{ - Struct result; - result.quot = a / b; - result.rem = a % b; - - if (a >= 0 && result.rem < 0) - { - result.quot++; - result.rem -= b; - } - - return result; -} - -static void qswap(void* ptr1, void* ptr2, size_t size) -{ - char* x = (char*)ptr1; - char* y = (char*)ptr2; - - while (size--) - { - char t = *x; - *x = *y; - *y = t; - x += 1; - y += 1; - } -} - -static size_t partition(void* base, size_t start, size_t end, size_t size, int (*compar)(const void*, const void*)) -{ - auto atindex = [&base, &size](size_t index) { return (void*)((char*)base + (index * size)); }; - - void* pivot = atindex(end); - size_t i = (start - 1); - - for (size_t j = start; j <= end - 1; j++) - { - if (compar(atindex(j), pivot) < 0) - { - i++; - qswap(atindex(i), atindex(j), size); - } - } - - qswap(atindex(i + 1), pivot, size); - return i + 1; -} - -static void quicksort(void* base, size_t start, size_t end, size_t size, int (*compar)(const void*, const void*)) -{ - if (start < end) - { - size_t pivot = partition(base, start, end, size, compar); - quicksort(base, start, pivot - 1, size, compar); - quicksort(base, pivot + 1, end, size, compar); - } -} - -void* binary_search(const void* key, const void* base, size_t start, size_t end, size_t size, - int (*compar)(const void*, const void*)) -{ - auto atindex = [&base, &size](size_t index) { return (const void*)((const char*)base + (index * size)); }; - - if (end >= start) - { - size_t middle = start + (end - start) / 2; - int rc = compar(atindex(middle), key); - - if (rc == 0) return const_cast(atindex(middle)); // we found it!! - - if (rc < 0) return binary_search(key, base, middle + 1, end, size, compar); - - return binary_search(key, base, start, middle - 1, size, compar); - } - - return NULL; -} - -extern "C" -{ - __lc_noreturn void abort() - { - _Exit(-1); - } - - float atof(const char* str) - { - return string_to_float_type(str); - } - - int atoi(const char* str) - { - return string_to_integer_type(str); - } - - long atol(const char* str) - { - return string_to_integer_type(str); - } - - long long atoll(const char* str) - { - return string_to_integer_type(str); - } - - unsigned long strtoul(const char* str, char** endptr, int base) - { - if (base != 0 && base != 10) NOT_IMPLEMENTED("strtoul with base not in (0,10)"); - if (endptr) NOT_IMPLEMENTED("strtoul with non-null endptr"); - return string_to_integer_type(str); - } - - long strtol(const char* str, char** endptr, int base) - { - if (base != 0 && base != 10) NOT_IMPLEMENTED("strtol with base not in (0,10)"); - if (endptr) NOT_IMPLEMENTED("strtol with non-null endptr"); - return string_to_integer_type(str); - } - - char* getenv(const char*) - { - return NULL; // FIXME: Not implemented :) - } - - __lc_noreturn void _Exit(int status) - { - __lc_fast_syscall1(SYS_exit, status); - __lc_unreachable(); - } - - int abs(int val) - { - return __builtin_abs(val); - } - - long labs(long val) - { - return __builtin_labs(val); - } - - long long llabs(long long val) - { - return __builtin_llabs(val); - } - - div_t div(int a, int b) - { - return common_div(a, b); - } - - ldiv_t ldiv(long a, long b) - { - return common_div(a, b); - } - - lldiv_t lldiv(long long a, long long b) - { - return common_div(a, b); - } - - int system(const char* command) - { - pid_t child = fork(); - if (child < 0) return -1; - if (child == 0) - { - char* argv[] = {const_cast("/bin/sh"), const_cast("-c"), const_cast(command), - nullptr}; // FIXME: This is very verbose. - execv(argv[0], argv); - exit(127); - } - int status; - waitpid(child, &status, 0); - return status; - } - - void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)) - { - quicksort(base, 0, nmemb - 1, size, compar); - } - - void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)) - { - return binary_search(key, base, 0, nmemb - 1, size, compar); - } - - size_t mbstowcs(wchar_t*, const char*, size_t) - { - NOT_IMPLEMENTED("mbstowcs"); - } - - static void gentemp(char* startptr) - { - for (int i = 0; i < 6; i++) - { - startptr[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"[rand() % 63]; - } - } - - char* mktemp(char* str) - { - size_t len = strlen(str); - if (len < 6) - { - errno = EINVAL; - return NULL; - } - char* startptr = str + (len - 6); - if (strncmp(startptr, "XXXXXX", 6)) - { - errno = EINVAL; - return NULL; - } - do { - gentemp(startptr); - } while (access(str, F_OK) == 0); - return str; - } - - char* mkdtemp(char* str) - { - size_t len = strlen(str); - if (len < 6) - { - errno = EINVAL; - return NULL; - } - char* startptr = str + (len - 6); - if (strncmp(startptr, "XXXXXX", 6)) - { - errno = EINVAL; - return NULL; - } - do { - gentemp(startptr); - } while (mkdir(str, 0700) < 0 && errno == EEXIST); - if (errno) return NULL; - return str; - } - - double strtod(const char*, char**) - { - NOT_IMPLEMENTED("strtod"); - } -} \ No newline at end of file diff --git a/libs/libc/src/strftime.cpp b/libs/libc/src/strftime.cpp deleted file mode 100644 index d185f5bf..00000000 --- a/libs/libc/src/strftime.cpp +++ /dev/null @@ -1,318 +0,0 @@ -#include -#include -#include -#include -#include - -static void printf_strrev(char* arr, int size) -{ - int left = 0; - int right = size - 1; - for (int i = left; i < right; i++) - { - char temp = arr[i]; - arr[i] = arr[right]; - arr[right] = temp; - right--; - } -} - -template static char* printf_unsigned_to_string(IntegerType number, char* arr, int base) -{ - int i = 0; - - if (number == 0) - { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - while (number != 0) - { - IntegerType r = number % (IntegerType)base; - arr[i] = (char)((r > 9) ? (r - 10) + 'a' : r + '0'); - i++; - number /= base; - } - - printf_strrev(arr, i); - - arr[i] = '\0'; - - return arr; -} - -template static char* printf_signed_to_string(IntegerType number, char* arr, int base) -{ - int i = 0, negative = 0; - - if (number == 0) - { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - if (number < 0 && base == 10) - { - number *= -1; - negative = 1; - } - - while (number != 0) - { - IntegerType r = number % base; - arr[i] = (char)((r > 9) ? (r - 10) + 'a' : r + '0'); - i++; - number /= base; - } - - if (negative) - { - arr[i] = '-'; - i++; - } - - printf_strrev(arr, i); - - arr[i] = '\0'; - - return arr; -} - -const char* short_week_days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; -const char* long_week_days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; -const char* short_month_names[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; -const char* long_month_names[] = {"January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December"}; - -extern "C" size_t strftime(char* s, size_t max, const char* format, const struct tm* time) -{ - char buffer[1025]; // 1024 with null terminator - size_t format_size = strlen(format); - size_t format_index = 0; - size_t buffer_insert_index = 0; - ssize_t max_remaining = (ssize_t)max; - size_t written = 0; - - if (s && max) *s = 0; - - auto flush_buffer = [&]() { - size_t buffer_length = buffer_insert_index; - written += buffer_length; - buffer_insert_index = 0; - if (max_remaining < 0) - { - buffer[buffer_length] = 0; - if (s) strncat(s, buffer, sizeof(buffer)); - return; - } - if (max_remaining == 0) { return; } - if (buffer_length <= (size_t)max_remaining) - { - max_remaining -= buffer_length; - buffer[buffer_length] = 0; - if (s) strncat(s, buffer, sizeof(buffer)); - } - else - { - buffer[max_remaining] = 0; - max_remaining = 0; - if (s) strncat(s, buffer, sizeof(buffer)); - } - }; - - auto append_string = [&](const char* str) { - while (strlen(str) > 1024) - { - flush_buffer(); - memcpy(buffer, str, 1024); - str += 1024; - buffer_insert_index = 1024; - } - if (buffer_insert_index + strlen(str) > 1024) flush_buffer(); - memcpy(buffer + buffer_insert_index, str, strlen(str)); - buffer_insert_index += strlen(str); - if (buffer_insert_index == 1024) flush_buffer(); - }; - - auto append_char = [&](char c) { - buffer[buffer_insert_index++] = c; - if (buffer_insert_index == 1024) flush_buffer(); - }; - - while (format_index < format_size) - { - char current_char = format[format_index]; - if (current_char == '%') - { - if (format_index + 1 == format_size) // end of format string - { - format_index++; - continue; - } - else - { - format_index++; - current_char = format[format_index]; - switch (current_char) - { - case '%': { - append_char('%'); - break; - } - case 'a': { - append_string(short_week_days[time->tm_wday % 7]); - break; - } - case 'A': { - append_string(long_week_days[time->tm_wday % 7]); - break; - } - case 'b': { - append_string(short_month_names[(time->tm_mon - 1) % 12]); - break; - } - case 'B': { - append_string(long_month_names[(time->tm_mon - 1) % 12]); - break; - } - case 'c': { - char buf[32]; - append_string(short_week_days[time->tm_wday % 7]); - append_char(' '); - append_string(short_month_names[(time->tm_mon - 1) % 12]); - append_char(' '); - printf_signed_to_string(time->tm_mday, buf, 10); - append_string(buf); - append_char(' '); - printf_signed_to_string(time->tm_hour % 24, buf, 10); - append_string(buf); - append_char(':'); - printf_signed_to_string(time->tm_min % 60, buf, 10); - append_string(buf); - append_char(':'); - printf_signed_to_string(time->tm_sec % 60, buf, 10); - append_string(buf); - append_char(' '); - printf_signed_to_string(time->tm_year + 1900, buf, 10); - append_string(buf); - break; - } - case 'd': { - char buf[30]; - printf_signed_to_string(time->tm_mday % 32, buf, 10); - append_string(buf); - break; - } - case 'H': { - char buf[30]; - printf_signed_to_string(time->tm_hour % 24, buf, 10); - append_string(buf); - break; - } - case 'I': { - char buf[30]; - int hour = time->tm_hour % 12; - if (hour == 0) hour = 12; - printf_signed_to_string(hour, buf, 10); - append_string(buf); - break; - } - case 'j': { - char buf[30]; - printf_signed_to_string(time->tm_yday % 367, buf, 10); - append_string(buf); - break; - } - case 'm': { - char buf[30]; - printf_signed_to_string(time->tm_mon % 13, buf, 10); - append_string(buf); - break; - } - case 'M': { - char buf[30]; - printf_signed_to_string(time->tm_min % 60, buf, 10); - append_string(buf); - break; - } - case 'p': { - if (time->tm_hour < 12) append_string("AM"); - else - append_string("PM"); - break; - } - case 'P': { - if (time->tm_hour < 12) append_string("am"); - else - append_string("pm"); - break; - } - case 'S': { - char buf[30]; - printf_signed_to_string(time->tm_sec % 61, buf, 10); - append_string(buf); - break; - } - case 'w': { - char buf[30]; - printf_signed_to_string(time->tm_wday % 7, buf, 10); - append_string(buf); - break; - } - case 'x': { - char buf[30]; - printf_signed_to_string(time->tm_mon % 13, buf, 10); - append_string(buf); - append_char('/'); - printf_signed_to_string(time->tm_mday % 32, buf, 10); - append_string(buf); - append_char('/'); - printf_signed_to_string((time->tm_year + 1900) % 100, buf, 10); - append_string(buf); - break; - } - case 'X': { - char buf[30]; - printf_signed_to_string(time->tm_hour % 24, buf, 10); - append_string(buf); - append_char(':'); - printf_signed_to_string(time->tm_min % 60, buf, 10); - append_string(buf); - append_char(':'); - printf_signed_to_string(time->tm_sec % 60, buf, 10); - append_string(buf); - break; - } - case 'y': { - char buf[30]; - printf_signed_to_string((time->tm_year + 1900) % 100, buf, 10); - append_string(buf); - break; - } - case 'Y': { - char buf[30]; - printf_signed_to_string(time->tm_year + 1900, buf, 10); - append_string(buf); - break; - } - case 'Z': { - append_string("UTC"); // FIXME: Add timezone support. - break; - } - default: { - fprintf(stderr, "strftime: unknown format specifier %%%c\n", current_char); - abort(); - } - } - } - } - else { append_char(current_char); } - format_index++; - } - - if (buffer_insert_index > 0) flush_buffer(); - return written; -} \ No newline at end of file diff --git a/libs/libc/src/string.cpp b/libs/libc/src/string.cpp deleted file mode 100644 index 44184d4f..00000000 --- a/libs/libc/src/string.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include -#include -#include -#include - -extern "C" -{ - void* memcpy(void* dest, const void* src, size_t n) - { - for (size_t i = 0; i < n; ++i) { *((char*)dest + i) = *((const char*)src + i); } - return dest; - } - - void* memset(void* buf, int c, size_t n) - { - for (size_t i = 0; i < n; ++i) { *((char*)buf + i) = (char)c; } - return buf; - } - - void* memchr(const void* buf, int c, size_t n) - { - const char* s = (const char*)buf; - for (; n && *s != (char)c; s++, n--) - ; - if (n) return (void*)(const_cast(s)); - return NULL; - } - - int memcmp(const void* a, const void* b, size_t n) - { - if (!n) return 0; - const unsigned char* ap = (const unsigned char*)a; - const unsigned char* bp = (const unsigned char*)b; - while (--n && *ap == *bp) - { - ap++; - bp++; - } - return *ap - *bp; - } - - void* memmove(void* dest, const void* src, size_t n) - { - if (dest == src) return dest; - if (dest > src) - for (long i = n - 1; i >= 0; i++) { *((char*)dest + i) = *((const char*)src + i); } - else - for (long i = 0; i < (long)n; i++) { *((char*)dest + i) = *((const char*)src + i); } - return dest; - } - - char* strdup(const char* str) - { - size_t len = strlen(str); - char* dest = (char*)malloc(len + 1); - if (!dest) return dest; - return (char*)memcpy(dest, str, len + 1); - } - - char* strndup(const char* str, size_t max) - { - size_t len = strnlen(str, max); - char* dest = (char*)malloc(len + 1); - if (!dest) return dest; - memcpy(dest, str, len); - dest[len] = 0; - return dest; - } - - size_t strlen(const char* str) - { - const char* i = str; - for (; *i; ++i) - ; - return (i - str); - } - - size_t strnlen(const char* str, size_t max) - { - char* p = (char*)memchr(str, 0, max); - return p ? p - str : max; - } - - char* strcpy(char* dest, const char* src) - { - return (char*)memcpy(dest, src, strlen(src) + 1); - } - - char* strncpy(char* dest, const char* src, size_t max) - { - size_t i; - for (i = 0; i < max && src[i] != 0; i++) dest[i] = src[i]; - for (; i < max; i++) dest[i] = 0; - return dest; - } - - size_t strlcpy(char* dest, const char* src, size_t size) - { - size_t len = strlen(src); - if (size == 0) return len; - if (len < (size - 1)) - { - memcpy(dest, src, len); - dest[len] = 0; - } - else - { - memcpy(dest, src, size - 1); - dest[size - 1] = 0; - } - return len; - } - - char* stpcpy(char* dest, const char* src) - { - size_t len = strlen(src); - size_t rc = strlcpy(dest, src, len + 1); - return dest + rc; - } - - int strcmp(const char* a, const char* b) - { - while (*a && (*a == *b)) - { - a++; - b++; - } - return *(const unsigned char*)a - *(const unsigned char*)b; - } - - int strncmp(const char* a, const char* b, size_t max) - { - const char* base = a; - while (*a && (*a == *b) && (size_t)(a - base) < (max - 1)) - { - a++; - b++; - } - return *(const unsigned char*)a - *(const unsigned char*)b; - } - - int strcoll(const char* a, const char* b) - { - return strcmp(a, b); - } - - size_t strxfrm(char* dest, const char* src, size_t n) - { - strncpy(dest, src, n); - return n; - } - - size_t strcspn(const char* str, const char* reject) - { - const char* s = str; - while (*s) - { - const char* rp = reject; - while (*rp) - { - if (*s == *rp) return s - str; - rp++; - } - s++; - } - return s - str; - } - - size_t strspn(const char* str, const char* accept) - { - const char* s = str; - while (*s) - { - const char* ap = accept; - bool match = false; - while (*ap) - { - if (*s == *ap) - { - match = true; - break; - } - ap++; - } - if (!match) return s - str; - s++; - } - return s - str; - } - - char* strpbrk(const char* a, const char* b) - { - while (*a) - { - if (strchr(b, *a)) return const_cast(a); - a++; - } - return NULL; - } - - char* strcat(char* dest, const char* src) - { - size_t dest_len = strlen(dest); - size_t i; - - for (i = 0; *(src + i); i++) *(dest + dest_len + i) = *(src + i); - - *(dest + dest_len + i) = '\0'; - - return dest; - } - - char* strncat(char* dest, const char* src, size_t max) - { - size_t dest_len = strlen(dest); - size_t i; - - for (i = 0; i < max && *(src + i); i++) *(dest + dest_len + i) = *(src + i); - - *(dest + dest_len + i) = '\0'; - - return dest; - } - - char* strchr(const char* str, int c) - { - while (*str && *str != (char)c) str++; - if (*str) return const_cast(str); - return NULL; - } - - char* strchrnul(const char* str, int c) - { - while (*str && *str != (char)c) str++; - return const_cast(str); - } - - char* strrchr(const char* str, int c) - { - const char* s = str + strlen(str); - while (s != str && *s != (char)c) s--; - if (s != str) return const_cast(s); - if (*s == (char)c) return const_cast(s); - return NULL; - } - - char* strstr(const char* haystack, const char* needle) - { - size_t needle_size = strlen(needle); - size_t haystack_size = strlen(haystack); - while (*haystack) - { - if (*haystack == *needle) - { - if (needle_size <= haystack_size) - { - if (!strncmp(haystack, needle, needle_size)) return const_cast(haystack); - } - else { return NULL; } - } - haystack++; - haystack_size--; - } - return NULL; - } - -#pragma GCC push_options -#pragma GCC diagnostic ignored "-Wwrite-strings" - - char* strerror(int err) - { - switch (err) - { - case EPERM: return "Operation not permitted"; - case ENOENT: return "No such file or directory"; - case ESRCH: return "No such process"; - case EINTR: return "Interrupted system call"; - case EIO: return "Input/output error"; - case E2BIG: return "Argument list too long"; - case ENOEXEC: return "Exec format error"; - case EBADF: return "Bad file descriptor"; - case ECHILD: return "No child processes"; - case EAGAIN: return "Resource temporarily unavailable"; - case ENOMEM: return "Cannot allocate memory"; - case EACCES: return "Permission denied"; - case EFAULT: return "Bad address"; - case EEXIST: return "File exists"; - case ENOTDIR: return "Not a directory"; - case EISDIR: return "Is a directory"; - case EINVAL: return "Invalid argument"; - case EMFILE: return "Too many open files"; - case ENOTTY: return "Inappropriate ioctl for device"; - case EFBIG: return "File too large"; - case ENOSPC: return "No space left on device"; - case EPIPE: return "Broken pipe"; - case EDOM: return "Numerical argument out of domain"; - case ERANGE: return "Numerical result out of range"; - case ENOSYS: return "Function not implemented"; - case ENOTSUP: return "Operation not supported"; - case 0: return "Success"; - default: return "Unknown error"; - } - } - -#pragma GCC pop_options - - char* strtok(char*, const char*) - { - NOT_IMPLEMENTED("strtok"); - } -} \ No newline at end of file diff --git a/libs/libc/src/strings.cpp b/libs/libc/src/strings.cpp deleted file mode 100644 index b8f436e5..00000000 --- a/libs/libc/src/strings.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -static char lowercase(char c) -{ - if (isalpha(c)) return (char)tolower(c); - return c; -} - -extern "C" -{ - void bzero(void* buf, size_t n) - { - memset(buf, 0, n); - } - - void bcopy(void* dest, const void* src, size_t n) - { - memcpy(dest, src, n); - } - - int strcasecmp(const char* a, const char* b) - { - while (*a && (lowercase(*a) == lowercase(*b))) - { - a++; - b++; - } - return (unsigned char)lowercase(*a) - (unsigned char)lowercase(*b); - } - - int strncasecmp(const char* a, const char* b, size_t max) - { - const char* base = a; - while (*a && (lowercase(*a) == lowercase(*b)) && (size_t)(a - base) < (max - 1)) - { - a++; - b++; - } - return (unsigned char)lowercase(*a) - (unsigned char)lowercase(*b); - } -} \ No newline at end of file diff --git a/libs/libc/src/sys/ioctl.cpp b/libs/libc/src/sys/ioctl.cpp deleted file mode 100644 index 053fb7e6..00000000 --- a/libs/libc/src/sys/ioctl.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include -#include -#include -#include - -extern "C" -{ - int ioctl(int fd, int cmd, ...) - { - va_list ap; - va_start(ap, cmd); - long result = __lc_fast_syscall3(SYS_ioctl, fd, cmd, va_arg(ap, uintptr_t)); - va_end(ap); - return (int)result; - } -} \ No newline at end of file diff --git a/libs/libc/src/sys/mman.cpp b/libs/libc/src/sys/mman.cpp deleted file mode 100644 index 3a5b6b1a..00000000 --- a/libs/libc/src/sys/mman.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include - -extern "C" -{ - // FIXME: Implement a POSIX-compliant mmap. - void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset) - { - long result = __luna_syscall5(SYS_mmap, (sysarg_t)addr, (sysarg_t)len, (sysarg_t)prot, - flags & MAP_ANONYMOUS ? (sysarg_t)-1 : (sysarg_t)fd, (sysarg_t)offset); - _RETURN_WITH_MEMORY_ERRNO(result, void*); - } - - int munmap(void* addr, size_t len) - { - return (int)__lc_fast_syscall2(SYS_munmap, addr, len); - } - - int mprotect(void* addr, size_t size, int prot) - { - return (int)__lc_fast_syscall3(SYS_mprotect, addr, size, prot); - } -} \ No newline at end of file diff --git a/libs/libc/src/sys/stat.cpp b/libs/libc/src/sys/stat.cpp deleted file mode 100644 index f2820101..00000000 --- a/libs/libc/src/sys/stat.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include -#include - -extern "C" -{ - int mkdir(const char* pathname, mode_t mode) - { - return (int)__lc_fast_syscall2(SYS_mkdir, pathname, mode); - } - - int fstat(int fd, struct stat* buf) - { - return (int)__lc_fast_syscall2(SYS_fstat, fd, buf); - } - - int stat(const char* path, struct stat* buf) - { - return (int)__lc_fast_syscall2(SYS_stat, path, buf); - } - - mode_t umask(mode_t cmask) - { - return (mode_t)__lc_fast_syscall1(SYS_umask, cmask); - } - - int chmod(const char*, mode_t) - { - NOT_IMPLEMENTED("chmod"); - } - - int fchmod(int, mode_t) - { - NOT_IMPLEMENTED("fchmod"); - } -} \ No newline at end of file diff --git a/libs/libc/src/sys/wait.cpp b/libs/libc/src/sys/wait.cpp deleted file mode 100644 index ca9e524e..00000000 --- a/libs/libc/src/sys/wait.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -#include - -extern "C" -{ - pid_t waitpid(pid_t pid, int* wstatus, int options) - { - return __lc_fast_syscall3(SYS_waitpid, pid, wstatus, options); - } - - pid_t wait(int* wstatus) - { - return waitpid(-1, wstatus, 0); - } -} \ No newline at end of file diff --git a/libs/libc/src/syscall.cpp b/libs/libc/src/syscall.cpp deleted file mode 100644 index bad85517..00000000 --- a/libs/libc/src/syscall.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include -#include - -extern "C" long syscall(long number, ...) -{ - typedef unsigned long arg; - long result; - va_list ap; - va_start(ap, number); - switch (number) - { - case SYS_yield: - case SYS_fork: result = __luna_syscall0(number); break; - case SYS_exit: - case SYS_getprocid: - case SYS_close: - case SYS_umask: - case SYS_setuid: - case SYS_setgid: - case SYS_seteuid: - case SYS_setegid: - case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break; - case SYS_munmap: - case SYS_execv: - case SYS_access: - case SYS_fstat: - case SYS_stat: - case SYS_mkdir: - case SYS_dup2: - case SYS_clock_gettime: - case SYS_pstat: { - arg arg0 = va_arg(ap, arg); - arg arg1 = va_arg(ap, arg); - result = __luna_syscall2(number, arg0, arg1); - break; - } - case SYS_open: - case SYS_getdents: - case SYS_fcntl: - case SYS_seek: - case SYS_write: - case SYS_read: - case SYS_ioctl: - case SYS_mprotect: - case SYS_waitpid: { - arg arg0 = va_arg(ap, arg); - arg arg1 = va_arg(ap, arg); - arg arg2 = va_arg(ap, arg); - result = __luna_syscall3(number, arg0, arg1, arg2); - break; - } - case SYS_mmap: { - arg arg0 = va_arg(ap, arg); - arg arg1 = va_arg(ap, arg); - arg arg2 = va_arg(ap, arg); - arg arg3 = va_arg(ap, arg); - arg arg4 = va_arg(ap, arg); - result = __luna_syscall5(number, arg0, arg1, arg2, arg3, arg4); - break; - } - default: result = -ENOSYS; break; - } - va_end(ap); - if (number == SYS_mmap) { _RETURN_WITH_MEMORY_ERRNO(result, long int); } - else { _RETURN_WITH_ERRNO(result, long); } -} \ No newline at end of file diff --git a/libs/libc/src/time.cpp b/libs/libc/src/time.cpp deleted file mode 100644 index f6516871..00000000 --- a/libs/libc/src/time.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define SECONDS_PER_DAY 86400 - -static int isleap(int year) -{ - return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); -} - -static int make_yday(int year, int month) -{ - static const short int upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - int yd; - - yd = upto[month - 1]; - if (month > 2 && isleap(year)) yd++; - return yd; -} - -static int day_of_week(int year, int mon, int day) -{ - static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; - year -= mon < 3; - return (year + year / 4 - year / 100 + year / 400 + t[mon - 1] + day) % 7; -} - -static time_t broken_down_to_unix(time_t year, time_t yday, time_t hour, time_t min, time_t sec) -{ - return sec + min * 60 + hour * 3600 + yday * 86400 + (year - 70) * 31536000 + ((year - 69) / 4) * 86400 - - ((year - 1) / 100) * 86400 + ((year + 299) / 400) * 86400; -} - -static void time_to_struct_tm(time_t time, struct tm* result) -{ - result->tm_isdst = 0; // No DST/timezone support for now. - - int year = 1970; - - while (time > 0) - { - time_t seconds_in_year = (isleap(year) ? 366 : 365) * SECONDS_PER_DAY; - if (seconds_in_year <= time) - { - year++; - time -= seconds_in_year; - continue; - } - break; - } - - int month_days[] = {31, isleap(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - int month = 0; - - while (1) - { - time_t seconds_in_month = month_days[month] * SECONDS_PER_DAY; - if (seconds_in_month <= time) - { - month++; - time -= seconds_in_month; - continue; - } - break; - } - - int day = (int)(time / SECONDS_PER_DAY); - time %= SECONDS_PER_DAY; - - assert(day < month_days[month]); - - int hour = (int)(time / 3600); - time %= 3600; - - int min = (int)(time / 60); - time %= 60; - - result->tm_year = year - 1900; - result->tm_mon = month + 1; - result->tm_yday = make_yday(year, month + 1) + day; - result->tm_wday = day_of_week(year, month + 1, day + 1); - result->tm_mday = day + 1; - result->tm_hour = hour; - result->tm_min = min; - result->tm_sec = (int)time; -} - -const char* wday_names[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; -const char* month_names[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - -extern "C" -{ - clock_t clock() - { - struct timespec tp; - clock_gettime(CLOCK_PROCTIME, &tp); - return (tp.tv_sec * CLOCKS_PER_SEC) + (tp.tv_nsec / 1000); - } - - time_t time(time_t* tloc) - { - struct timespec tp; - clock_gettime(CLOCK_REALTIME, &tp); - if (tloc) { *tloc = tp.tv_sec; } - return tp.tv_sec; - } - - int clock_gettime(clockid_t clock_id, struct timespec* tp) - { - return (int)__lc_fast_syscall2(SYS_clock_gettime, clock_id, tp); - } - - int gettimeofday(struct timeval* tp, __lc_unused void* tzp) - { - struct timespec tspec; - clock_gettime(CLOCK_REALTIME, &tspec); - tp->tv_sec = tspec.tv_sec; - tp->tv_usec = tspec.tv_nsec / 1000; - return 0; - } - - struct tm* localtime(const time_t* time) - { - static struct tm result; - return localtime_r(time, &result); - } - - struct tm* gmtime(const time_t* time) - { - static struct tm result; - return gmtime_r(time, &result); - } - - struct tm* localtime_r(const time_t* time, struct tm* result) - { - return gmtime_r(time, result); // FIXME: Implement timezones. - } - - struct tm* gmtime_r(const time_t* time, struct tm* result) - { - time_to_struct_tm(*time, result); - return result; - } - - char* asctime_r(const struct tm* time, char buf[26]) - { - strftime(buf, 26, "%a %b %d %H:%M:%S %Y\n", time); - return buf; - } - - char* asctime(const struct tm* time) - { - static char buf[26]; - return asctime_r(time, buf); - } - - char* ctime_r(const time_t* time, char buf[26]) - { - struct tm stm; - return asctime_r(localtime_r(time, &stm), buf); - } - - char* ctime(const time_t* time) - { - return asctime(localtime(time)); - } - - time_t mktime(struct tm* time) - { - return broken_down_to_unix(time->tm_year, time->tm_yday, time->tm_hour, time->tm_min, time->tm_sec); - } - - double difftime(time_t time2, time_t time1) - { - return (double)(time2 - time1); - } -} \ No newline at end of file diff --git a/libs/libc/src/unistd.cpp b/libs/libc/src/unistd.cpp deleted file mode 100644 index 29ec9fed..00000000 --- a/libs/libc/src/unistd.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -extern "C" -{ - int execv(const char* program, char* const argv[]) - { - return (int)__lc_fast_syscall2(SYS_execv, program, argv); - } - - int execve(const char*, char* const[], char* const[]) - { - NOT_IMPLEMENTED("execve"); - } - int execvp(const char*, char* const[]) - { - NOT_IMPLEMENTED("execvp"); - } - - pid_t fork(void) - { - return __lc_fast_syscall0(SYS_fork); - } - - pid_t getpid(void) - { - return getprocid(ID_PID); - } - - pid_t getppid(void) - { - return getprocid(ID_PPID); - } - - uid_t getuid(void) - { - return (uid_t)getprocid(ID_UID); - } - - uid_t geteuid(void) - { - return (uid_t)getprocid(ID_EUID); - } - - gid_t getgid(void) - { - return (gid_t)getprocid(ID_GID); - } - - gid_t getegid(void) - { - return (gid_t)getprocid(ID_EGID); - } - - int setuid(uid_t uid) - { - return (int)__lc_fast_syscall1(SYS_setuid, uid); - } - - int seteuid(uid_t euid) - { - return (int)__lc_fast_syscall1(SYS_seteuid, euid); - } - - int setgid(gid_t gid) - { - return (int)__lc_fast_syscall1(SYS_setgid, gid); - } - - int setegid(gid_t egid) - { - return (int)__lc_fast_syscall1(SYS_setegid, egid); - } - - unsigned int sleep(unsigned int seconds) - { - return msleep(seconds * 1000); - } - - ssize_t read(int fd, void* buf, size_t count) - { - return __lc_fast_syscall3(SYS_read, fd, count, buf); // yes, our read() syscall is in the wrong order. - } - - ssize_t write(int fd, const void* buf, size_t count) - { - return __lc_fast_syscall3(SYS_write, fd, count, buf); // yes, our write() syscall is in the wrong order. - } - - int close(int fd) - { - return (int)__lc_fast_syscall1(SYS_close, fd); - } - - off_t lseek(int fd, off_t offset, int whence) - { - return __lc_fast_syscall3(SYS_seek, fd, offset, whence); - } - - __lc_noreturn void _exit(int status) - { - __lc_fast_syscall1(SYS_exit, status); - __lc_unreachable(); - } - - int dup(int fd) - { - return fcntl(fd, F_DUPFD, 0); - } - - int dup2(int fd, int fd2) - { - return (int)__lc_fast_syscall2(SYS_dup2, fd, fd2); - } - - int access(const char* path, int amode) - { - return (int)__lc_fast_syscall2(SYS_access, path, amode); - } - - int isatty(int fd) - { - int result = fcntl(fd, F_ISTTY); - if (result < 0) return 0; - return 1; - } - - char* getcwd(char* buf, size_t size) - { - const char* dummy_cwd = "/"; // FIXME: Actually retrieve the current working directory from the kernel. - if (size < 2) - { - errno = ERANGE; - return NULL; - } - if (!buf) { buf = (char*)malloc(size); } - strlcpy(buf, dummy_cwd, 2); - return buf; - } - - int unlink(const char*) - { - NOT_IMPLEMENTED("unlink"); - } - - int rmdir(const char*) - { - NOT_IMPLEMENTED("rmdir"); - } - - int chdir(const char*) - { - NOT_IMPLEMENTED("chdir"); - } - - int pipe(int[2]) - { - NOT_IMPLEMENTED("pipe"); - } - - long pathconf(const char* path, int name) - { - switch (name) - { - case _PC_PATH_MAX: return PATH_MAX - (strlen(path) + 1); - default: errno = EINVAL; return -1; - } - } - - int getdtablesize(void) - { - return OPEN_MAX; - } -} \ No newline at end of file diff --git a/libs/libc/src/utime.cpp b/libs/libc/src/utime.cpp deleted file mode 100644 index b3ffb991..00000000 --- a/libs/libc/src/utime.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -extern "C" -{ - int utime(const char*, const struct utimbuf*) - { - NOT_IMPLEMENTED("utime"); - } -} \ No newline at end of file diff --git a/libs/libc/src/wchar.cpp b/libs/libc/src/wchar.cpp deleted file mode 100644 index 50d32df9..00000000 --- a/libs/libc/src/wchar.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include - -extern "C" -{ - size_t wcslen(const wchar_t* str) - { - const wchar_t* i = str; - for (; *i; ++i) - ; - return (i - str); - } - - wchar_t* wcscat(wchar_t* dest, const wchar_t* src) - { - size_t dest_len = wcslen(dest); - size_t i; - - for (i = 0; *(src + i); i++) *(dest + dest_len + i) = *(src + i); - - *(dest + dest_len + i) = L'\0'; - - return dest; - } -} \ No newline at end of file diff --git a/luna/Types.h b/luna/Types.h new file mode 100644 index 00000000..d2dc477b --- /dev/null +++ b/luna/Types.h @@ -0,0 +1,10 @@ +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; \ No newline at end of file diff --git a/ports/add-port.sh b/ports/add-port.sh deleted file mode 100755 index 222931ac..00000000 --- a/ports/add-port.sh +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd $(dirname $0)/.. - -unset LUNA_BASE - -source tools/env.sh - -cd ports - -unset pkgname -unset pkgver -unset pkgurl -unset pkgmode -unset setupdir -unset builddir -unset installdir -unset srcdir -unset port_unpack -unset port_patch -unset port_configure -unset port_build -unset port_install -unset port_uninstall - -export DESTDIR=${DESTDIR:-"$LUNA_ROOT/initrd"} - -export listdir=$PWD - -if [ -z $1 ] -then - echo "Usage: add-port.sh " - exit 1 -fi - -if [ -d $1 ] -then - pkgscript=$1/package.sh -elif [ -f $1 ] -then - pkgscript=$1 -else - echo "Unrecognized argument: $1" - exit 1 -fi - -export portdir=$(realpath $(dirname $pkgscript)) -export workdir=$portdir/workdir -mkdir -p $workdir - -source $pkgscript - -if ! [ -z ${pkgdeps+x} ] -then - echo "Installing dependencies of $pkgname..." - for pkg in ${pkgdeps[@]} - do - set +e - grep $pkg ports.list >/dev/null - if [ "$?" = "0" ] - then - echo "Dependency $pkg is already installed." - else - echo "Installing dependency $pkg..." - ./add-port.sh $pkg - fi - set -e - done -fi - -echo "Building $pkgname version $pkgver..." - -cd $workdir - -if ! [ -d $srcdir ] -then - mkdir -p $setupdir - cd $setupdir - - echo "Downloading $pkgname version $pkgver..." - - case $pkgmode in - "web") wget $pkgurl;; - "git") git clone $pkgurl;; - *) echo "Don't know how to download package mode '$pkgmode'"; exit 1;; - esac - - set +e - command -v port_unpack >/dev/null - set -e - if [ "$?" = "0" ] - then - echo "Unpacking $pkgname version $pkgver..." - port_unpack | filter-lines $pkgname "unpack" - fi - - set +e - command -v port_patch >/dev/null - set -e - if [ "$?" = "0" ] - then - echo "Patching $pkgname version $pkgver..." - port_patch | filter-lines $pkgname "patch" - fi -fi - -cd $workdir - -mkdir -p $builddir -cd $builddir - -set +e -command -v port_configure >/dev/null -set -e -if [ "$?" = "0" ] -then - echo "Configuring $pkgname version $pkgver..." - port_configure | filter-lines $pkgname "configure" -fi - -echo "Making $pkgname version $pkgver..." -port_build | filter-lines $pkgname "build" # this one is required - -cd $workdir - -mkdir -p $installdir -cd $installdir - -echo "Installing $pkgname version $pkgver..." -port_install | filter-lines $pkgname "install" - -if ! [ "$SKIP_ADD_TO_PORTS_LIST" = "1" ] -then - echo "$pkgname" >> $listdir/ports.list - cat $listdir/ports.list | sort | uniq | tee $listdir/ports.list >/dev/null # avoid duplicates - - echo "Success! Registered port: $pkgname version $pkgver." -fi \ No newline at end of file diff --git a/ports/bc/bc.patch b/ports/bc/bc.patch deleted file mode 100644 index a4a4ffdc..00000000 --- a/ports/bc/bc.patch +++ /dev/null @@ -1,60 +0,0 @@ -diff --color -rN -u bc-vanilla/include/library.h bc-6.0.4/include/library.h ---- a/bc-6.0.4/include/library.h 2022-09-26 19:34:34.000000000 +0200 -+++ b/bc-6.0.4/include/library.h 2022-10-15 14:59:11.413415573 +0200 -@@ -36,7 +36,7 @@ - #ifndef LIBBC_PRIVATE_H - #define LIBBC_PRIVATE_H - --#ifndef _WIN32 -+#if !defined(_WIN32) && !defined(__luna__) - - #include - -@@ -236,13 +236,17 @@ - BcVm* - bcl_getspecific(void); - --#ifndef _WIN32 -+#if !defined(_WIN32) && !defined(__luna__) - - typedef pthread_key_t BclTls; - - #else // _WIN32 - -+#ifdef __luna__ -+typedef int BclTls; -+#else - typedef DWORD BclTls; -+#endif - - #endif // _WIN32 - -diff --color -rN -u bc-vanilla/src/vm.c bc-6.0.4/src/vm.c ---- a/bc-6.0.4/src/vm.c 2022-09-26 19:34:35.000000000 +0200 -+++ b/bc-6.0.4/src/vm.c 2022-10-21 17:29:13.511229371 +0200 -@@ -193,7 +193,7 @@ - static void - bc_vm_sigaction(void) - { --#ifndef _WIN32 -+#if !defined(_WIN32) && !defined(__luna__) - - struct sigaction sa; - -@@ -223,11 +223,15 @@ - if (BC_TTY) sigaction(SIGHUP, &sa, NULL); - #endif // BC_ENABLE_HISTORY - --#else // _WIN32 -+#else -+ -+#ifndef __luna__ - - signal(SIGTERM, bc_vm_sig); - signal(SIGINT, bc_vm_sig); - -+#endif -+ - #endif // _WIN32 - } - diff --git a/ports/bc/package.sh b/ports/bc/package.sh deleted file mode 100644 index a307fd32..00000000 --- a/ports/bc/package.sh +++ /dev/null @@ -1,40 +0,0 @@ -pkgname="bc" -pkgver="6.0.4" -pkgurl="https://github.com/gavinhoward/bc/releases/download/$pkgver/bc-$pkgver.tar.gz" - -pkgmode="web" - -setupdir="$workdir" -builddir="$workdir/build" -installdir="$workdir/build" -srcdir="$workdir/bc-$pkgver" - -port_unpack() -{ - tar xvf bc-$pkgver.tar.gz -} - -port_patch() -{ - patch -u -i $portdir/bc.patch -p 1 -d $workdir -} - -port_configure() -{ - HOSTCC=gcc PREFIX=${PREFIX:-""} $srcdir/configure --disable-nls --bc-only --disable-history --disable-man-pages -} - -port_build() -{ - make -j$(nproc) -} - -port_install() -{ - make install -} - -port_uninstall() -{ - make uninstall -} \ No newline at end of file diff --git a/ports/binutils/binutils.patch b/ports/binutils/binutils.patch deleted file mode 100644 index 6c8e94a6..00000000 --- a/ports/binutils/binutils.patch +++ /dev/null @@ -1,144 +0,0 @@ -diff --color -rN -u binutils-2.38/bfd/config.bfd binutils-2.38/bfd/config.bfd ---- a/binutils-2.38/bfd/config.bfd 2022-01-22 13:14:07.000000000 +0100 -+++ b/binutils-2.38/bfd/config.bfd 2022-11-09 16:09:46.143869977 +0100 -@@ -651,6 +651,11 @@ - targ_selvecs="iamcu_elf32_vec i386_pei_vec" - targ64_selvecs="x86_64_elf64_vec x86_64_elf32_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec" - ;; -+ i[3-7]86-*-luna*) -+ targ_defvec=i386_elf32_vec -+ targ_selvecs= -+ targ64_selvecs=x86_64_elf64_vec -+ ;; - i[3-7]86-*-redox*) - targ_defvec=i386_elf32_vec - targ_selvecs= -@@ -706,6 +711,11 @@ - targ_selvecs="i386_elf32_vec iamcu_elf32_vec x86_64_elf32_vec i386_pei_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec" - want64=true - ;; -+ x86_64-*-luna*) -+ targ_defvec=x86_64_elf64_vec -+ targ_selvecs=i386_elf32_vec -+ want64=true -+ ;; - x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin) - targ_defvec=x86_64_pe_vec - targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_big_vec x86_64_elf64_vec l1om_elf64_vec k1om_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec" -diff --color -rN -u binutils-2.38/gas/configure.tgt binutils-2.38/gas/configure.tgt ---- a/binutils-2.38/gas/configure.tgt 2022-01-22 13:14:08.000000000 +0100 -+++ b/binutils-2.38/gas/configure.tgt 2022-11-09 16:09:46.144869977 +0100 -@@ -238,6 +238,7 @@ - x86_64*-linux-gnux32) arch=x86_64:32 ;; - esac ;; - i386-*-lynxos*) fmt=elf em=lynx ;; -+ i386-*-luna*) fmt=elf em=gnu ;; - i386-*-redox*) fmt=elf ;; - i386-*-solaris*) fmt=elf em=solaris ;; - i386-*-freebsd* \ -diff --color -rN -u binutils-2.38/gas/messages.c binutils-2.38/gas/messages.c ---- a/binutils-2.38/gas/messages.c 2022-01-22 13:14:08.000000000 +0100 -+++ b/binutils-2.38/gas/messages.c 2022-11-09 16:26:03.275802078 +0100 -@@ -324,7 +324,9 @@ - signal_crash (int signo) - { - /* Reset, to prevent unbounded recursion. */ -+#ifndef __luna__ - signal (signo, SIG_DFL); -+#endif - - as_abort (NULL, 0, strsignal (signo)); - } -diff --color -rN -u binutils-2.38/ld/configure.tgt binutils-2.38/ld/configure.tgt ---- a/binutils-2.38/ld/configure.tgt 2022-01-22 15:19:36.000000000 +0100 -+++ b/binutils-2.38/ld/configure.tgt 2022-11-09 16:09:46.145869977 +0100 -@@ -329,6 +329,11 @@ - targ64_extra_emuls="elf_x86_64 elf32_x86_64 elf_l1om elf_k1om" - targ64_extra_libpath="elf_x86_64 elf32_x86_64" - ;; -+i[3-7]86-*-luna*) -+ targ_emul=elf_i386_luna -+ targ_extra_emuls=elf_i386 -+ targ64_extra_emuls="elf_x86_64_luna elf_x86_64" -+ ;; - i[3-7]86-*-redox*) targ_emul=elf_i386 - targ_extra_emuls=elf_x86_64 - ;; -@@ -967,6 +972,10 @@ - targ_extra_libpath="elf_i386 elf32_x86_64 elf_l1om elf_k1om" - tdir_elf_i386=`echo ${targ_alias} | sed -e 's/x86_64/i386/'` - ;; -+x86_64-*-luna*) -+ targ_emul=elf_x86_64_luna -+ targ_extra_emuls="elf_i386_luna elf_x86_64 elf_i386" -+ ;; - x86_64-*-redox*) targ_emul=elf_x86_64 - targ_extra_emuls=elf_i386 - ;; -diff --color -rN -u binutils-2.38/ld/emulparams/elf_i386_luna.sh binutils-2.38/ld/emulparams/elf_i386_luna.sh ---- a/binutils-2.38/ld/emulparams/elf_i386_luna.sh 1970-01-01 01:00:00.000000000 +0100 -+++ b/binutils-2.38/ld/emulparams/elf_i386_luna.sh 2022-11-09 16:09:46.145869977 +0100 -@@ -0,0 +1,3 @@ -+source_sh ${srcdir}/emulparams/elf_i386.sh -+TEXT_START_ADDR=0x08000000 -+MAXPAGESIZE=0x1000 -\ No newline at end of file -diff --color -rN -u binutils-2.38/ld/emulparams/elf_x86_64_luna.sh binutils-2.38/ld/emulparams/elf_x86_64_luna.sh ---- a/binutils-2.38/ld/emulparams/elf_x86_64_luna.sh 1970-01-01 01:00:00.000000000 +0100 -+++ b/binutils-2.38/ld/emulparams/elf_x86_64_luna.sh 2022-11-09 16:09:46.145869977 +0100 -@@ -0,0 +1,2 @@ -+source_sh ${srcdir}/emulparams/elf_x86_64.sh -+MAXPAGESIZE=0x1000 -\ No newline at end of file -diff --color -rN -u binutils-2.38/ld/Makefile.am binutils-2.38/ld/Makefile.am ---- a/binutils-2.38/ld/Makefile.am 2022-01-22 13:14:09.000000000 +0100 -+++ b/binutils-2.38/ld/Makefile.am 2022-11-09 16:09:46.145869977 +0100 -@@ -278,6 +278,7 @@ - eelf32xtensa.c \ - eelf32z80.c \ - eelf_i386.c \ -+ eelf_i386_luna.c \ - eelf_i386_be.c \ - eelf_i386_fbsd.c \ - eelf_i386_haiku.c \ -@@ -464,6 +465,7 @@ - eelf_x86_64_fbsd.c \ - eelf_x86_64_haiku.c \ - eelf_x86_64_sol2.c \ -+ eelf_x86_64_luna.c \ - ehppa64linux.c \ - ei386pep.c \ - emmo.c -diff --color -rN -u binutils-2.38/ld/Makefile.in binutils-2.38/ld/Makefile.in ---- a/binutils-2.38/ld/Makefile.in 2022-02-09 12:49:03.000000000 +0100 -+++ b/binutils-2.38/ld/Makefile.in 2022-11-09 16:09:46.146869977 +0100 -@@ -769,6 +769,7 @@ - eelf32xtensa.c \ - eelf32z80.c \ - eelf_i386.c \ -+ eelf_i386_luna.c \ - eelf_i386_be.c \ - eelf_i386_fbsd.c \ - eelf_i386_haiku.c \ -@@ -954,6 +955,7 @@ - eelf_x86_64_fbsd.c \ - eelf_x86_64_haiku.c \ - eelf_x86_64_sol2.c \ -+ eelf_x86_64_luna.c \ - ehppa64linux.c \ - ei386pep.c \ - emmo.c -diff --color -rN -u binutils-2.38/libiberty/pex-unix.c binutils-2.38/libiberty/pex-unix.c ---- a/binutils-2.38/libiberty/pex-unix.c 2022-01-22 13:14:09.000000000 +0100 -+++ b/binutils-2.38/libiberty/pex-unix.c 2022-11-09 16:25:21.767804963 +0100 -@@ -773,8 +773,10 @@ - { - /* If we are cleaning up when the caller didn't retrieve process - status for some reason, encourage the process to go away. */ -+#ifndef __luna__ - if (done) - kill (pid, SIGTERM); -+#endif - - if (pex_wait (obj, pid, status, time) < 0) - { diff --git a/ports/binutils/package.sh b/ports/binutils/package.sh deleted file mode 100644 index e712b772..00000000 --- a/ports/binutils/package.sh +++ /dev/null @@ -1,48 +0,0 @@ -pkgname="binutils" -pkgver="2.38" -pkgurl="https://ftp.gnu.org/gnu/binutils/binutils-$pkgver.tar.xz" - -pkgmode="web" - -pkgdeps=('gmp' 'mpfr' 'mpc') - -setupdir="$workdir" -builddir="$workdir/build" -installdir="$workdir/build" -srcdir="$workdir/binutils-$pkgver" - -port_unpack() -{ - tar xvf binutils-$pkgver.tar.xz -} - -port_patch() -{ - patch -u -i $portdir/binutils.patch -p 1 -d $workdir -} - -port_configure() -{ - CFLAGS="-ffunction-sections -fdata-sections" LDFLAGS="-Wl,--gc-sections" $srcdir/configure --target=x86_64-luna --prefix="" --disable-werror --disable-nls --disable-dependency-tracking --with-build-sysroot=$LUNA_ROOT/base --host=x86_64-luna -} - -port_build() -{ - make -j$(nproc) -} - -port_install() -{ - make install-strip-binutils - rm -rf $DESTDIR/include/ - rm -rf $DESTDIR/lib/ - rm -rf $DESTDIR/share/ - rm -rf $DESTDIR/x86_64-luna/ - # keep only a few binaries since we only use an initial ramdisk for now, which doesn't like having many of these large binaries - rm -f $DESTDIR/bin/{ar,as,elfedit,gprof,ld,ld.bfd,objcopy,ranlib,strip} -} - -port_uninstall() -{ - rm -f $DESTDIR/bin/{addr2line,c++filt,nm,objdump,readelf,size,strings} -} \ No newline at end of file diff --git a/ports/gmp/gmp.patch b/ports/gmp/gmp.patch deleted file mode 100644 index ab6934dd..00000000 --- a/ports/gmp/gmp.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff --color -rN -u gmp-vanilla/invalid.c gmp-6.2.1/invalid.c ---- a/gmp-6.2.1/invalid.c 2020-11-14 19:45:09.000000000 +0100 -+++ b/gmp-6.2.1/invalid.c 2022-10-26 21:09:20.102237128 +0200 -@@ -77,6 +77,6 @@ - void - __gmp_invalid_operation (void) - { -- raise (SIGFPE); -+// raise (SIGFPE); - abort (); - } diff --git a/ports/gmp/package.sh b/ports/gmp/package.sh deleted file mode 100644 index d8fde85b..00000000 --- a/ports/gmp/package.sh +++ /dev/null @@ -1,44 +0,0 @@ -pkgname="gmp" -pkgver="6.2.1" -pkgurl="https://ftp.gnu.org/gnu/gmp/gmp-$pkgver.tar.xz" - -pkgmode="web" - -islib=1 - -setupdir="$workdir" -builddir="$workdir/build" -installdir="$workdir/build" -srcdir="$workdir/gmp-$pkgver" - -port_unpack() -{ - tar xvf gmp-$pkgver.tar.xz -} - -port_patch() -{ - patch -u -i $portdir/gmp.patch -p 1 -d $workdir -} - -port_configure() -{ - CC_FOR_BUILD=gcc $srcdir/configure --enable-shared=no --with-gnu-ld --host=x86_64-luna --prefix=/usr -} - -port_build() -{ - make -j$(nproc) -} - -port_install() -{ - make DESTDIR=$LUNA_BASE install - rm -f $LUNA_BASE/usr/lib/*.la -} - -port_uninstall() -{ - make DESTDIR=$LUNA_BASE uninstall - rm -f $LUNA_BASE/usr/lib/libgmp.a -} \ No newline at end of file diff --git a/ports/list-ports.sh b/ports/list-ports.sh deleted file mode 100755 index d812c1fe..00000000 --- a/ports/list-ports.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd $(dirname $0)/.. - -source tools/env.sh - -cd ports - -unset_vars() -{ - unset pkgname - unset pkgver - unset pkgurl - unset pkgmode - unset setupdir - unset builddir - unset installdir - unset srcdir - unset port_unpack - unset port_patch - unset port_configure - unset port_build - unset port_install - unset port_uninstall -} - -if ! [ -f ./ports.list ] -then - echo "No ports installed." - exit 0 -fi - -export HAVE_PORTS=0 - -install_port() -{ - HAVE_PORTS=1 - unset_vars - cd $LUNA_ROOT/ports - export DESTDIR=${DESTDIR:-"$LUNA_ROOT/initrd"} - export portdir=$PWD/$1 - export workdir=$portdir/workdir - source $portdir/package.sh - echo "$pkgname $pkgver" -} - -while read package; do - install_port $package -done < ./ports.list - -if [ "$HAVE_PORTS" = "0" ] -then - echo "No ports installed." -fi \ No newline at end of file diff --git a/ports/make-package.sh b/ports/make-package.sh deleted file mode 100755 index 41424b89..00000000 --- a/ports/make-package.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source $(dirname $0)/../tools/env.sh - -export DESTDIR=$PWD/pkgroot -export SKIP_ADD_TO_PORTS_LIST=1 - -source $LUNA_ROOT/ports/$1/package.sh - -mkdir pkgroot - -$LUNA_ROOT/ports/add-port.sh $pkgname - -cd pkgroot - -tar cJf ../$pkgname-$pkgver.pkg.tar.xz * - -cd - - -rm -rf pkgroot - -echo "Built package $pkgname-$pkgver.pkg.tar.xz" \ No newline at end of file diff --git a/ports/mpc/package.sh b/ports/mpc/package.sh deleted file mode 100644 index d28aaa7d..00000000 --- a/ports/mpc/package.sh +++ /dev/null @@ -1,41 +0,0 @@ -pkgname="mpc" -pkgver="1.2.1" -pkgurl="https://ftp.gnu.org/gnu/mpc/mpc-$pkgver.tar.gz" - -pkgmode="web" - -pkgdeps=('gmp' 'mpfr') - -islib=1 - -setupdir="$workdir" -builddir="$workdir/build" -installdir="$workdir/build" -srcdir="$workdir/mpc-$pkgver" - -port_unpack() -{ - tar xvf mpc-$pkgver.tar.gz -} - -port_configure() -{ - $srcdir/configure --host=x86_64-luna --with-gnu-ld --enable-shared=no --prefix=/usr -} - -port_build() -{ - make -j$(nproc) -} - -port_install() -{ - make DESTDIR=$LUNA_BASE install - rm -f $LUNA_BASE/usr/lib/*.la -} - -port_uninstall() -{ - make DESTDIR=$LUNA_BASE uninstall - rm -f $LUNA_BASE/usr/lib/libmpc.a -} \ No newline at end of file diff --git a/ports/mpfr/package.sh b/ports/mpfr/package.sh deleted file mode 100644 index b9df3d56..00000000 --- a/ports/mpfr/package.sh +++ /dev/null @@ -1,41 +0,0 @@ -pkgname="mpfr" -pkgver="4.1.0" -pkgurl="https://ftp.gnu.org/gnu/mpfr/mpfr-$pkgver.tar.gz" - -pkgmode="web" - -pkgdeps=('gmp') - -islib=1 - -setupdir="$workdir" -builddir="$workdir/build" -installdir="$workdir/build" -srcdir="$workdir/mpfr-$pkgver" - -port_unpack() -{ - tar xvf mpfr-$pkgver.tar.gz -} - -port_configure() -{ - $srcdir/configure --with-gnu-ld --host=x86_64-luna --enable-shared=no --prefix=/usr -} - -port_build() -{ - make -j$(nproc) -} - -port_install() -{ - make DESTDIR=$LUNA_BASE install - rm -f $LUNA_BASE/usr/lib/*.la -} - -port_uninstall() -{ - make DESTDIR=$LUNA_BASE uninstall - rm -f $LUNA_BASE/usr/lib/libmpfr.a -} \ No newline at end of file diff --git a/ports/nasm/nasm.patch b/ports/nasm/nasm.patch deleted file mode 100644 index 49e2d0fc..00000000 --- a/ports/nasm/nasm.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --color -rN -u nasm-vanilla/Makefile.in nasm-2.15.05/Makefile.in ---- a/nasm-2.15.05/Makefile.in 2020-08-28 18:04:43.000000000 +0200 -+++ b/nasm-2.15.05/Makefile.in 2022-10-30 18:00:40.386258721 +0100 -@@ -389,9 +389,6 @@ - $(MKDIR_P) $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) nasm$(X) $(DESTDIR)$(bindir)/nasm$(X) - $(INSTALL_PROGRAM) ndisasm$(X) $(DESTDIR)$(bindir)/ndisasm$(X) -- $(MKDIR_P) $(DESTDIR)$(mandir)/man1 -- $(INSTALL_DATA) $(srcdir)/nasm.1 $(DESTDIR)$(mandir)/man1/nasm.1 -- $(INSTALL_DATA) $(srcdir)/ndisasm.1 $(DESTDIR)$(mandir)/man1/ndisasm.1 - - clean: - for d in . $(SUBDIRS) $(XSUBDIRS); do \ diff --git a/ports/nasm/package.sh b/ports/nasm/package.sh deleted file mode 100644 index baf8787d..00000000 --- a/ports/nasm/package.sh +++ /dev/null @@ -1,41 +0,0 @@ -pkgname="nasm" -pkgver="2.15.05" -pkgurl="https://www.nasm.us/pub/nasm/releasebuilds/$pkgver/nasm-$pkgver.tar.gz" - -pkgmode="web" - -setupdir="$workdir" -builddir="$workdir/build" -installdir="$workdir/build" -srcdir="$workdir/nasm-$pkgver" - -port_unpack() -{ - tar xvf nasm-$pkgver.tar.gz -} - -port_patch() -{ - patch -u -i $portdir/nasm.patch -p 1 -d $workdir -} - -port_configure() -{ - $srcdir/configure --host=x86_64-luna --prefix="" -} - -port_build() -{ - make -j$(nproc) -} - -port_install() -{ - make install - $STRIP $DESTDIR/bin/{nasm,ndisasm} -} - -port_uninstall() # nasm's Makefile does not provide an uninstall target. -{ - rm -f $DESTDIR/bin/{nasm,ndisasm} -} \ No newline at end of file diff --git a/ports/remove-port.sh b/ports/remove-port.sh deleted file mode 100755 index 22cc8240..00000000 --- a/ports/remove-port.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd $(dirname $0)/.. - -source tools/env.sh - -cd ports - -export DESTDIR=${DESTDIR:-"$LUNA_ROOT/initrd"} -export listdir=$PWD - -if [ -z $1 ] -then - echo "Usage: remove-port.sh " - exit 1 -fi - -if [ -d $1 ] -then - pkgscript=$1/package.sh -elif [ -f $1 ] -then - pkgscript=$1 -else - echo "Unrecognized argument: $1" - exit 1 -fi - -export portdir=$(realpath $(dirname $pkgscript)) -export workdir=$portdir/workdir -mkdir -p $workdir - -source $pkgscript - -echo "Removing $pkgname version $pkgver..." - -cd $installdir -port_uninstall | filter-lines $pkgname "uninstall" - -rm -rf $workdir -cat $listdir/ports.list | grep -v $pkgname | tee $listdir/ports.list >/dev/null - -echo "Success! Removed port: $pkgname version $pkgver." \ No newline at end of file diff --git a/tests/Makefile b/tests/Makefile deleted file mode 100644 index 38f21741..00000000 --- a/tests/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -build: - make -C libc build - -install: - make -C libc install - -test: - make -C libc test - \ No newline at end of file diff --git a/tests/Test.h b/tests/Test.h deleted file mode 100644 index 4836e95f..00000000 --- a/tests/Test.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __TEST_H_ -#define __TEST_H_ -#include - -int printf(const char*, ...); - -#define DEFINE_TEST(name) bool test_##name() -#define START_TEST(name) printf("testing whether %s works... ", #name) -#define START_TEST_CASE(name) printf("testing %s...\n", #name) - -#define TEST_SUCCESS() \ - do { \ - printf("yes!\n"); \ - return true; \ - } while (0) - -#define TEST_FAIL(expr) \ - do { \ - printf("no (%s)\n", #expr); \ - return false; \ - } while (0) - -#define TEST_NOT_SURE(expr) \ - do { \ - printf("not sure (%s)\n", #expr); \ - return true; \ - } while (0) - -#define EXPECT(expr) \ - do { \ - if (!(expr)) { TEST_FAIL(expr); } \ - } while (0) - -#define EXPECT_EQ(a, b) EXPECT((a) == (b)) - -#define EXPECT_NOT_EQ(a, b) EXPECT((a) != (b)) - -#define EXPECT_NOT_CRASHED() TEST_SUCCESS() - -#define RUN_TEST(name) \ - do { \ - if (!test_##name()) return 1; \ - } while (0) - -#endif \ No newline at end of file diff --git a/tests/libc/Makefile b/tests/libc/Makefile deleted file mode 100644 index 698044bc..00000000 --- a/tests/libc/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -TESTDIR := $(LUNA_ROOT)/tests/libc -DESTDIR := $(LUNA_ROOT)/initrd/bin - -build: - @mkdir -p $(TESTDIR)/bin - $(LUNA_ROOT)/tools/sync-libc.sh - $(CC) $(TESTDIR)/string.c $(TESTDIR)/stdlib.c $(TESTDIR)/wchar.c $(TESTDIR)/Test.c -I$(LUNA_ROOT)/tests -o $(TESTDIR)/bin/test-libc -Wall -Wextra -Wno-deprecated-declarations -Wno-stringop-overread -Werror - -install: - $(LUNA_ROOT)/tools/clean.sh - @mkdir -p $(DESTDIR) - cp $(TESTDIR)/bin/test-libc $(DESTDIR)/test-libc - -test: - CFLAGS="-DRUN_TEST_AS_INIT=/bin/test-libc" $(LUNA_ROOT)/tools/run.sh \ No newline at end of file diff --git a/tests/libc/Test.c b/tests/libc/Test.c deleted file mode 100644 index afc9b17d..00000000 --- a/tests/libc/Test.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "Test.h" - -// string.h -DEFINE_TEST(memset); -DEFINE_TEST(memcpy); -DEFINE_TEST(memchr); -DEFINE_TEST(memcmp); -DEFINE_TEST(memmove); -DEFINE_TEST(strlen); -DEFINE_TEST(strnlen); -DEFINE_TEST(strcmp); -DEFINE_TEST(strncmp); -DEFINE_TEST(strcspn); -DEFINE_TEST(strspn); -DEFINE_TEST(strchr); -DEFINE_TEST(strchrnul); -DEFINE_TEST(strrchr); -DEFINE_TEST(strpbrk); -DEFINE_TEST(strdup); -DEFINE_TEST(strndup); - -// stdlib.h -DEFINE_TEST(atoi); -DEFINE_TEST(atol); -DEFINE_TEST(atoll); -DEFINE_TEST(srand); -DEFINE_TEST(malloc); -DEFINE_TEST(calloc); -DEFINE_TEST(mktemp); -DEFINE_TEST(qsort); -DEFINE_TEST(bsearch); - -// wchar.h -DEFINE_TEST(wcslen); - -int main() -{ - START_TEST_CASE(string.h); - RUN_TEST(memset); - RUN_TEST(memcpy); - RUN_TEST(memchr); - RUN_TEST(memcmp); - RUN_TEST(memmove); - RUN_TEST(strlen); - RUN_TEST(strnlen); - RUN_TEST(strcmp); - RUN_TEST(strncmp); - RUN_TEST(strcspn); - RUN_TEST(strspn); - RUN_TEST(strchr); - RUN_TEST(strchrnul); - RUN_TEST(strrchr); - RUN_TEST(strpbrk); - RUN_TEST(strdup); - RUN_TEST(strndup); - - START_TEST_CASE(stdlib.h); - RUN_TEST(atoi); - RUN_TEST(atol); - RUN_TEST(atoll); - RUN_TEST(srand); - RUN_TEST(malloc); - RUN_TEST(calloc); - RUN_TEST(mktemp); - RUN_TEST(qsort); - RUN_TEST(bsearch); - - START_TEST_CASE(wchar.h); - RUN_TEST(wcslen); -} \ No newline at end of file diff --git a/tests/libc/stdlib.c b/tests/libc/stdlib.c deleted file mode 100644 index d869808c..00000000 --- a/tests/libc/stdlib.c +++ /dev/null @@ -1,234 +0,0 @@ -#include "Test.h" -#include -#include -#include - -DEFINE_TEST(atoi) -{ - START_TEST(atoi); - - const char* str = "42"; - int num = atoi(str); - - EXPECT_EQ(num, 42); - - str = "-56"; - num = atoi(str); - - EXPECT_EQ(num, -56); - - str = "Not a number"; - num = atoi(str); - - EXPECT_EQ(num, 0); - - TEST_SUCCESS(); -} - -DEFINE_TEST(atol) -{ - START_TEST(atol); - - const char* str = "42"; - long num = atol(str); - - EXPECT_EQ(num, 42); - - str = "-56"; - num = atol(str); - - EXPECT_EQ(num, -56); - - str = "Not a number"; - num = atol(str); - - EXPECT_EQ(num, 0); - - str = "68719476735"; - num = atol(str); - - EXPECT_EQ(num, 68719476735); - - TEST_SUCCESS(); -} - -DEFINE_TEST(atoll) -{ - START_TEST(atoll); - - const char* str = "42"; - long long num = atoll(str); - - EXPECT_EQ(num, 42); - - str = "-56"; - num = atoll(str); - - EXPECT_EQ(num, -56); - - str = "Not a number"; - num = atoll(str); - - EXPECT_EQ(num, 0); - - str = "68719476735"; - num = atoll(str); - - EXPECT_EQ(num, 68719476735); - - TEST_SUCCESS(); -} - -DEFINE_TEST(srand) -{ - START_TEST(srand); - - srand(5849); - - int val = rand(); - - EXPECT_EQ(val, -1731894882); - - TEST_SUCCESS(); -} - -DEFINE_TEST(malloc) -{ - START_TEST(malloc); - - int* ptr = malloc(6 * sizeof(int)); - - if (!ptr) - { - TEST_NOT_SURE(ptr); - return true; - } - - *ptr = 6; - - EXPECT_EQ(*ptr, 6); - - ptr[5] = 4; - - EXPECT_EQ(ptr[5], 4); - - free(ptr); - - TEST_SUCCESS(); -} - -DEFINE_TEST(calloc) -{ - START_TEST(calloc); - - int* ptr = calloc(6, sizeof(int)); - - if (!ptr) { TEST_NOT_SURE(ptr); } - - EXPECT_EQ(*ptr, 0); - EXPECT_EQ(ptr[5], 0); - - *ptr = 6; - - EXPECT_EQ(*ptr, 6); - - ptr[5] = 4; - - EXPECT_EQ(ptr[5], 4); - - free(ptr); - - TEST_SUCCESS(); -} - -DEFINE_TEST(mktemp) -{ - START_TEST(mktemp); - - char template[] = "/tmp/file.XXXXXX"; - - const char* template2 = "/tmp/file.XXXXXX"; - - char* ptr = mktemp(template); - - EXPECT_NOT_EQ(ptr, NULL); // mktemp only fails if we give it an invalid template. - - int rc = access(ptr, F_OK); - - EXPECT_NOT_EQ(rc, 0); // FIXME: This could actually happen, since that's why mktemp is deprecated. - // Another process could create the file between generating the name and actually using it. - - rc = strcmp(ptr, template2); - - EXPECT_NOT_EQ(rc, 0); - - TEST_SUCCESS(); -} - -static int compare_char(const void* p1, const void* p2) -{ - const char* c1 = (const char*)p1; - const char* c2 = (const char*)p2; - if (*c1 < *c2) return -1; - if (*c1 > *c2) return 1; - return 0; -} - -static int compare_int(const void* p1, const void* p2) -{ - const int* c1 = (const int*)p1; - const int* c2 = (const int*)p2; - if (*c1 < *c2) return -1; - if (*c1 > *c2) return 1; - return 0; -} - -DEFINE_TEST(qsort) -{ - START_TEST(qsort); - - char unsorted[] = "elacbkdjf"; - const char sorted[] = "abcdefjkl"; - - qsort(unsorted, 9, sizeof(char), compare_char); - - int rc = memcmp(sorted, unsorted, 9); - - EXPECT_EQ(rc, 0); - - int unsorted2[] = {1500, 45, 3, 11, 41, 90, 6, 32, 5, 76}; - const int sorted2[] = {3, 5, 6, 11, 32, 41, 45, 76, 90, 1500}; - - qsort(unsorted2, 10, sizeof(int), compare_int); - - rc = memcmp(unsorted2, sorted2, 10); - - EXPECT_EQ(rc, 0); - - TEST_SUCCESS(); -} - -DEFINE_TEST(bsearch) -{ - START_TEST(bsearch); - - const char sorted[] = "abcdefjkl"; - char key = 'j'; - - char* ptr = bsearch(&key, sorted, 9, sizeof(char), compare_char); // try with sorted array first - - EXPECT_EQ(*ptr, 'j'); - EXPECT_EQ(ptr, &sorted[6]); - - int unsorted[] = {1500, 45, 3, 11, 41, 90, 6, 32, 5, 76}; - qsort(unsorted, 10, sizeof(int), compare_int); - - int key2 = 90; - - int* ptr2 = bsearch(&key2, unsorted, 10, sizeof(int), compare_int); - - EXPECT_EQ(*ptr2, 90); - EXPECT_EQ(ptr2, &unsorted[8]); - - TEST_SUCCESS(); -} \ No newline at end of file diff --git a/tests/libc/string.c b/tests/libc/string.c deleted file mode 100644 index 30a3554e..00000000 --- a/tests/libc/string.c +++ /dev/null @@ -1,385 +0,0 @@ -#include "Test.h" -#include -#include - -DEFINE_TEST(memset) -{ - START_TEST(memset); - - char test[10]; - char* ptr = memset(test, 0, 10); - - EXPECT_EQ(ptr, test); - - for (int i = 0; i < 10; i++) { EXPECT_EQ(test[i], 0); } - - ptr = memset(test, 42, 10); - - EXPECT_EQ(ptr, test); - - for (int i = 0; i < 10; i++) { EXPECT_EQ(test[i], 42); } - - TEST_SUCCESS(); -} - -DEFINE_TEST(memcpy) -{ - START_TEST(memcpy); - - char buf[20] = "Nothing is going on"; - const char* str = "Something is going!"; - - char* ptr = memcpy(buf, str, 20); - - EXPECT_EQ(ptr, buf); - - for (int i = 0; i < 20; i++) { EXPECT_EQ(buf[i], str[i]); } - - const char* new = "Well..."; - - ptr = memcpy(buf, new, 7); - - EXPECT_EQ(ptr, buf); - - for (int i = 0; i < 7; i++) { EXPECT_EQ(buf[i], new[i]); } - for (int i = 7; i < 20; i++) { EXPECT_EQ(buf[i], str[i]); } - - TEST_SUCCESS(); -} - -DEFINE_TEST(memchr) -{ - START_TEST(memchr); - - char buf[20] = "abcdefghijklmnopqrs"; - - char* ptr = memchr(buf, 'z', 20); - - EXPECT_EQ(ptr, NULL); - - ptr = memchr(buf, 'd', 20); - - EXPECT_EQ(ptr, buf + 3); - - ptr = memchr(buf, 's', 20); - - EXPECT_EQ(ptr, buf + 18); - - TEST_SUCCESS(); -} - -DEFINE_TEST(memcmp) -{ - START_TEST(memcmp); - - char buf[20] = "abcdefghijklmnopqrs"; - char buf2[20] = "abcdefghijklmnopqrp"; - - int val = memcmp(buf, buf, 20); - - EXPECT_EQ(val, 0); - - val = memcmp(buf, buf2, 20); - - EXPECT(val > 0); - - val = memcmp(buf2, buf, 20); - - EXPECT(val < 0); - - TEST_SUCCESS(); -} - -DEFINE_TEST(memmove) -{ - START_TEST(memmove); - - char buf[20] = "Nothing is going on"; - const char* str = "Something is going!"; - - char* ptr = memmove(buf, str, 20); - - EXPECT_EQ(ptr, buf); - - for (int i = 0; i < 20; i++) { EXPECT_EQ(buf[i], str[i]); } - - const char* new = "Well..."; - - ptr = memmove(buf, new, 7); - - EXPECT_EQ(ptr, buf); - - for (int i = 0; i < 7; i++) { EXPECT_EQ(buf[i], new[i]); } - for (int i = 7; i < 20; i++) { EXPECT_EQ(buf[i], str[i]); } - - char newbuf[16] = "part_a is part_b"; - char result[16] = "is part_b part_b"; - - ptr = memmove(newbuf, newbuf + 7, 9); - - EXPECT_EQ(ptr, newbuf); - - EXPECT(memcmp(newbuf, result, 16) == 0); // we have tested memcmp at this point - - TEST_SUCCESS(); -} - -DEFINE_TEST(strlen) -{ - START_TEST(strlen); - - const char* str = "Hello, World!"; - - size_t len = strlen(str); - - EXPECT_EQ(len, 13); - - char null[] = {'\0'}; - - len = strlen(null); - - EXPECT_EQ(len, 0); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strnlen) -{ - START_TEST(strnlen); - - const char* str = "What is going on?"; - - size_t len = strnlen(str, 20); - - EXPECT_EQ(len, 17); - - len = strnlen(str, 15); - - EXPECT_EQ(len, 15); - - char buf[] = {'H', 'e', 'l', 'l', 'o'}; - - len = strnlen(buf, sizeof(buf)); - - EXPECT_EQ(len, sizeof(buf)); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strcmp) -{ - START_TEST(strcmp); - - const char* str1 = "Hello, World!"; - const char* str2 = "Hello, Planet!"; - - int rc = strcmp(str1, str1); - - EXPECT_EQ(rc, 0); - - rc = strcmp(str1, str2); - - EXPECT(rc > 0); - - rc = strcmp(str2, str1); - - EXPECT(rc < 0); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strncmp) -{ - START_TEST(strncmp); - - const char* str1 = "Hello, World!"; - const char* str2 = "Hello, Planet!"; - - int rc = strncmp(str1, str1, 14); - - EXPECT_EQ(rc, 0); - - rc = strncmp(str1, str2, 14); - - EXPECT(rc > 0); - - rc = strncmp(str2, str1, 14); - - EXPECT(rc < 0); - - rc = strncmp(str1, str2, 6); - - EXPECT_EQ(rc, 0); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strcspn) -{ - START_TEST(strcspn); - - const char* str = "This string has vowels"; - const char* vowels = "aeiou"; - - size_t len = strcspn(str, vowels); - - EXPECT_EQ(len, 2); - - str = "WWWWW"; - len = strcspn(str, vowels); - - EXPECT_EQ(len, 5); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strspn) -{ - START_TEST(strspn); - - const char* str = "This is a test string"; - const char* accept = "This "; - - size_t len = strspn(str, accept); - - EXPECT_EQ(len, 8); - - str = "WWWWW"; - len = strspn(str, accept); - - EXPECT_EQ(len, 0); - - str = "This is hi"; - len = strspn(str, accept); - - EXPECT_EQ(len, 10); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strchr) -{ - START_TEST(strchr); - - const char* str = "Hello, world!"; - - char* ptr = strchr(str, 'l'); - - EXPECT_EQ(ptr, str + 2); - - ptr = strchr(str, 'u'); - - EXPECT_EQ(ptr, NULL); - - ptr = strchr(str, '!'); - - EXPECT_EQ(ptr, str + 12); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strchrnul) -{ - START_TEST(strchrnul); - - const char* str = "Hello, world!"; - - char* ptr = strchrnul(str, 'l'); - - EXPECT_EQ(ptr, str + 2); - - ptr = strchrnul(str, 'u'); - - EXPECT_EQ(ptr, str + 13); - - ptr = strchrnul(str, '!'); - - EXPECT_EQ(ptr, str + 12); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strrchr) -{ - START_TEST(strrchr); - - const char* str = "Hello, world!"; - - char* ptr = strrchr(str, 'l'); - - EXPECT_EQ(ptr, str + 10); - - ptr = strrchr(str, 'u'); - - EXPECT_EQ(ptr, NULL); - - ptr = strrchr(str, '!'); - - EXPECT_EQ(ptr, str + 12); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strpbrk) -{ - START_TEST(strpbrk); - - const char* str = "Hello, world!"; - const char* vowels = "aeiou"; - - char* ptr = strpbrk(str, vowels); - - EXPECT_EQ(ptr, str + 1); - - str = "There are more vowels"; - ptr = strpbrk(str, vowels); - - EXPECT_EQ(ptr, str + 2); - - str = "zzzzzz"; - ptr = strpbrk(str, vowels); - - EXPECT_EQ(ptr, NULL); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strdup) -{ - START_TEST(strdup); - - const char* orig = "Well hello there!"; - - char* copy = strdup(orig); - if (!copy) { TEST_NOT_SURE(copy); } - - EXPECT(memcmp(orig, copy, 17) == 0); - - free(copy); - - TEST_SUCCESS(); -} - -DEFINE_TEST(strndup) -{ - START_TEST(strndup); - - const char* orig = "Well hello there!"; - - char* copy = strndup(orig, 17); - if (!copy) { TEST_NOT_SURE(copy); } - - EXPECT(memcmp(orig, copy, 17) == 0); - - free(copy); - - copy = strndup(orig, 12); - if (!copy) { TEST_NOT_SURE(copy); } - - EXPECT_NOT_EQ(memcmp(orig, copy, 14), - 0); // FIXME: This is undefined behaviour and the memory could also be by chance identical. - - free(copy); - - TEST_SUCCESS(); -} \ No newline at end of file diff --git a/tests/libc/wchar.c b/tests/libc/wchar.c deleted file mode 100644 index bec6dc7e..00000000 --- a/tests/libc/wchar.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "Test.h" -#include - -DEFINE_TEST(wcslen) -{ - START_TEST(wcslen); - - const wchar_t* str = L"Hello, World!"; - - size_t len = wcslen(str); - - EXPECT_EQ(len, 13); - - wchar_t null[] = {L'\0'}; - - len = wcslen(null); - - EXPECT_EQ(len, 0); - - TEST_SUCCESS(); -} \ No newline at end of file From 82c2381ac9660c724e56a79d7351ee732b603b19 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 10:30:10 +0100 Subject: [PATCH 005/407] Serial printing!! --- kernel/CMakeLists.txt | 9 +++++ kernel/src/arch/Serial.cpp | 20 ++++++++++ kernel/src/arch/Serial.h | 10 +++++ kernel/src/arch/x86_64/IO.cpp | 40 +++++++++++++++++++ kernel/src/arch/x86_64/IO.h | 13 +++++++ kernel/src/arch/x86_64/Serial.cpp | 15 +++++++ kernel/src/main.cpp | 4 +- kernel/src/string.cpp | 5 +++ luna/String.h | 65 +++++++++++++++++++++++++++++++ luna/Types.h | 1 + 10 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 kernel/src/arch/Serial.cpp create mode 100644 kernel/src/arch/Serial.h create mode 100644 kernel/src/arch/x86_64/IO.cpp create mode 100644 kernel/src/arch/x86_64/IO.h create mode 100644 kernel/src/arch/x86_64/Serial.cpp create mode 100644 kernel/src/string.cpp create mode 100644 luna/String.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 70bf59ca..18553a08 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,5 +1,13 @@ set(SOURCES src/main.cpp + src/string.cpp + src/arch/Serial.cpp +) + +set(SOURCES + ${SOURCES} + src/arch/x86_64/IO.cpp + src/arch/x86_64/Serial.cpp ) add_compile_options(-Os) @@ -20,6 +28,7 @@ add_link_options(-lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mno-red-zone add_executable(moon ${SOURCES}) target_include_directories(moon PUBLIC ${LUNA_ROOT}/luna) +target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) target_link_options(moon PRIVATE LINKER:-T ${CMAKE_CURRENT_LIST_DIR}/moon.ld -nostdlib -nodefaultlibs) diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp new file mode 100644 index 00000000..958557f6 --- /dev/null +++ b/kernel/src/arch/Serial.cpp @@ -0,0 +1,20 @@ +#include "arch/Serial.h" + +namespace Serial +{ + void write(const char* str, size_t size) + { + while (size--) putchar(*str++); + } + + void print(const char* str) + { + while (*str) putchar(*str++); + } + + void println(const char* str) + { + print(str); + putchar('\n'); + } +} \ No newline at end of file diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h new file mode 100644 index 00000000..031aaac0 --- /dev/null +++ b/kernel/src/arch/Serial.h @@ -0,0 +1,10 @@ +#pragma once +#include + +namespace Serial +{ + void putchar(u8 c); + void write(const char* str, size_t size); + void print(const char* str); + void println(const char* str); +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/IO.cpp b/kernel/src/arch/x86_64/IO.cpp new file mode 100644 index 00000000..8afa0a08 --- /dev/null +++ b/kernel/src/arch/x86_64/IO.cpp @@ -0,0 +1,40 @@ +#include "arch/x86_64/IO.h" + +namespace IO +{ + u8 inb(u16 port) + { + u8 result; + asm volatile("inb %1, %0" : "=a"(result) : "Nd"(port)); + return result; + } + + void outb(u16 port, u8 value) + { + asm volatile("outb %0, %1" : : "a"(value), "Nd"(port)); + } + + u16 inw(u16 port) + { + u16 result; + asm volatile("inw %1, %0" : "=a"(result) : "Nd"(port)); + return result; + } + + void outw(u16 port, u16 value) + { + asm volatile("outw %0, %1" : : "a"(value), "Nd"(port)); + } + + u32 inl(u16 port) + { + u32 result; + asm volatile("inl %1, %0" : "=a"(result) : "Nd"(port)); + return result; + } + + void outl(u16 port, u32 value) + { + asm volatile("outl %0, %1" : : "a"(value), "Nd"(port)); + } +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/IO.h b/kernel/src/arch/x86_64/IO.h new file mode 100644 index 00000000..05c6acf9 --- /dev/null +++ b/kernel/src/arch/x86_64/IO.h @@ -0,0 +1,13 @@ +#pragma once +#include + +namespace IO +{ + u8 inb(u16 port); + u16 inw(u16 port); + u32 inl(u16 port); + + void outb(u16 port, u8 value); + void outw(u16 port, u16 value); + void outl(u16 port, u32 value); +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/Serial.cpp b/kernel/src/arch/x86_64/Serial.cpp new file mode 100644 index 00000000..3dc26ec4 --- /dev/null +++ b/kernel/src/arch/x86_64/Serial.cpp @@ -0,0 +1,15 @@ +#include "arch/Serial.h" +#include "arch/x86_64/IO.h" + +#define COM1 0x3f8 + +static void serial_wait() +{ + while (!(IO::inb(COM1 + 5) & 0x20)) { asm volatile("pause"); } +} + +void Serial::putchar(u8 c) +{ + serial_wait(); + IO::outb(COM1, c); +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index abf41426..3b529072 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,7 +1,9 @@ -#include +#include "arch/Serial.h" extern "C" void _start() { + Serial::println("Hello, world!"); + for (;;) ; } \ No newline at end of file diff --git a/kernel/src/string.cpp b/kernel/src/string.cpp new file mode 100644 index 00000000..68167cd2 --- /dev/null +++ b/kernel/src/string.cpp @@ -0,0 +1,5 @@ +extern "C" +{ +#define _LUNA_IMPLEMENTATION +#include +} \ No newline at end of file diff --git a/luna/String.h b/luna/String.h new file mode 100644 index 00000000..bba602be --- /dev/null +++ b/luna/String.h @@ -0,0 +1,65 @@ +#pragma once +#include + +void* memcpy(void* dest, const void* src, size_t n) +#ifdef _LUNA_IMPLEMENTATION +{ + for (size_t i = 0; i < n; ++i) { *((u8*)dest + i) = *((const u8*)src + i); } + return dest; +} +#else + ; +#endif + +void* memset(void* buf, int c, size_t n) +#ifdef _LUNA_IMPLEMENTATION +{ + for (size_t i = 0; i < n; ++i) { *((u8*)buf + i) = (u8)c; } + return buf; +} +#else + ; +#endif + +int memcmp(const void* a, const void* b, size_t n) +#ifdef _LUNA_IMPLEMENTATION +{ + if (!n) return 0; + const u8* ap = (const u8*)a; + const u8* bp = (const u8*)b; + while (--n && *ap == *bp) + { + ap++; + bp++; + } + return *ap - *bp; +} +#else + ; +#endif + +void* memmove(void* dest, const void* src, size_t n) +#ifdef _LUNA_IMPLEMENTATION +{ + if (dest == src) return dest; + if (dest > src) + for (long i = n - 1; i >= 0; i++) { *((u8*)dest + i) = *((const u8*)src + i); } + else + for (long i = 0; i < (long)n; i++) { *((u8*)dest + i) = *((const u8*)src + i); } + return dest; +} +#else + ; +#endif + +size_t strlen(const char* str) +#ifdef _LUNA_IMPLEMENTATION +{ + const char* i = str; + for (; *i; ++i) + ; + return (i - str); +} +#else + ; +#endif \ No newline at end of file diff --git a/luna/Types.h b/luna/Types.h index d2dc477b..c45e4448 100644 --- a/luna/Types.h +++ b/luna/Types.h @@ -1,3 +1,4 @@ +#include #include typedef uint8_t u8; From ffbe5260a5d74ea1651e9536ab82f18376138511 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 11:25:15 +0100 Subject: [PATCH 006/407] Add Framebuffer stuff --- kernel/CMakeLists.txt | 3 + kernel/src/Framebuffer.cpp | 83 +++++++++++++++++++ kernel/src/Framebuffer.h | 18 +++++ kernel/src/bootboot.h | 162 +++++++++++++++++++++++++++++++++++++ kernel/src/main.cpp | 5 ++ 5 files changed, 271 insertions(+) create mode 100644 kernel/src/Framebuffer.cpp create mode 100644 kernel/src/Framebuffer.h create mode 100644 kernel/src/bootboot.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 18553a08..c2fa7223 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES src/main.cpp src/string.cpp + src/Framebuffer.cpp src/arch/Serial.cpp ) @@ -27,6 +28,8 @@ add_link_options(-lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mno-red-zone add_executable(moon ${SOURCES}) +set_target_properties(moon PROPERTIES CXX_STANDARD 20) + target_include_directories(moon PUBLIC ${LUNA_ROOT}/luna) target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) diff --git a/kernel/src/Framebuffer.cpp b/kernel/src/Framebuffer.cpp new file mode 100644 index 00000000..6328c33b --- /dev/null +++ b/kernel/src/Framebuffer.cpp @@ -0,0 +1,83 @@ +#include "Framebuffer.h" +#include "bootboot.h" + +static u8* g_fb_ptr = nullptr; +static u32 g_fb_size; +static u32 g_fb_width; +static u32 g_fb_height; +static u32 g_fb_scanline; + +extern BOOTBOOT bootboot; +extern u8 fb[1]; + +namespace Framebuffer +{ + void init() + { + update(fb, bootboot.fb_size, bootboot.fb_width, bootboot.fb_height, bootboot.fb_scanline); + } + + void update(u8* ptr, u32 size, u32 width, u32 height, u32 scanline) + { + g_fb_ptr = ptr; + g_fb_size = size; + g_fb_width = width; + g_fb_height = height; + g_fb_scanline = scanline; + } + + void pixel(u32 x, u32 y, u32 color) + { + if (!g_fb_ptr) [[unlikely]] + return; + *(u32*)(g_fb_ptr + g_fb_scanline * y + x * 4) = color; + } + + void rect(u32 x, u32 y, u32 w, u32 h, u32 color) + { + if (!g_fb_ptr) [[unlikely]] + return; + for (u32 i = y; i < (y + h); i++) + { + u32* addr = (u32*)(g_fb_ptr + (g_fb_scanline * i) + (x * sizeof(u32))); + for (u32* it = addr; it < (addr + w); it++) *it = color; + } + } + + void rect(u32 x, u32 y, u32 w, u32 h, u32* colors) + { + if (!g_fb_ptr) [[unlikely]] + return; + u32 j = 0; + for (u32 i = y; i < (y + h); i++) + { + u32* addr = (u32*)(g_fb_ptr + (g_fb_scanline * i) + (x * sizeof(u32))); + for (u32* it = addr; it < (addr + w); it++, j++) *it = colors[j]; + } + } + + u8* ptr() + { + return g_fb_ptr; + } + + u32 size() + { + return g_fb_size; + } + + u32 width() + { + return g_fb_width; + } + + u32 height() + { + return g_fb_height; + } + + u32 scanline() + { + return g_fb_scanline; + } +} \ No newline at end of file diff --git a/kernel/src/Framebuffer.h b/kernel/src/Framebuffer.h new file mode 100644 index 00000000..9105f315 --- /dev/null +++ b/kernel/src/Framebuffer.h @@ -0,0 +1,18 @@ +#pragma once +#include + +namespace Framebuffer +{ + void init(); + void update(u8* ptr, u32 size, u32 width, u32 height, u32 scanline); + + void pixel(u32 x, u32 y, u32 color); + void rect(u32 x, u32 y, u32 w, u32 h, u32 color); + void rect(u32 x, u32 y, u32 w, u32 h, u32* colors); + + u8* ptr(); + u32 size(); + u32 width(); + u32 height(); + u32 scanline(); +} \ No newline at end of file diff --git a/kernel/src/bootboot.h b/kernel/src/bootboot.h new file mode 100644 index 00000000..8ac1207e --- /dev/null +++ b/kernel/src/bootboot.h @@ -0,0 +1,162 @@ +/* + * bootboot.h + * https://gitlab.com/bztsrc/bootboot + * + * Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This file is part of the BOOTBOOT Protocol package. + * @brief The BOOTBOOT structure + * + */ + +#ifndef _BOOTBOOT_H_ +#define _BOOTBOOT_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +#ifndef _MSC_VER +#define _pack __attribute__((packed)) +#else +#define _pack +#pragma pack(push) +#pragma pack(1) +#endif + +#define BOOTBOOT_MAGIC "BOOT" + +/* default virtual addresses for level 0 and 1 static loaders */ +#define BOOTBOOT_MMIO 0xfffffffff8000000 /* memory mapped IO virtual address */ +#define BOOTBOOT_FB 0xfffffffffc000000 /* frame buffer virtual address */ +#define BOOTBOOT_INFO 0xffffffffffe00000 /* bootboot struct virtual address */ +#define BOOTBOOT_ENV 0xffffffffffe01000 /* environment string virtual address */ +#define BOOTBOOT_CORE 0xffffffffffe02000 /* core loadable segment start */ + +/* minimum protocol level: + * hardcoded kernel name, static kernel memory addresses */ +#define PROTOCOL_MINIMAL 0 +/* static protocol level: + * kernel name parsed from environment, static kernel memory addresses */ +#define PROTOCOL_STATIC 1 +/* dynamic protocol level: + * kernel name parsed, kernel memory addresses from ELF or PE symbols */ +#define PROTOCOL_DYNAMIC 2 +/* big-endian flag */ +#define PROTOCOL_BIGENDIAN 0x80 + +/* loader types, just informational */ +#define LOADER_BIOS (0 << 2) +#define LOADER_UEFI (1 << 2) +#define LOADER_RPI (2 << 2) +#define LOADER_COREBOOT (3 << 2) + +/* framebuffer pixel format, only 32 bits supported */ +#define FB_ARGB 0 +#define FB_RGBA 1 +#define FB_ABGR 2 +#define FB_BGRA 3 + + /* mmap entry, type is stored in least significant tetrad (half byte) of size + * this means size described in 16 byte units (not a problem, most modern + * firmware report memory in pages, 4096 byte units anyway). */ + typedef struct + { + uint64_t ptr; + uint64_t size; + } _pack MMapEnt; +#define MMapEnt_Ptr(a) ((a)->ptr) +#define MMapEnt_Size(a) ((a)->size & 0xFFFFFFFFFFFFFFF0) +#define MMapEnt_Type(a) ((a)->size & 0xF) +#define MMapEnt_IsFree(a) (((a)->size & 0xF) == 1) + +#define MMAP_USED 0 /* don't use. Reserved or unknown regions */ +#define MMAP_FREE 1 /* usable memory */ +#define MMAP_ACPI 2 /* acpi memory, volatile and non-volatile as well */ +#define MMAP_MMIO 3 /* memory mapped IO region */ + +#define INITRD_MAXSIZE 16 /* Mb */ + + typedef struct + { + /* first 64 bytes is platform independent */ + uint8_t magic[4]; /* 'BOOT' magic */ + uint32_t size; /* length of bootboot structure, minimum 128 */ + uint8_t protocol; /* 1, static addresses, see PROTOCOL_* and LOADER_* above */ + uint8_t fb_type; /* framebuffer type, see FB_* above */ + uint16_t numcores; /* number of processor cores */ + uint16_t bspid; /* Bootsrap processor ID (Local APIC Id on x86_64) */ + int16_t timezone; /* in minutes -1440..1440 */ + uint8_t datetime[8]; /* in BCD yyyymmddhhiiss UTC (independent to timezone) */ + uint64_t initrd_ptr; /* ramdisk image position and size */ + uint64_t initrd_size; + uint64_t fb_ptr; /* framebuffer pointer and dimensions */ + uint32_t fb_size; + uint32_t fb_width; + uint32_t fb_height; + uint32_t fb_scanline; + + /* the rest (64 bytes) is platform specific */ + union { + struct + { + uint64_t acpi_ptr; + uint64_t smbi_ptr; + uint64_t efi_ptr; + uint64_t mp_ptr; + uint64_t unused0; + uint64_t unused1; + uint64_t unused2; + uint64_t unused3; + } x86_64; + struct + { + uint64_t acpi_ptr; + uint64_t mmio_ptr; + uint64_t efi_ptr; + uint64_t unused0; + uint64_t unused1; + uint64_t unused2; + uint64_t unused3; + uint64_t unused4; + } aarch64; + } arch; + + /* from 128th byte, MMapEnt[], more records may follow */ + MMapEnt mmap; + /* use like this: + * MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++; + * until you reach bootboot->size, while(mmap_ent < bootboot + bootboot->size) */ + } _pack BOOTBOOT; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 3b529072..b2721fe4 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,9 +1,14 @@ +#include "Framebuffer.h" #include "arch/Serial.h" extern "C" void _start() { Serial::println("Hello, world!"); + Framebuffer::init(); + + Framebuffer::rect(0, 0, 200, 200, 0xFF00FF00); + for (;;) ; } \ No newline at end of file From 6b95307b549c78c8244df8cd41f806312b3d98f4 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 12:20:53 +0100 Subject: [PATCH 007/407] Add init --- .gitignore | 3 +- CMakeLists.txt | 1 - Makefile | 26 ----- kernel/CMakeLists.txt | 1 + kernel/src/Init.cpp | 22 ++++ kernel/src/Init.h | 7 ++ kernel/src/main.cpp | 6 +- kernel/src/string.cpp | 5 +- luna/Move.h | 6 + luna/PlacementNew.h | 13 +++ luna/Result.h | 234 +++++++++++++++++++++++++++++++++++++++ luna/String.h | 95 +++++++++------- tools/build-iso.sh | 11 +- tools/build.sh | 9 +- tools/buildstep.sh | 10 -- tools/env.sh | 12 +- tools/install-headers.sh | 5 +- tools/install.sh | 2 +- tools/test.sh | 10 -- 19 files changed, 362 insertions(+), 116 deletions(-) delete mode 100644 Makefile create mode 100644 kernel/src/Init.cpp create mode 100644 kernel/src/Init.h create mode 100644 luna/Move.h create mode 100644 luna/PlacementNew.h create mode 100644 luna/Result.h delete mode 100755 tools/buildstep.sh delete mode 100755 tools/test.sh diff --git a/.gitignore b/.gitignore index 1a09d8ef..616233bd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ Luna.iso toolchain/ .vscode/ build/ -initrd/boot/moon \ No newline at end of file +initrd/boot/moon +env-local.sh \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 97cc6d2b..38fe3a8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.8..3.22) set(CMAKE_C_COMPILER_WORKS 1) set(CMAKE_CXX_COMPILER_WORKS 1) -set(CMAKE_SYSTEM_NAME Luna) set(CMAKE_CROSSCOMPILING true) project(Luna LANGUAGES C CXX ASM) diff --git a/Makefile b/Makefile deleted file mode 100644 index 2eb69633..00000000 --- a/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -CC := x86_64-luna-gcc -CXX := x86_64-luna-g++ -ASM := nasm -AR := x86_64-luna-ar -LD := x86_64-luna-ld - -build: - +@tools/sync-libc.sh - +@tools/buildstep.sh kernel build - +@tools/buildstep.sh libs build - +@tools/buildstep.sh apps build - -clean: initrd-clean - +@tools/buildstep.sh kernel clean - +@tools/buildstep.sh libs clean - +@tools/buildstep.sh apps clean - -initrd-clean: - rm -f $(LUNA_ROOT)/initrd/boot/moon $(LUNA_ROOT)/Luna.iso - rm -rf $(LUNA_ROOT)/initrd/bin - -install: - +@tools/buildstep.sh kernel install - +@tools/buildstep.sh libs install - +@tools/buildstep.sh apps install - +@tools/install-built-ports.sh \ No newline at end of file diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index c2fa7223..592841e1 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES src/main.cpp src/string.cpp src/Framebuffer.cpp + src/Init.cpp src/arch/Serial.cpp ) diff --git a/kernel/src/Init.cpp b/kernel/src/Init.cpp new file mode 100644 index 00000000..872d55d4 --- /dev/null +++ b/kernel/src/Init.cpp @@ -0,0 +1,22 @@ +#include "Init.h" +#include "Framebuffer.h" +#include "arch/Serial.h" +#include "bootboot.h" +#include + +extern BOOTBOOT bootboot; + +void Init::check_magic() +{ + if (memcmp(bootboot.magic, BOOTBOOT_MAGIC, 4)) + { + Serial::println("ERROR: Invalid magic value from bootloader"); + for (;;) + ; + } +} + +void Init::early_init() +{ + Framebuffer::init(); +} \ No newline at end of file diff --git a/kernel/src/Init.h b/kernel/src/Init.h new file mode 100644 index 00000000..5c5479c1 --- /dev/null +++ b/kernel/src/Init.h @@ -0,0 +1,7 @@ +#pragma once + +namespace Init +{ + void early_init(); + void check_magic(); +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index b2721fe4..0668b1bd 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,11 +1,13 @@ #include "Framebuffer.h" +#include "Init.h" #include "arch/Serial.h" extern "C" void _start() { - Serial::println("Hello, world!"); + Init::check_magic(); + Init::early_init(); - Framebuffer::init(); + Serial::println("Hello, world!"); Framebuffer::rect(0, 0, 200, 200, 0xFF00FF00); diff --git a/kernel/src/string.cpp b/kernel/src/string.cpp index 68167cd2..7c431e6c 100644 --- a/kernel/src/string.cpp +++ b/kernel/src/string.cpp @@ -1,5 +1,2 @@ -extern "C" -{ #define _LUNA_IMPLEMENTATION -#include -} \ No newline at end of file +#include \ No newline at end of file diff --git a/luna/Move.h b/luna/Move.h new file mode 100644 index 00000000..9006d68a --- /dev/null +++ b/luna/Move.h @@ -0,0 +1,6 @@ +#pragma once + +template inline T&& move(T& lvalue) +{ + return (T &&) lvalue; +} \ No newline at end of file diff --git a/luna/PlacementNew.h b/luna/PlacementNew.h new file mode 100644 index 00000000..1e6afcd1 --- /dev/null +++ b/luna/PlacementNew.h @@ -0,0 +1,13 @@ +#pragma once +#include + +inline void* operator new(size_t, void* p) noexcept +{ + return p; +} +inline void* operator new[](size_t, void* p) noexcept +{ + return p; +} +inline void operator delete(void*, void*) noexcept {}; +inline void operator delete[](void*, void*) noexcept {}; \ No newline at end of file diff --git a/luna/Result.h b/luna/Result.h new file mode 100644 index 00000000..c2e79d6c --- /dev/null +++ b/luna/Result.h @@ -0,0 +1,234 @@ +#pragma once +#include +#include +#include + +struct Error +{ + Error(int err) + { + error = err; + } + + int error; +}; + +template class Result +{ + public: + Result(const T& value) + { + m_storage.store_reference(value); + m_has_value = true; + m_has_error = false; + } + + Result(T&& value) + { + m_storage.store_movable_reference(value); + m_has_value = true; + m_has_error = false; + } + + Result(const Result& other) + { + if (!other.m_has_error) + { + m_storage.store_reference(other.m_storage.fetch_reference()); + m_has_value = true; + m_has_error = false; + } + else + { + m_has_error = true; + m_has_value = false; + m_error = other.m_error; + } + } + + Result(Result&& other) + { + if (!other.m_has_error) + { + m_storage.store_movable_reference(move(other.m_storage.fetch_reference())); + m_has_value = true; + m_has_error = false; + } + else + { + m_has_error = true; + m_has_value = false; + m_error = other.m_error; + } + } + + Result(const Error& err) + { + m_error = err.error; + m_has_error = true; + m_has_value = false; + } + + bool has_error() + { + return m_has_error; + } + + bool has_value() + { + return m_has_value; + } + + int error() + { + // ensure(has_error()); + return m_error; + } + + Error release_error() + { + // ensure(has_error()); + return {m_error}; + } + + T value() + { + // ensure(has_value()); + return m_storage.fetch_reference(); + } + + T value_or(T other) + { + if (has_value()) return m_storage.fetch_reference(); + return other; + } + + T release_value() + { + // ensure(has_value()); + T item = m_storage.fetch_reference(); + m_has_value = false; + m_storage.destroy(); + return move(item); + } + + ~Result() + { + if (has_value()) m_storage.destroy(); + } + + private: + struct Storage + { + u8 buffer[sizeof(T)]; + + T* fetch_ptr() + { + return (T*)buffer; + } + + T& fetch_reference() + { + return *fetch_ptr(); + } + + const T* fetch_ptr() const + { + return (const T*)buffer; + } + + const T& fetch_reference() const + { + return *fetch_ptr(); + } + + void store_ptr(T* ptr) + { + new (buffer) T(*ptr); + } + + void store_reference(const T& ref) + { + new (buffer) T(ref); + } + + void store_movable_reference(T&& ref) + { + new (buffer) T(ref); + } + + void destroy() + { + fetch_reference().~T(); + } + }; + Storage m_storage; + int m_error; + bool m_has_error; + bool m_has_value; +}; + +template <> class Result +{ + public: + Result() + { + m_has_error = false; + } + + Result(const Result& other) + { + m_has_error = other.m_has_error; + m_error = other.m_error; + } + + Result(Result&& other) + { + m_has_error = other.m_has_error; + m_error = other.m_error; + } + + Result(const Error& err) + { + m_error = err.error; + m_has_error = true; + } + + bool has_error() + { + return m_has_error; + } + + bool has_value() + { + return !m_has_error; + } + + int error() + { + // ensure(has_error()); + return m_error; + } + + Error release_error() + { + // ensure(has_error()); + return {m_error}; + } + + void value() + { + // ensure(has_value()); + return; + } + + void release_value() + { + // ensure(has_value()); + return; + } + + private: + int m_error; + bool m_has_error; +}; \ No newline at end of file diff --git a/luna/String.h b/luna/String.h index bba602be..9bfc8230 100644 --- a/luna/String.h +++ b/luna/String.h @@ -1,65 +1,74 @@ #pragma once #include -void* memcpy(void* dest, const void* src, size_t n) -#ifdef _LUNA_IMPLEMENTATION +#ifndef NO_EXTERN_C +extern "C" { - for (size_t i = 0; i < n; ++i) { *((u8*)dest + i) = *((const u8*)src + i); } - return dest; -} -#else - ; #endif -void* memset(void* buf, int c, size_t n) + void* memcpy(void* dest, const void* src, size_t n) #ifdef _LUNA_IMPLEMENTATION -{ - for (size_t i = 0; i < n; ++i) { *((u8*)buf + i) = (u8)c; } - return buf; -} -#else - ; -#endif - -int memcmp(const void* a, const void* b, size_t n) -#ifdef _LUNA_IMPLEMENTATION -{ - if (!n) return 0; - const u8* ap = (const u8*)a; - const u8* bp = (const u8*)b; - while (--n && *ap == *bp) { - ap++; - bp++; + for (size_t i = 0; i < n; ++i) { *((u8*)dest + i) = *((const u8*)src + i); } + return dest; } - return *ap - *bp; -} #else ; #endif -void* memmove(void* dest, const void* src, size_t n) + void* memset(void* buf, int c, size_t n) #ifdef _LUNA_IMPLEMENTATION -{ - if (dest == src) return dest; - if (dest > src) - for (long i = n - 1; i >= 0; i++) { *((u8*)dest + i) = *((const u8*)src + i); } - else - for (long i = 0; i < (long)n; i++) { *((u8*)dest + i) = *((const u8*)src + i); } - return dest; -} + { + for (size_t i = 0; i < n; ++i) { *((u8*)buf + i) = (u8)c; } + return buf; + } #else ; #endif -size_t strlen(const char* str) + int memcmp(const void* a, const void* b, size_t n) #ifdef _LUNA_IMPLEMENTATION -{ - const char* i = str; - for (; *i; ++i) - ; - return (i - str); -} + { + if (!n) return 0; + const u8* ap = (const u8*)a; + const u8* bp = (const u8*)b; + while (--n && *ap == *bp) + { + ap++; + bp++; + } + return *ap - *bp; + } #else ; +#endif + + void* memmove(void* dest, const void* src, size_t n) +#ifdef _LUNA_IMPLEMENTATION + { + if (dest == src) return dest; + if (dest > src) + for (long i = n - 1; i >= 0; i++) { *((u8*)dest + i) = *((const u8*)src + i); } + else + for (long i = 0; i < (long)n; i++) { *((u8*)dest + i) = *((const u8*)src + i); } + return dest; + } +#else + ; +#endif + + size_t strlen(const char* str) +#ifdef _LUNA_IMPLEMENTATION + { + const char* i = str; + for (; *i; ++i) + ; + return (i - str); + } +#else + ; +#endif + +#ifndef NO_EXTERN_C +} #endif \ No newline at end of file diff --git a/tools/build-iso.sh b/tools/build-iso.sh index c810c1e9..ac9c3c6e 100755 --- a/tools/build-iso.sh +++ b/tools/build-iso.sh @@ -7,9 +7,14 @@ cd $LUNA_ROOT tools/setup.sh -tools/install-headers.sh +#tools/install-headers.sh -make -j$(nproc) -make install +mkdir -p build +if [ "$USE_NINJA" = "1" ] +then +cmake -S . -B build -G Ninja +fi +cmake --build build +cmake --install build mkbootimg luna.json Luna.iso \ No newline at end of file diff --git a/tools/build.sh b/tools/build.sh index 0d0e5d9e..b5855836 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -7,6 +7,11 @@ cd $LUNA_ROOT tools/setup.sh -tools/install-headers.sh +#tools/install-headers.sh -make -j$(nproc) \ No newline at end of file +mkdir -p build +if [ "$USE_NINJA" = "1" ] +then +cmake -S . -B build -G Ninja +fi +cmake --build build \ No newline at end of file diff --git a/tools/buildstep.sh b/tools/buildstep.sh deleted file mode 100755 index fe06e0d3..00000000 --- a/tools/buildstep.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -set -e - -unset -f filter-lines -filter-lines() -{ - sed $'s|^|\x1b[33m('"$1/$2"$')\x1b[39m |' -} - -make -C $1 $2 | filter-lines $1 $2 \ No newline at end of file diff --git a/tools/env.sh b/tools/env.sh index 4a9e8061..6d99f72b 100755 --- a/tools/env.sh +++ b/tools/env.sh @@ -3,14 +3,4 @@ export LUNA_ROOT=${LUNA_ROOT:-$(realpath $(dirname $0)/..)} export LUNA_BASE=${LUNA_BASE:-$LUNA_ROOT/base} export PATH=$LUNA_ROOT/toolchain/x86-64-luna/bin:$LUNA_ROOT/toolchain/dist:$PATH -export CC=x86_64-luna-gcc -export CXX=x86_64-luna-g++ -export LD=x86_64-luna-ld -export AR=x86_64-luna-ar -export ASM=nasm -export STRIP=x86_64-luna-strip - -filter-lines() -{ - sed $'s|^|\x1b[32m('"$1/$2"$')\x1b[39m |' -} \ No newline at end of file +[ -f "$LUNA_ROOT/env-local.sh" ] && source $LUNA_ROOT/env-local.sh \ No newline at end of file diff --git a/tools/install-headers.sh b/tools/install-headers.sh index cbacbd09..eed3b849 100755 --- a/tools/install-headers.sh +++ b/tools/install-headers.sh @@ -8,6 +8,7 @@ cd $LUNA_ROOT mkdir -p base mkdir -p base/usr/include mkdir -p base/usr/include/moon +mkdir -p base/usr/include/luna -cp -RT libs/libc/include base/usr/include -cp -RT kernel/include base/usr/include/moon \ No newline at end of file +cp -RT kernel/**/*.h base/usr/include/moon +cp -RT luna/*.h base/usr/include/luna \ No newline at end of file diff --git a/tools/install.sh b/tools/install.sh index 7b903dc2..99247915 100755 --- a/tools/install.sh +++ b/tools/install.sh @@ -5,4 +5,4 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -make install \ No newline at end of file +cmake --install build \ No newline at end of file diff --git a/tools/test.sh b/tools/test.sh deleted file mode 100755 index d73fd091..00000000 --- a/tools/test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e -source $(dirname $0)/env.sh - -cd $LUNA_ROOT - -make -C tests build -make -C tests install -make -C tests test \ No newline at end of file From 705c2747de43fdb08d0d9be2246b1485d7fcc469 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 14:29:15 +0100 Subject: [PATCH 008/407] Add memory manager --- kernel/CMakeLists.txt | 2 + kernel/src/Init.cpp | 2 + kernel/src/MemoryManager.cpp | 142 +++++++++++++++++++ kernel/src/MemoryManager.h | 14 ++ kernel/src/arch/MMU.h | 33 +++++ kernel/src/arch/x86_64/MMU.cpp | 248 +++++++++++++++++++++++++++++++++ kernel/src/main.cpp | 5 + luna/Result.h | 8 +- 8 files changed, 452 insertions(+), 2 deletions(-) create mode 100644 kernel/src/MemoryManager.cpp create mode 100644 kernel/src/MemoryManager.h create mode 100644 kernel/src/arch/MMU.h create mode 100644 kernel/src/arch/x86_64/MMU.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 592841e1..9e7a3e4f 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES src/main.cpp src/string.cpp src/Framebuffer.cpp + src/MemoryManager.cpp src/Init.cpp src/arch/Serial.cpp ) @@ -10,6 +11,7 @@ set(SOURCES ${SOURCES} src/arch/x86_64/IO.cpp src/arch/x86_64/Serial.cpp + src/arch/x86_64/MMU.cpp ) add_compile_options(-Os) diff --git a/kernel/src/Init.cpp b/kernel/src/Init.cpp index 872d55d4..9a72febc 100644 --- a/kernel/src/Init.cpp +++ b/kernel/src/Init.cpp @@ -1,5 +1,6 @@ #include "Init.h" #include "Framebuffer.h" +#include "arch/MMU.h" #include "arch/Serial.h" #include "bootboot.h" #include @@ -19,4 +20,5 @@ void Init::check_magic() void Init::early_init() { Framebuffer::init(); + MMU::setup_initial_page_directory(); } \ No newline at end of file diff --git a/kernel/src/MemoryManager.cpp b/kernel/src/MemoryManager.cpp new file mode 100644 index 00000000..b0f80e17 --- /dev/null +++ b/kernel/src/MemoryManager.cpp @@ -0,0 +1,142 @@ +#include "MemoryManager.h" +#include "arch/MMU.h" +#include "arch/Serial.h" +#include "bootboot.h" +#include +#include + +extern BOOTBOOT bootboot; + +static bool page_bitmap_read(u64 index); +static void page_bitmap_set(u64 index, bool value); + +static u64 free_mem = 0; +static u64 used_mem = 0; +static u64 reserved_mem = 0; + +static char* page_bitmap_addr = nullptr; +static char* page_virtual_bitmap_addr = nullptr; +static u64 page_bitmap_size; + +static u64 start_index = 0; + +static bool page_bitmap_read(u64 index) +{ + return (page_virtual_bitmap_addr[index / 8] & (0b10000000 >> (index % 8))) > 0; +} + +static void page_bitmap_set(u64 index, bool value) +{ + uint64_t byteIndex = index / 8; + uint8_t bitIndexer = 0b10000000 >> (index % 8); + page_virtual_bitmap_addr[byteIndex] &= (uint8_t)(~bitIndexer); + if (value) { page_virtual_bitmap_addr[byteIndex] |= bitIndexer; } +} + +namespace MemoryManager +{ + void init_physical_allocator() + { + u64 total_mem = 0; + + void* biggest_memory_block = nullptr; + u64 biggest_memory_block_size = 0; + + // walk the memory map + MMapEnt* ptr = &bootboot.mmap; + uint64_t mmap_entries = (bootboot.size - 128) / 16; + for (u64 i = 0; i < mmap_entries; i++) + { + u64 size = MMapEnt_Size(ptr); + total_mem += size; + if (!MMapEnt_IsFree(ptr)) + { + ptr++; + continue; + } + if (size > biggest_memory_block_size) + { + biggest_memory_block = (void*)MMapEnt_Ptr(ptr); + biggest_memory_block_size = MMapEnt_Size(ptr); + } + ptr++; + } + + page_bitmap_addr = (char*)biggest_memory_block; + page_virtual_bitmap_addr = page_bitmap_addr; // we'll map this to virtual memory as soon as the MMU is ready + if ((total_mem / MMU::page_size() / 8) >= biggest_memory_block_size) + { + Serial::println("ERROR: No single memory block is enough to hold the page bitmap"); + for (;;) + ; + } + + page_bitmap_size = total_mem / MMU::page_size() / 8 + 1; + memset(page_bitmap_addr, 0xFF, page_bitmap_size); + + ptr = &bootboot.mmap; + for (uint64_t i = 0; i < mmap_entries; i++) + { + uint64_t index = MMapEnt_Ptr(ptr) / MMU::page_size(); + if (!MMapEnt_IsFree(ptr)) { reserved_mem += MMapEnt_Size(ptr); } + else + { + free_mem += MMapEnt_Size(ptr); + for (uint64_t j = 0; j < (MMapEnt_Size(ptr) / MMU::page_size()); j++) + { + page_bitmap_set(index + j, false); + } + } + ptr++; + } + + lock_pages((u64)page_bitmap_addr, page_bitmap_size / MMU::page_size() + 1); + } + + void init() + { + init_physical_allocator(); + MMU::setup_initial_page_directory(); + } + + void lock_page(u64 page) + { + uint64_t index = ((uint64_t)page) / MMU::page_size(); + if (page_bitmap_read(index)) return; + page_bitmap_set(index, true); + used_mem += MMU::page_size(); + free_mem -= MMU::page_size(); + } + + void lock_pages(u64 pages, u64 count) + { + for (u64 index = 0; index < count; index++) { lock_page(pages + (index * MMU::page_size())); } + } + + Result alloc_physical_page() + { + for (u64 index = start_index; index < (page_bitmap_size * 8); index++) + { + if (page_bitmap_read(index)) continue; + page_bitmap_set(index, true); + start_index = index + 1; + free_mem -= MMU::page_size(); + used_mem += MMU::page_size(); + return index * MMU::page_size(); + } + + return err; // FIXME: ENOMEM. + } + + Result free_physical_page(u64 page) + { + u64 index = page / MMU::page_size(); + if (index > (page_bitmap_size * 8)) return err; + if (!page_bitmap_read(index)) return err; + page_bitmap_set(index, false); + used_mem -= MMU::page_size(); + free_mem += MMU::page_size(); + if (start_index > index) start_index = index; + return {}; + } +} \ No newline at end of file diff --git a/kernel/src/MemoryManager.h b/kernel/src/MemoryManager.h new file mode 100644 index 00000000..0f580786 --- /dev/null +++ b/kernel/src/MemoryManager.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include + +namespace MemoryManager +{ + void init(); + + Result alloc_physical_page(); + Result free_physical_page(u64 page); + + void lock_page(u64 page); + void lock_pages(u64 pages, u64 count); +} \ No newline at end of file diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h new file mode 100644 index 00000000..0d22e16f --- /dev/null +++ b/kernel/src/arch/MMU.h @@ -0,0 +1,33 @@ +#pragma once +#include + +struct PageDirectory; + +namespace MMU +{ + enum Flags + { + None = 0, + ReadWrite = 1, + User = 2, + NoExecute = 4, + WriteThrough = 8, + CacheDisable = 16, + }; + + Result map(u64 virt, u64 phys, Flags flags); + Result unmap(u64 virt); + Result get_physical(u64 virt); + Result get_flags(u64 virt); + Result remap(u64 virt, Flags flags); + + void switch_page_directory(PageDirectory* dir); + PageDirectory* get_page_directory(); + + void flush_all(); + + Result create_page_directory(); + void setup_initial_page_directory(); + + size_t page_size(); +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp new file mode 100644 index 00000000..2a04b554 --- /dev/null +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -0,0 +1,248 @@ +#include "arch/MMU.h" +#include "MemoryManager.h" + +#define PAGE_SIZE 4096 + +const u64 rindex = 0776; // recursive index +const u64 sign = 0177777UL << 48; // sign extension + +struct [[gnu::packed]] PageTableEntry +{ + bool present : 1; + bool read_write : 1; + bool user : 1; + bool write_through : 1; + bool cache_disabled : 1; + bool accessed : 1; + bool ignore0 : 1; + bool larger_pages : 1; + bool ignore1 : 1; + u8 available : 3; + u64 address : 48; + u8 available2 : 3; + bool no_execute : 1; + + void set_address(uint64_t addr); + uint64_t get_address(); +}; + +#pragma GCC push_options +#pragma GCC diagnostic ignored "-Wconversion" + +void PageTableEntry::set_address(uint64_t addr) +{ + this->address = (addr >> 12); +} + +uint64_t PageTableEntry::get_address() +{ + return (uint64_t)this->address << 12; +} + +#pragma GCC pop_options + +struct alignas(PAGE_SIZE) PageDirectory +{ + PageTableEntry entries[512]; +}; + +static_assert(sizeof(PageTableEntry) == 8UL); +static_assert(sizeof(PageDirectory) == PAGE_SIZE); + +namespace MMU +{ + size_t page_size() + { + return PAGE_SIZE; + } + + PageDirectory* l4_table() + { + u64 l4 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (rindex << 12); + return (PageDirectory*)l4; + } + + u64 l4_index(u64 addr) + { + return (addr >> 39) & 0777; + } + + PageTableEntry& l4_entry(u64 addr) + { + return l4_table()->entries[l4_index(addr)]; + } + + PageDirectory* l3_table(u64 addr) + { + u64 l4 = l4_index(addr); + u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12); + return (PageDirectory*)l3; + } + + u64 l3_index(u64 addr) + { + return (addr >> 30) & 0777; + } + + PageTableEntry& l3_entry(u64 addr) + { + return l3_table(addr)->entries[l3_index(addr)]; + } + + PageDirectory* l2_table(u64 addr) + { + u64 l4 = l4_index(addr); + u64 l3 = l3_index(addr); + u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12); + return (PageDirectory*)l2; + } + + u64 l2_index(u64 addr) + { + return (addr >> 21) & 0777; + } + + PageTableEntry& l2_entry(u64 addr) + { + return l2_table(addr)->entries[l2_index(addr)]; + } + + PageDirectory* l1_table(u64 addr) + { + u64 l4 = l4_index(addr); + u64 l3 = l3_index(addr); + u64 l2 = l2_index(addr); + u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12); + return (PageDirectory*)l1; + } + + u64 l1_index(u64 addr) + { + return (addr >> 12) & 0777; + } + + PageTableEntry& l1_entry(u64 addr) + { + return l1_table(addr)->entries[l1_index(addr)]; + } + + void switch_page_directory(PageDirectory* dir) + { + asm volatile("mov %0, %%cr3" : : "r"(dir)); + } + + PageDirectory* get_page_directory() + { + PageDirectory* value; + asm volatile("mov %%cr3, %0" : "=r"(value)); + return value; + } + + void flush_all() + { + switch_page_directory(get_page_directory()); + } + + void flush_page(u64 page) + { + asm volatile("invlpg (%0)" : : "r"(page) : "memory"); + } + + Flags arch_flags_to_mmu(PageTableEntry& entry) + { + int result = Flags::None; + if (entry.read_write) result |= Flags::ReadWrite; + if (entry.user) result |= Flags::User; + if (entry.no_execute) result |= Flags::NoExecute; + if (entry.write_through) result |= Flags::WriteThrough; + if (entry.cache_disabled) result |= Flags::CacheDisable; + return (Flags)result; + } + + Result map(u64 virt, u64 phys, Flags flags) + { + auto& l4 = l4_entry(virt); + if (!l4.present) + { + auto addr = MemoryManager::alloc_physical_page(); + if (addr.has_error()) return addr.release_error(); + l4.present = true; + if (flags & Flags::ReadWrite) l4.read_write = true; + if (flags & Flags::User) l4.user = true; + l4.set_address(addr.release_value()); + } + auto& l3 = l3_entry(virt); + if (!l3.present) + { + auto addr = MemoryManager::alloc_physical_page(); + if (addr.has_error()) return addr.release_error(); + l3.present = true; + if (flags & Flags::ReadWrite) l3.read_write = true; + if (flags & Flags::User) l3.user = true; + l3.set_address(addr.release_value()); + } + if (l3.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM + auto& l2 = l2_entry(virt); + if (!l2.present) + { + auto addr = MemoryManager::alloc_physical_page(); + if (addr.has_error()) return addr.release_error(); + l2.present = true; + if (flags & Flags::ReadWrite) l2.read_write = true; + if (flags & Flags::User) l2.user = true; + l2.set_address(addr.release_value()); + } + if (l2.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM + auto& l1 = l1_entry(virt); + bool was_present = l1.present; + if (flags & Flags::ReadWrite) l1.read_write = true; + if (flags & Flags::User) l1.user = true; + if (flags & Flags::WriteThrough) l1.write_through = true; + if (flags & Flags::CacheDisable) l1.cache_disabled = true; + if (flags & Flags::NoExecute) l1.no_execute = true; + l1.set_address(phys); + if (was_present) flush_page(virt); + return {}; + } + + Result get_physical(u64 virt) + { + auto& l4 = l4_entry(virt); + if (!l4.present) return err; + auto& l3 = l3_entry(virt); + if (!l3.present) return err; + if (l3.larger_pages) return l3.get_address(); + auto& l2 = l2_entry(virt); + if (!l2.present) return err; + if (l2.larger_pages) return l2.get_address(); + auto& l1 = l1_entry(virt); + if (!l1.present) return err; + return l1.get_address(); + } + + Result get_flags(u64 virt) + { + auto& l4 = l4_entry(virt); + if (!l4.present) return err; + auto& l3 = l3_entry(virt); + if (!l3.present) return err; + if (l3.larger_pages) return arch_flags_to_mmu(l3); + auto& l2 = l2_entry(virt); + if (!l2.present) return err; + if (l2.larger_pages) return arch_flags_to_mmu(l2); + auto& l1 = l1_entry(virt); + if (!l1.present) return err; + return arch_flags_to_mmu(l1); + } + + void setup_initial_page_directory() + { + PageDirectory* dir = get_page_directory(); + u64 paddr = (u64)dir; + PageTableEntry& recursive_entry = dir->entries[rindex]; + recursive_entry.read_write = true; + recursive_entry.present = true; + recursive_entry.set_address(paddr); + flush_all(); + } +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 0668b1bd..75d83cae 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,7 +1,10 @@ #include "Framebuffer.h" #include "Init.h" +#include "arch/MMU.h" #include "arch/Serial.h" +extern u8 fb[1]; + extern "C" void _start() { Init::check_magic(); @@ -11,6 +14,8 @@ extern "C" void _start() Framebuffer::rect(0, 0, 200, 200, 0xFF00FF00); + Serial::println(MMU::get_physical((u64)fb).has_error() ? "fb is not mapped" : "fb is mapped!!"); + for (;;) ; } \ No newline at end of file diff --git a/luna/Result.h b/luna/Result.h index c2e79d6c..ca09050e 100644 --- a/luna/Result.h +++ b/luna/Result.h @@ -25,7 +25,7 @@ template class Result Result(T&& value) { - m_storage.store_movable_reference(value); + m_storage.store_movable_reference(move(value)); m_has_value = true; m_has_error = false; } @@ -231,4 +231,8 @@ template <> class Result private: int m_error; bool m_has_error; -}; \ No newline at end of file +}; + +// clang-format off +#define err Error{0} +// clang-format on \ No newline at end of file From d148e0aff76f21717b4c72ac753788f5802292fa Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 14:29:59 +0100 Subject: [PATCH 009/407] Initialize MemoryManager instead of MMU directly --- kernel/src/Init.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/Init.cpp b/kernel/src/Init.cpp index 9a72febc..85cc9dbf 100644 --- a/kernel/src/Init.cpp +++ b/kernel/src/Init.cpp @@ -1,6 +1,6 @@ #include "Init.h" #include "Framebuffer.h" -#include "arch/MMU.h" +#include "MemoryManager.h" #include "arch/Serial.h" #include "bootboot.h" #include @@ -20,5 +20,5 @@ void Init::check_magic() void Init::early_init() { Framebuffer::init(); - MMU::setup_initial_page_directory(); + MemoryManager::init(); } \ No newline at end of file From 4c4f72b865facbe770e0f77c4f7f9c5664246ee5 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 15:33:53 +0100 Subject: [PATCH 010/407] More MMU stuff, but writing still fails --- kernel/src/arch/MMU.h | 6 +++--- kernel/src/arch/x86_64/MMU.cpp | 30 ++++++++++++++++++++---------- kernel/src/main.cpp | 29 +++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index 0d22e16f..5f6fac42 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -15,11 +15,11 @@ namespace MMU CacheDisable = 16, }; - Result map(u64 virt, u64 phys, Flags flags); + Result map(u64 virt, u64 phys, int flags); Result unmap(u64 virt); Result get_physical(u64 virt); - Result get_flags(u64 virt); - Result remap(u64 virt, Flags flags); + Result get_flags(u64 virt); + Result remap(u64 virt, int flags); void switch_page_directory(PageDirectory* dir); PageDirectory* get_page_directory(); diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 2a04b554..1ccc1c08 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -1,5 +1,6 @@ #include "arch/MMU.h" #include "MemoryManager.h" +#include #define PAGE_SIZE 4096 @@ -148,7 +149,7 @@ namespace MMU asm volatile("invlpg (%0)" : : "r"(page) : "memory"); } - Flags arch_flags_to_mmu(PageTableEntry& entry) + int arch_flags_to_mmu(PageTableEntry& entry) { int result = Flags::None; if (entry.read_write) result |= Flags::ReadWrite; @@ -156,10 +157,10 @@ namespace MMU if (entry.no_execute) result |= Flags::NoExecute; if (entry.write_through) result |= Flags::WriteThrough; if (entry.cache_disabled) result |= Flags::CacheDisable; - return (Flags)result; + return result; } - Result map(u64 virt, u64 phys, Flags flags) + Result map(u64 virt, u64 phys, int flags) { auto& l4 = l4_entry(virt); if (!l4.present) @@ -167,34 +168,43 @@ namespace MMU auto addr = MemoryManager::alloc_physical_page(); if (addr.has_error()) return addr.release_error(); l4.present = true; - if (flags & Flags::ReadWrite) l4.read_write = true; - if (flags & Flags::User) l4.user = true; l4.set_address(addr.release_value()); + memset(l3_table(virt), 0, PAGE_SIZE); } + if (flags & Flags::ReadWrite) l4.read_write = true; + if (flags & Flags::User) l4.user = true; + auto& l3 = l3_entry(virt); if (!l3.present) { auto addr = MemoryManager::alloc_physical_page(); if (addr.has_error()) return addr.release_error(); l3.present = true; - if (flags & Flags::ReadWrite) l3.read_write = true; - if (flags & Flags::User) l3.user = true; l3.set_address(addr.release_value()); + memset(l2_table(virt), 0, PAGE_SIZE); } + if (flags & Flags::ReadWrite) l3.read_write = true; + if (flags & Flags::User) l3.user = true; + if (l3.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM + auto& l2 = l2_entry(virt); if (!l2.present) { auto addr = MemoryManager::alloc_physical_page(); if (addr.has_error()) return addr.release_error(); l2.present = true; - if (flags & Flags::ReadWrite) l2.read_write = true; - if (flags & Flags::User) l2.user = true; l2.set_address(addr.release_value()); + memset(l1_table(virt), 0, PAGE_SIZE); } + if (flags & Flags::ReadWrite) l2.read_write = true; + if (flags & Flags::User) l2.user = true; + if (l2.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM + auto& l1 = l1_entry(virt); bool was_present = l1.present; + l1.present = true; if (flags & Flags::ReadWrite) l1.read_write = true; if (flags & Flags::User) l1.user = true; if (flags & Flags::WriteThrough) l1.write_through = true; @@ -220,7 +230,7 @@ namespace MMU return l1.get_address(); } - Result get_flags(u64 virt) + Result get_flags(u64 virt) { auto& l4 = l4_entry(virt); if (!l4.present) return err; diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 75d83cae..2731e861 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,5 +1,6 @@ #include "Framebuffer.h" #include "Init.h" +#include "MemoryManager.h" #include "arch/MMU.h" #include "arch/Serial.h" @@ -16,6 +17,34 @@ extern "C" void _start() Serial::println(MMU::get_physical((u64)fb).has_error() ? "fb is not mapped" : "fb is mapped!!"); + const u64 address = 0xfffffffff8000000; + + u64 physical = MemoryManager::alloc_physical_page().release_value(); + + bool success = !MMU::map(address, physical, MMU::ReadWrite | MMU::NoExecute).has_error(); + + if (success) Serial::println("Mapped page :)"); + else + Serial::println("Failed to map page"); + + if (MMU::get_physical(address).release_value() == physical) Serial::println("Mapping is active ;)"); + else + Serial::println("Mapping is not active"); + + int flags = MMU::get_flags(address).release_value(); + + if (flags & MMU::ReadWrite) Serial::println("Mapping is writable"); + if (flags & MMU::NoExecute) Serial::println("Mapping is not executable"); + + u32* ptr = (u32*)address; + (void)*ptr; + + Serial::println("Can read from pointer"); + + *ptr = 8; + + Serial::println("Can write to pointer"); + for (;;) ; } \ No newline at end of file From d6c56fb5124707cffa8bbe978249c07b062c25be Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 16:31:32 +0100 Subject: [PATCH 011/407] Mapping finally works!! --- kernel/src/arch/x86_64/MMU.cpp | 19 ++++++++++++------- kernel/src/main.cpp | 21 +++++++++++++++------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 1ccc1c08..d79a995a 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -1,5 +1,6 @@ #include "arch/MMU.h" #include "MemoryManager.h" +#include "arch/Serial.h" #include #define PAGE_SIZE 4096 @@ -23,21 +24,21 @@ struct [[gnu::packed]] PageTableEntry u8 available2 : 3; bool no_execute : 1; - void set_address(uint64_t addr); - uint64_t get_address(); + void set_address(u64 addr); + u64 get_address(); }; #pragma GCC push_options #pragma GCC diagnostic ignored "-Wconversion" -void PageTableEntry::set_address(uint64_t addr) +void PageTableEntry::set_address(u64 addr) { this->address = (addr >> 12); } -uint64_t PageTableEntry::get_address() +u64 PageTableEntry::get_address() { - return (uint64_t)this->address << 12; + return (u64)this->address << 12; } #pragma GCC pop_options @@ -170,6 +171,7 @@ namespace MMU l4.present = true; l4.set_address(addr.release_value()); memset(l3_table(virt), 0, PAGE_SIZE); + l4.ignore0 = l4.ignore1 = 0; } if (flags & Flags::ReadWrite) l4.read_write = true; if (flags & Flags::User) l4.user = true; @@ -182,6 +184,7 @@ namespace MMU l3.present = true; l3.set_address(addr.release_value()); memset(l2_table(virt), 0, PAGE_SIZE); + l3.ignore0 = l3.ignore1 = 0; } if (flags & Flags::ReadWrite) l3.read_write = true; if (flags & Flags::User) l3.user = true; @@ -196,6 +199,7 @@ namespace MMU l2.present = true; l2.set_address(addr.release_value()); memset(l1_table(virt), 0, PAGE_SIZE); + l2.ignore0 = l2.ignore1 = 0; } if (flags & Flags::ReadWrite) l2.read_write = true; if (flags & Flags::User) l2.user = true; @@ -203,15 +207,16 @@ namespace MMU if (l2.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM auto& l1 = l1_entry(virt); - bool was_present = l1.present; + if (l1.present) return err; // Please explicitly unmap the page before mapping it again. + l1.ignore0 = l1.ignore1 = false; l1.present = true; if (flags & Flags::ReadWrite) l1.read_write = true; if (flags & Flags::User) l1.user = true; if (flags & Flags::WriteThrough) l1.write_through = true; if (flags & Flags::CacheDisable) l1.cache_disabled = true; if (flags & Flags::NoExecute) l1.no_execute = true; + if (l1.ignore0 || l1.ignore1) return {1}; l1.set_address(phys); - if (was_present) flush_page(virt); return {}; } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 2731e861..4d47e607 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -21,30 +21,39 @@ extern "C" void _start() u64 physical = MemoryManager::alloc_physical_page().release_value(); - bool success = !MMU::map(address, physical, MMU::ReadWrite | MMU::NoExecute).has_error(); + auto rc = MMU::map(address, physical, MMU::ReadWrite); + bool success = !rc.has_error(); + + int flags; + u8* ptr; if (success) Serial::println("Mapped page :)"); else + { Serial::println("Failed to map page"); + goto failure; + } if (MMU::get_physical(address).release_value() == physical) Serial::println("Mapping is active ;)"); else + { Serial::println("Mapping is not active"); + goto failure; + } - int flags = MMU::get_flags(address).release_value(); + flags = MMU::get_flags(address).release_value(); if (flags & MMU::ReadWrite) Serial::println("Mapping is writable"); if (flags & MMU::NoExecute) Serial::println("Mapping is not executable"); - u32* ptr = (u32*)address; - (void)*ptr; - - Serial::println("Can read from pointer"); + ptr = (u8*)address; *ptr = 8; Serial::println("Can write to pointer"); +failure: + for (;;) ; } \ No newline at end of file From ba1bf72e1b96898307e5c230cc06d050166704a2 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 16:32:28 +0100 Subject: [PATCH 012/407] Remove unused include --- kernel/src/arch/x86_64/MMU.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index d79a995a..b6533bfa 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -1,6 +1,5 @@ #include "arch/MMU.h" #include "MemoryManager.h" -#include "arch/Serial.h" #include #define PAGE_SIZE 4096 From ae235e55389be2882ed35c284337a5e9df4b222f Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 16:51:21 +0100 Subject: [PATCH 013/407] MMU: unmap and remap for x86_64 --- kernel/src/arch/MMU.h | 2 +- kernel/src/arch/x86_64/MMU.cpp | 84 ++++++++++++++++++++++++++-------- kernel/src/main.cpp | 29 ++++++++++-- 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index 5f6fac42..624427f6 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -26,7 +26,7 @@ namespace MMU void flush_all(); - Result create_page_directory(); + Result create_page_directory_for_userspace(); void setup_initial_page_directory(); size_t page_size(); diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index b6533bfa..ff6e9534 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -160,6 +160,39 @@ namespace MMU return result; } + Result find_entry(u64 virt) + { + auto& l4 = l4_entry(virt); + if (!l4.present) return err; + auto& l3 = l3_entry(virt); + if (!l3.present) return err; + if (l3.larger_pages) return &l3; + auto& l2 = l2_entry(virt); + if (!l2.present) return err; + if (l2.larger_pages) return &l2; + return &l1_entry(virt); + } + + Result apply_cascading_flags(u64 virt, int flags) + { + auto& l4 = l4_entry(virt); + if (!l4.present) return err; + if (flags & Flags::ReadWrite) l4.read_write = true; + if (flags & Flags::User) l4.user = true; + auto& l3 = l3_entry(virt); + if (!l3.present) return err; + if (l3.larger_pages) return &l3; + if (flags & Flags::ReadWrite) l3.read_write = true; + if (flags & Flags::User) l3.user = true; + auto& l2 = l2_entry(virt); + if (!l2.present) return err; + if (l2.larger_pages) return &l2; + if (flags & Flags::ReadWrite) l2.read_write = true; + if (flags & Flags::User) l2.user = true; + auto& l1 = l1_entry(virt); + return &l1; + } + Result map(u64 virt, u64 phys, int flags) { auto& l4 = l4_entry(virt); @@ -214,37 +247,50 @@ namespace MMU if (flags & Flags::WriteThrough) l1.write_through = true; if (flags & Flags::CacheDisable) l1.cache_disabled = true; if (flags & Flags::NoExecute) l1.no_execute = true; - if (l1.ignore0 || l1.ignore1) return {1}; l1.set_address(phys); return {}; } + Result remap(u64 virt, int flags) + { + auto rc = apply_cascading_flags(virt, flags); + if (rc.has_error()) return rc.release_error(); + auto& l1 = *rc.release_value(); + if (!l1.present) return err; + if (flags & Flags::ReadWrite) l1.read_write = true; + if (flags & Flags::User) l1.user = true; + if (flags & Flags::WriteThrough) l1.write_through = true; + if (flags & Flags::CacheDisable) l1.cache_disabled = true; + if (flags & Flags::NoExecute) l1.no_execute = true; + return {}; + } + + Result unmap(u64 virt) + { + auto rc = find_entry(virt); + if (rc.has_error()) return rc.release_error(); + auto& l1 = *rc.release_value(); + if (!l1.present) return err; + u64 address = l1.get_address(); + memset(&l1, 0, sizeof(l1)); + flush_page(virt); + return address; + } + Result get_physical(u64 virt) { - auto& l4 = l4_entry(virt); - if (!l4.present) return err; - auto& l3 = l3_entry(virt); - if (!l3.present) return err; - if (l3.larger_pages) return l3.get_address(); - auto& l2 = l2_entry(virt); - if (!l2.present) return err; - if (l2.larger_pages) return l2.get_address(); - auto& l1 = l1_entry(virt); + auto rc = find_entry(virt); + if (rc.has_error()) return rc.release_error(); + auto& l1 = *rc.release_value(); if (!l1.present) return err; return l1.get_address(); } Result get_flags(u64 virt) { - auto& l4 = l4_entry(virt); - if (!l4.present) return err; - auto& l3 = l3_entry(virt); - if (!l3.present) return err; - if (l3.larger_pages) return arch_flags_to_mmu(l3); - auto& l2 = l2_entry(virt); - if (!l2.present) return err; - if (l2.larger_pages) return arch_flags_to_mmu(l2); - auto& l1 = l1_entry(virt); + auto rc = find_entry(virt); + if (rc.has_error()) return rc.release_error(); + auto& l1 = *rc.release_value(); if (!l1.present) return err; return arch_flags_to_mmu(l1); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 4d47e607..fa03a90c 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -6,6 +6,12 @@ extern u8 fb[1]; +void hang() +{ + for (;;) + ; +} + extern "C" void _start() { Init::check_magic(); @@ -31,14 +37,14 @@ extern "C" void _start() else { Serial::println("Failed to map page"); - goto failure; + hang(); } if (MMU::get_physical(address).release_value() == physical) Serial::println("Mapping is active ;)"); else { Serial::println("Mapping is not active"); - goto failure; + hang(); } flags = MMU::get_flags(address).release_value(); @@ -52,7 +58,24 @@ extern "C" void _start() Serial::println("Can write to pointer"); -failure: + auto urc = MMU::unmap(address); + if (urc.has_error()) + { + Serial::println("Failed to unmap page"); + hang(); + } + + if (urc.release_value() != physical) + { + Serial::println("unmap returned a different address than the one we mapped"); + hang(); + } + + Serial::println("Unmapped memory, writing to it should crash"); + + *ptr = 16; + + Serial::println("ERROR: we should have crashed by this point"); for (;;) ; From 6a7097c9ecf1d0b0f6f30175d99ac677464de73d Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 16:54:07 +0100 Subject: [PATCH 014/407] Add variables for the future --- kernel/src/MemoryManager.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/src/MemoryManager.cpp b/kernel/src/MemoryManager.cpp index b0f80e17..4f349e0d 100644 --- a/kernel/src/MemoryManager.cpp +++ b/kernel/src/MemoryManager.cpp @@ -7,6 +7,11 @@ extern BOOTBOOT bootboot; +extern u8 start_of_kernel_rodata[1]; +extern u8 end_of_kernel_rodata[1]; +extern u8 start_of_kernel_data[1]; +extern u8 end_of_kernel_data[1]; + static bool page_bitmap_read(u64 index); static void page_bitmap_set(u64 index, bool value); @@ -93,6 +98,10 @@ namespace MemoryManager lock_pages((u64)page_bitmap_addr, page_bitmap_size / MMU::page_size() + 1); } + void protect_kernel_sections() + { + } + void init() { init_physical_allocator(); From 33584548339a79eba908635b1eb2d342f295151e Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 13 Nov 2022 16:56:03 +0100 Subject: [PATCH 015/407] Add getters for free, used and reserved memory --- kernel/src/MemoryManager.cpp | 19 +++++++++++++++---- kernel/src/MemoryManager.h | 4 ++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/kernel/src/MemoryManager.cpp b/kernel/src/MemoryManager.cpp index 4f349e0d..1223ffd8 100644 --- a/kernel/src/MemoryManager.cpp +++ b/kernel/src/MemoryManager.cpp @@ -98,10 +98,6 @@ namespace MemoryManager lock_pages((u64)page_bitmap_addr, page_bitmap_size / MMU::page_size() + 1); } - void protect_kernel_sections() - { - } - void init() { init_physical_allocator(); @@ -148,4 +144,19 @@ namespace MemoryManager if (start_index > index) start_index = index; return {}; } + + u64 free() + { + return free_mem; + } + + u64 used() + { + return used_mem; + } + + u64 reserved() + { + return reserved_mem; + } } \ No newline at end of file diff --git a/kernel/src/MemoryManager.h b/kernel/src/MemoryManager.h index 0f580786..59621504 100644 --- a/kernel/src/MemoryManager.h +++ b/kernel/src/MemoryManager.h @@ -11,4 +11,8 @@ namespace MemoryManager void lock_page(u64 page); void lock_pages(u64 pages, u64 count); + + u64 free(); + u64 used(); + u64 reserved(); } \ No newline at end of file From e16324887f8d949a067b8dd3a92473511288e383 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 15 Nov 2022 19:10:19 +0100 Subject: [PATCH 016/407] MMU: Properly clear flags --- kernel/src/arch/x86_64/MMU.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index ff6e9534..e259eb47 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -242,11 +242,11 @@ namespace MMU if (l1.present) return err; // Please explicitly unmap the page before mapping it again. l1.ignore0 = l1.ignore1 = false; l1.present = true; - if (flags & Flags::ReadWrite) l1.read_write = true; - if (flags & Flags::User) l1.user = true; - if (flags & Flags::WriteThrough) l1.write_through = true; - if (flags & Flags::CacheDisable) l1.cache_disabled = true; - if (flags & Flags::NoExecute) l1.no_execute = true; + l1.read_write = (flags & Flags::ReadWrite); + l1.user = (flags & Flags::User); + l1.write_through = (flags & Flags::WriteThrough); + l1.cache_disabled = (flags & Flags::CacheDisable); + l1.no_execute = (flags & Flags::NoExecute); l1.set_address(phys); return {}; } @@ -257,11 +257,11 @@ namespace MMU if (rc.has_error()) return rc.release_error(); auto& l1 = *rc.release_value(); if (!l1.present) return err; - if (flags & Flags::ReadWrite) l1.read_write = true; - if (flags & Flags::User) l1.user = true; - if (flags & Flags::WriteThrough) l1.write_through = true; - if (flags & Flags::CacheDisable) l1.cache_disabled = true; - if (flags & Flags::NoExecute) l1.no_execute = true; + l1.read_write = (flags & Flags::ReadWrite); + l1.user = (flags & Flags::User); + l1.write_through = (flags & Flags::WriteThrough); + l1.cache_disabled = (flags & Flags::CacheDisable); + l1.no_execute = (flags & Flags::NoExecute); return {}; } From c319336e3d89670d9abfe59d7ca399b056f5d842 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 15 Nov 2022 19:10:32 +0100 Subject: [PATCH 017/407] Add a CPU interface --- CMakeLists.txt | 4 ++- kernel/CMakeLists.txt | 41 ++++++++++++++++++++--------- kernel/src/Init.cpp | 3 +++ kernel/src/arch/CPU.h | 10 +++++++ kernel/src/arch/x86_64/CPU.asm | 17 ++++++++++++ kernel/src/arch/x86_64/CPU.cpp | 44 +++++++++++++++++++++++++++++++ kernel/src/main.cpp | 48 +++++++++++++++++++--------------- 7 files changed, 132 insertions(+), 35 deletions(-) create mode 100644 kernel/src/arch/CPU.h create mode 100644 kernel/src/arch/x86_64/CPU.asm create mode 100644 kernel/src/arch/x86_64/CPU.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 38fe3a8d..576771e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,13 +5,15 @@ set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CROSSCOMPILING true) -project(Luna LANGUAGES C CXX ASM) +project(Luna LANGUAGES C CXX ASM_NASM) set(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR}) set(CMAKE_C_COMPILER x86_64-luna-gcc) set(CMAKE_CXX_COMPILER x86_64-luna-g++) +set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) + set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) add_subdirectory(kernel) \ No newline at end of file diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 9e7a3e4f..65604d76 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -7,30 +7,45 @@ set(SOURCES src/arch/Serial.cpp ) +# x86-64 specific set(SOURCES ${SOURCES} src/arch/x86_64/IO.cpp src/arch/x86_64/Serial.cpp src/arch/x86_64/MMU.cpp + src/arch/x86_64/CPU.cpp ) -add_compile_options(-Os) +# x86-64 specific +set(ASM_SOURCES + src/arch/x86_64/CPU.asm +) -add_compile_options(-pedantic -Wall -Wextra -Werror -Wvla) -add_compile_options(-Wdisabled-optimization -Wformat=2 -Winit-self) -add_compile_options(-Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) -add_compile_options(-Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) -add_compile_options(-fno-rtti -ffreestanding -fno-exceptions) -add_compile_options(-fno-asynchronous-unwind-tables -fno-omit-frame-pointer) -add_compile_options(-nostdlib -mcmodel=kernel) -add_compile_options(-mno-red-zone) - -add_compile_options(-mno-80387 -mno-mmx -mno-sse -mno-sse2) - -add_link_options(-lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mno-red-zone -mcmodel=kernel) +add_library(moon-asm STATIC ${ASM_SOURCES}) add_executable(moon ${SOURCES}) +target_link_libraries(moon moon-asm) + +target_compile_options(moon PRIVATE -Os) + +target_compile_options(moon PRIVATE -pedantic -Wall -Wextra -Werror -Wvla) +target_compile_options(moon PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) +target_compile_options(moon PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) +target_compile_options(moon PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) +target_compile_options(moon PRIVATE -fno-rtti -ffreestanding -fno-exceptions) +target_compile_options(moon PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) +target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel) + +# x86-64 specific +target_compile_options(moon PRIVATE -mno-red-zone) +target_compile_options(moon PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) + +target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mcmodel=kernel) + +# x86-64 specific +target_link_options(moon PRIVATE -mno-red-zone) + set_target_properties(moon PROPERTIES CXX_STANDARD 20) target_include_directories(moon PUBLIC ${LUNA_ROOT}/luna) diff --git a/kernel/src/Init.cpp b/kernel/src/Init.cpp index 85cc9dbf..25018f87 100644 --- a/kernel/src/Init.cpp +++ b/kernel/src/Init.cpp @@ -1,6 +1,7 @@ #include "Init.h" #include "Framebuffer.h" #include "MemoryManager.h" +#include "arch/CPU.h" #include "arch/Serial.h" #include "bootboot.h" #include @@ -21,4 +22,6 @@ void Init::early_init() { Framebuffer::init(); MemoryManager::init(); + + CPU::platform_init(); } \ No newline at end of file diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h new file mode 100644 index 00000000..c2aa77e1 --- /dev/null +++ b/kernel/src/arch/CPU.h @@ -0,0 +1,10 @@ +#pragma once +#include + +namespace CPU +{ + Result identify(); + void platform_init(); + + [[noreturn]] void efficient_halt(); +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm new file mode 100644 index 00000000..3a889598 --- /dev/null +++ b/kernel/src/arch/x86_64/CPU.asm @@ -0,0 +1,17 @@ +global enable_sse +enable_sse: + mov rax, cr0 + and ax, 0xFFFB ;clear coprocessor emulation CR0.EM + or ax, 0x2 ;set coprocessor monitoring CR0.MP + mov cr0, rax + mov rax, cr4 + or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time + mov cr4, rax + ret + +global enable_write_protect +enable_write_protect: + mov rax, cr0 + or eax, 0x80000 ;set write-protect CR0.WP + mov cr0, rax + ret \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp new file mode 100644 index 00000000..eeb32306 --- /dev/null +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -0,0 +1,44 @@ +#include "arch/CPU.h" +#include +#include +#include + +extern "C" void enable_sse(); +extern "C" void enable_write_protect(); + +namespace CPU +{ + Result identify() + { + static char brand_string[49]; + + u32 buf[4]; + if (!__get_cpuid(0x80000002, &buf[0], &buf[1], &buf[2], &buf[3])) return err; + memcpy(brand_string, buf, 16); + if (!__get_cpuid(0x80000003, &buf[0], &buf[1], &buf[2], &buf[3])) return err; + memcpy(&brand_string[16], buf, 16); + if (!__get_cpuid(0x80000004, &buf[0], &buf[1], &buf[2], &buf[3])) return err; + memcpy(&brand_string[32], buf, 16); + + brand_string[48] = 0; // null-terminate it :) + + return brand_string; + } + + void platform_init() + { + enable_sse(); + enable_write_protect(); + } + + [[noreturn]] void efficient_halt() // Halt the CPU, using the lowest power possible. On x86-64 we do this using the + // "hlt" instruction, which puts the CPU into a low-power idle state until the + // next interrupt arrives... and we disable interrupts beforehand. + { + asm volatile("cli"); // Disable interrupts + loop: + asm volatile("hlt"); // Let the cpu rest and pause until the next interrupt arrives... which in this case should + // be never (unless an NMI arrives) :) + goto loop; // Safeguard: if we ever wake up, start our low-power rest again + } +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index fa03a90c..8747cc4f 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,18 +1,13 @@ #include "Framebuffer.h" #include "Init.h" #include "MemoryManager.h" +#include "arch/CPU.h" #include "arch/MMU.h" #include "arch/Serial.h" extern u8 fb[1]; -void hang() -{ - for (;;) - ; -} - -extern "C" void _start() +extern "C" [[noreturn]] void _start() { Init::check_magic(); Init::early_init(); @@ -21,6 +16,10 @@ extern "C" void _start() Framebuffer::rect(0, 0, 200, 200, 0xFF00FF00); + auto cpu_name_or_error = CPU::identify(); + + Serial::println(cpu_name_or_error.has_error() ? "Unable to determine CPU name" : cpu_name_or_error.release_value()); + Serial::println(MMU::get_physical((u64)fb).has_error() ? "fb is not mapped" : "fb is mapped!!"); const u64 address = 0xfffffffff8000000; @@ -31,28 +30,40 @@ extern "C" void _start() bool success = !rc.has_error(); int flags; - u8* ptr; + volatile u8* ptr; if (success) Serial::println("Mapped page :)"); else { Serial::println("Failed to map page"); - hang(); + CPU::efficient_halt(); } if (MMU::get_physical(address).release_value() == physical) Serial::println("Mapping is active ;)"); else { Serial::println("Mapping is not active"); - hang(); + CPU::efficient_halt(); } flags = MMU::get_flags(address).release_value(); if (flags & MMU::ReadWrite) Serial::println("Mapping is writable"); - if (flags & MMU::NoExecute) Serial::println("Mapping is not executable"); + if (flags & MMU::User) Serial::println("Mapping is user accessible"); - ptr = (u8*)address; + auto rrc = MMU::remap(address, MMU::ReadWrite | MMU::User); + if (rrc.has_error()) + { + Serial::println("Failed to change flags of mapping"); + CPU::efficient_halt(); + } + + flags = MMU::get_flags(address).release_value(); + + if (flags & MMU::ReadWrite) Serial::println("Mapping is now writable"); + if (flags & MMU::User) Serial::println("Mapping is now user accessible"); + + ptr = (volatile u8*)address; *ptr = 8; @@ -62,21 +73,16 @@ extern "C" void _start() if (urc.has_error()) { Serial::println("Failed to unmap page"); - hang(); + CPU::efficient_halt(); } if (urc.release_value() != physical) { Serial::println("unmap returned a different address than the one we mapped"); - hang(); + CPU::efficient_halt(); } - Serial::println("Unmapped memory, writing to it should crash"); + Serial::println("Successfully unmapped address"); - *ptr = 16; - - Serial::println("ERROR: we should have crashed by this point"); - - for (;;) - ; + CPU::efficient_halt(); } \ No newline at end of file From c9feb113663e065d9ecce86f1855c4c93de83ebb Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 15 Nov 2022 19:36:50 +0100 Subject: [PATCH 018/407] Introduce a check() method (like assert() but always on) --- kernel/CMakeLists.txt | 2 ++ kernel/src/main.cpp | 2 ++ luna/Check.h | 22 ++++++++++++++++++++++ luna/Result.h | 17 +++++++++-------- 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 luna/Check.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 65604d76..25eca3cd 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -27,6 +27,8 @@ add_executable(moon ${SOURCES}) target_link_libraries(moon moon-asm) +target_compile_definitions(moon PRIVATE IN_MOON) + target_compile_options(moon PRIVATE -Os) target_compile_options(moon PRIVATE -pedantic -Wall -Wextra -Werror -Wvla) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 8747cc4f..17499474 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -84,5 +84,7 @@ extern "C" [[noreturn]] void _start() Serial::println("Successfully unmapped address"); + check(false); + CPU::efficient_halt(); } \ No newline at end of file diff --git a/luna/Check.h b/luna/Check.h new file mode 100644 index 00000000..f8c4fd13 --- /dev/null +++ b/luna/Check.h @@ -0,0 +1,22 @@ +#pragma once +#ifdef IN_MOON +#include "arch/Serial.h" + +[[noreturn]] inline bool __check_failed(const char* string) +{ + Serial::print("CHECK FAILED: "); + Serial::println(string); + for (;;) + ; +} +#else +[[noreturn]] inline bool __check_failed(const char*) +{ + __builtin_trap(); +} +#endif + +#define STRINGIZE(x) #x +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) + +#define check(expr) (expr) || __check_failed("at " __FILE__ ":" STRINGIZE_VALUE_OF(__LINE__) ": " #expr) \ No newline at end of file diff --git a/luna/Result.h b/luna/Result.h index ca09050e..c5777205 100644 --- a/luna/Result.h +++ b/luna/Result.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include @@ -81,19 +82,19 @@ template class Result int error() { - // ensure(has_error()); + check(has_error()); return m_error; } Error release_error() { - // ensure(has_error()); + check(has_error()); return {m_error}; } T value() { - // ensure(has_value()); + check(has_value()); return m_storage.fetch_reference(); } @@ -105,7 +106,7 @@ template class Result T release_value() { - // ensure(has_value()); + check(has_value()); T item = m_storage.fetch_reference(); m_has_value = false; m_storage.destroy(); @@ -206,25 +207,25 @@ template <> class Result int error() { - // ensure(has_error()); + check(has_error()); return m_error; } Error release_error() { - // ensure(has_error()); + check(has_error()); return {m_error}; } void value() { - // ensure(has_value()); + check(has_value()); return; } void release_value() { - // ensure(has_value()); + check(has_value()); return; } From bb46cd890b3bb087ec9f409ade1b69d4fd92c617 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 15 Nov 2022 20:41:59 +0100 Subject: [PATCH 019/407] Add GDT and IDT setup and loading + NX if supported --- kernel/src/arch/CPU.h | 2 + kernel/src/arch/x86_64/CPU.asm | 32 ++++++ kernel/src/arch/x86_64/CPU.cpp | 176 +++++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index c2aa77e1..cff9919d 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -7,4 +7,6 @@ namespace CPU void platform_init(); [[noreturn]] void efficient_halt(); + + void switch_kernel_stack(u64 top); } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 3a889598..e23c6d0e 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -14,4 +14,36 @@ enable_write_protect: mov rax, cr0 or eax, 0x80000 ;set write-protect CR0.WP mov cr0, rax + ret + +global enable_nx +enable_nx: + mov rcx, 0xC0000080 ; IA32_EFER + rdmsr + or eax, 1 << 11 ; no-execute enable (NXE) + wrmsr +.end: + ret + +global load_gdt +load_gdt: + cli + lgdt [rdi] + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + push 0x08 + lea rax, [rel .reload_CS] + push rax + retfq +.reload_CS: + ret + +global load_tr +load_tr: + mov rax, rdi + ltr ax ret \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index eeb32306..a1436d65 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -5,6 +5,174 @@ extern "C" void enable_sse(); extern "C" void enable_write_protect(); +extern "C" void enable_nx(); + +// GDT code and definitions + +struct GDTR +{ + u16 size; + u64 offset; +} __attribute__((packed)); + +struct GDTEntry +{ + u16 limit0; + u16 base0; + u8 base1; + u8 access; + u8 limit1_flags; + u8 base2; +} __attribute__((packed)); + +struct HighGDTEntry +{ + u32 base_high; + u32 reserved; +} __attribute__((packed)); + +struct TSS +{ + u32 reserved0; + u64 rsp[3]; + u64 reserved1; + u64 ist[7]; + u64 reserved2; + u16 reserved3; + u16 iomap_base; +} __attribute__((packed)); + +struct GlobalDescriptorTable +{ + GDTEntry null; + GDTEntry kernel_code; + GDTEntry kernel_data; + GDTEntry user_code; + GDTEntry user_data; + GDTEntry tss; + HighGDTEntry tss2; +} __attribute__((packed)) __attribute((aligned(4096))); + +static TSS task_state_segment; + +static GlobalDescriptorTable gdt = {{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00}, + {0xffff, 0x0000, 0x00, 0x9a, 0xaf, 0x00}, + {0xffff, 0x0000, 0x00, 0x92, 0xcf, 0x00}, + {0xffff, 0x0000, 0x00, 0xfa, 0xaf, 0x00}, + {0xffff, 0x0000, 0x00, 0xf2, 0xcf, 0x00}, + {0x0000, 0x0000, 0x00, 0xe9, 0x0f, 0x00}, + {0x00000000, 0x00000000}}; + +extern "C" void load_gdt(GDTR* gdtr); +extern "C" void load_tr(int segment); + +static void set_base(GDTEntry* entry, u32 base) +{ + entry->base0 = (base & 0xFFFF); + entry->base1 = (base >> 16) & 0xFF; + entry->base2 = (u8)((base >> 24) & 0xFF); +} + +static void set_limit(GDTEntry* entry, u32 limit) +{ + check(limit <= 0xFFFFF); + entry->limit0 = limit & 0xFFFF; + entry->limit1_flags = (entry->limit1_flags & 0xF0) | ((limit >> 16) & 0xF); +} + +static void set_tss_base(GDTEntry* tss1, HighGDTEntry* tss2, u64 addr) +{ + set_base(tss1, addr & 0xffffffff); + tss2->base_high = (u32)(addr >> 32); +} + +static void setup_tss() +{ + memset(&task_state_segment, 0, sizeof(TSS)); + task_state_segment.iomap_base = sizeof(TSS); + set_tss_base(&gdt.tss, &gdt.tss2, (u64)&task_state_segment); + set_limit(&gdt.tss, sizeof(TSS) - 1); +} + +static void setup_gdt() +{ + static GDTR gdtr; + gdtr.offset = (u64)&gdt; + gdtr.size = sizeof(GlobalDescriptorTable); + setup_tss(); + load_gdt(&gdtr); + load_tr(0x2b); +} + +// IDT code and definitions + +struct IDTEntry +{ + u16 offset0; + u16 selector; + u8 ist; + u8 type_attr; + u16 offset1; + u32 offset2; + u32 ignore; + void set_offset(u64 offset); + u64 get_offset(); +}; + +void IDTEntry::set_offset(u64 offset) +{ + offset0 = (u16)(offset & 0x000000000000ffff); + offset1 = (u16)((offset & 0x00000000ffff0000) >> 16); + offset2 = (u32)((offset & 0xffffffff00000000) >> 32); +} + +u64 IDTEntry::get_offset() +{ + u64 offset = 0; + offset |= (u64)offset0; + offset |= (u64)offset1 << 16; + offset |= (u64)offset2 << 32; + return offset; +} + +static IDTEntry idt[256]; + +#define IDT_TA_InterruptGate 0b10001110 +#define IDT_TA_UserInterruptGate 0b11101110 +#define IDT_TA_TrapGate 0b10001111 + +struct IDTR +{ + uint16_t limit; + uint64_t offset; +} __attribute__((packed)); + +[[maybe_unused]] static void idt_add_handler(short num, void* handler, u8 type_attr) +{ + check(handler != nullptr); + check(num < 256); + IDTEntry* entry_for_handler = &idt[num]; + entry_for_handler->selector = 0x08; + entry_for_handler->type_attr = type_attr; + entry_for_handler->set_offset((u64)handler); +} + +static void setup_idt() // FIXME: Add entries to the IDT. +{ + static IDTR idtr; + idtr.limit = 0x0FFF; + idtr.offset = (u64)idt; + asm("lidt %0" : : "m"(idtr)); +} + +// Generic CPU code + +static bool test_nx() +{ + u32 __unused, edx = 0; + if (!__get_cpuid(0x80000001, &__unused, &__unused, &__unused, &edx)) return 0; + return edx & (1 << 20); +} namespace CPU { @@ -29,6 +197,9 @@ namespace CPU { enable_sse(); enable_write_protect(); + if (test_nx()) enable_nx(); + setup_gdt(); + setup_idt(); } [[noreturn]] void efficient_halt() // Halt the CPU, using the lowest power possible. On x86-64 we do this using the @@ -41,4 +212,9 @@ namespace CPU // be never (unless an NMI arrives) :) goto loop; // Safeguard: if we ever wake up, start our low-power rest again } + + void switch_kernel_stack(u64 top) + { + task_state_segment.rsp[0] = top; + } } \ No newline at end of file From df8666fd73b7f68d6013d6919295a516dfee4c68 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 15 Nov 2022 20:47:50 +0100 Subject: [PATCH 020/407] Remove unneeded label --- kernel/src/arch/x86_64/CPU.asm | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index e23c6d0e..918931f9 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -22,7 +22,6 @@ enable_nx: rdmsr or eax, 1 << 11 ; no-execute enable (NXE) wrmsr -.end: ret global load_gdt From 7f15ba0ac5d82219842c3bdaa3f02855bc39a7ac Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 16 Nov 2022 17:37:18 +0100 Subject: [PATCH 021/407] Add some interrupt handling --- kernel/src/arch/CPU.h | 2 + kernel/src/arch/x86_64/CPU.asm | 77 +++++++++++++++++++++++++++++++++- kernel/src/arch/x86_64/CPU.cpp | 31 ++++++++++++-- kernel/src/arch/x86_64/CPU.h | 10 +++++ kernel/src/main.cpp | 6 ++- tools/check-formatting.sh | 4 +- tools/run-clang-format.sh | 4 +- 7 files changed, 123 insertions(+), 11 deletions(-) create mode 100644 kernel/src/arch/x86_64/CPU.h diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index cff9919d..a471b0d0 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -1,6 +1,8 @@ #pragma once #include +struct Registers; + namespace CPU { Result identify(); diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 918931f9..329f576f 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -1,3 +1,9 @@ +section .data +global __divisor +__divisor: + dd 0 + +section .text global enable_sse enable_sse: mov rax, cr0 @@ -45,4 +51,73 @@ global load_tr load_tr: mov rax, rdi ltr ax - ret \ No newline at end of file + ret + +%macro ISR 1 + global _isr%1 + _isr%1: + push byte 0 + push byte %1 + jmp _asm_interrupt_entry +%endmacro + +%macro ISR_ERROR 1 + global _isr%1 + _isr%1: + push byte %1 + jmp _asm_interrupt_entry +%endmacro + +%macro IRQ 2 + global _isr%1 + _isr%1: + push byte %2 + push byte %1 + jmp _asm_interrupt_entry +%endmacro + +extern arch_interrupt_entry + +_asm_interrupt_entry: + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + cld + + mov rdi, rsp + call arch_interrupt_entry + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + + add rsp, 16 + + iretq + +ISR 0 ; divide by zero \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index a1436d65..941f464f 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -1,4 +1,5 @@ -#include "arch/CPU.h" +#include "arch/x86_64/CPU.h" +#include "arch/Serial.h" #include #include #include @@ -147,7 +148,7 @@ struct IDTR uint64_t offset; } __attribute__((packed)); -[[maybe_unused]] static void idt_add_handler(short num, void* handler, u8 type_attr) +static void idt_add_handler(short num, void* handler, u8 type_attr) { check(handler != nullptr); check(num < 256); @@ -157,14 +158,38 @@ struct IDTR entry_for_handler->set_offset((u64)handler); } -static void setup_idt() // FIXME: Add entries to the IDT. +#define INT(x) extern "C" void _isr##x() +#define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) + +INT(0); + +static void setup_idt() { + TRAP(0); // divide by zero + static IDTR idtr; idtr.limit = 0x0FFF; idtr.offset = (u64)idt; asm("lidt %0" : : "m"(idtr)); } +// Interrupt handling + +// Called from _asm_interrupt_entry +extern "C" void arch_interrupt_entry(Registers* regs) +{ + if (regs->isr < 32) + { + Serial::println("Exception catched! Halting."); + CPU::efficient_halt(); + } + else + { + Serial::println("IRQ catched! Halting."); + CPU::efficient_halt(); + } +} + // Generic CPU code static bool test_nx() diff --git a/kernel/src/arch/x86_64/CPU.h b/kernel/src/arch/x86_64/CPU.h new file mode 100644 index 00000000..f156e80d --- /dev/null +++ b/kernel/src/arch/x86_64/CPU.h @@ -0,0 +1,10 @@ +#include "arch/CPU.h" +#include + +struct Registers // Saved CPU registers for x86-64 +{ + u64 r15, r14, r13, r12, r11, r10, r9, r8; + u64 rbp, rdi, rsi, rdx, rcx, rbx, rax; + u64 isr, error; + u64 rip, cs, rflags, rsp, ss; +}; \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 17499474..a7be3ce5 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -84,7 +84,11 @@ extern "C" [[noreturn]] void _start() Serial::println("Successfully unmapped address"); - check(false); + extern int __divisor; // divisor is defined as 0, we do it this way so the compiler doesn't catch it (this is + // testing exception handling) + [[maybe_unused]] volatile int div_rc = 4 / __divisor; + + Serial::println("ERROR: Still here after division by zero"); CPU::efficient_halt(); } \ No newline at end of file diff --git a/tools/check-formatting.sh b/tools/check-formatting.sh index fa7c7449..366c5748 100755 --- a/tools/check-formatting.sh +++ b/tools/check-formatting.sh @@ -4,9 +4,7 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -SOURCES=($(find kernel/src -type f | grep "\.c") $(find kernel/include -type f)) -SOURCES+=($(find libs/libc/src -type f | grep "\.c") $(find libs/libc/include -type f)) -SOURCES+=($(find apps/src -type f)) +SOURCES=($(find kernel/src -type f | grep -v "\.asm")) ALL_OK=1 diff --git a/tools/run-clang-format.sh b/tools/run-clang-format.sh index 4e88d1ec..43963d0f 100755 --- a/tools/run-clang-format.sh +++ b/tools/run-clang-format.sh @@ -5,9 +5,7 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -SOURCES=($(find kernel/src -type f | grep "\.c") $(find kernel/include -type f)) -SOURCES+=($(find libs/libc/src -type f | grep "\.c") $(find libs/libc/include -type f)) -SOURCES+=($(find apps/src -type f)) +SOURCES=($(find kernel/src -type f | grep -v "\.asm")) for f in ${SOURCES[@]} do From 7fc5a6b75304dbb7e46c5272ac943ecbc0ae3bfa Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 16 Nov 2022 20:02:04 +0100 Subject: [PATCH 022/407] Make kernel rodata and data not executable --- kernel/CMakeLists.txt | 2 +- kernel/moon.ld | 7 +++++-- kernel/src/Init.cpp | 2 ++ kernel/src/MemoryManager.cpp | 39 ++++++++++++++++++++++++++++++++++++ kernel/src/MemoryManager.h | 5 +++++ luna/Alignment.h | 22 ++++++++++++++++++++ luna/Result.h | 9 ++++++++- 7 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 luna/Alignment.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 25eca3cd..85aad645 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -31,7 +31,7 @@ target_compile_definitions(moon PRIVATE IN_MOON) target_compile_options(moon PRIVATE -Os) -target_compile_options(moon PRIVATE -pedantic -Wall -Wextra -Werror -Wvla) +target_compile_options(moon PRIVATE -Wall -Wextra -Werror -Wvla) target_compile_options(moon PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) target_compile_options(moon PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) target_compile_options(moon PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) diff --git a/kernel/moon.ld b/kernel/moon.ld index 8445665d..5b99a57b 100644 --- a/kernel/moon.ld +++ b/kernel/moon.ld @@ -16,13 +16,16 @@ SECTIONS kernel_start = .; .text : { KEEP(*(.text.boot)) *(.text .text.*) /* code */ + . = ALIGN(0x1000); start_of_kernel_rodata = .; - *(.rodata .rodata.*) /* data */ + *(.rodata .rodata.*) /* read-only data */ end_of_kernel_rodata = .; + . = ALIGN(0x1000); - start_of_kernel_data = .; + start_of_kernel_data = .; /* data */ *(.data .data.*) + } :boot .bss (NOLOAD) : { /* bss */ *(.bss .bss.*) diff --git a/kernel/src/Init.cpp b/kernel/src/Init.cpp index 25018f87..781d1473 100644 --- a/kernel/src/Init.cpp +++ b/kernel/src/Init.cpp @@ -24,4 +24,6 @@ void Init::early_init() MemoryManager::init(); CPU::platform_init(); + + check(MemoryManager::protect_kernel_sections().has_value()); } \ No newline at end of file diff --git a/kernel/src/MemoryManager.cpp b/kernel/src/MemoryManager.cpp index 1223ffd8..f1ae9961 100644 --- a/kernel/src/MemoryManager.cpp +++ b/kernel/src/MemoryManager.cpp @@ -2,6 +2,7 @@ #include "arch/MMU.h" #include "arch/Serial.h" #include "bootboot.h" +#include #include #include @@ -40,6 +41,17 @@ static void page_bitmap_set(u64 index, bool value) namespace MemoryManager { + Result protect_kernel_sections() + { + u64 rodata_pages = get_blocks_from_size((u64)(end_of_kernel_rodata - start_of_kernel_rodata), MMU::page_size()); + TRY(remap((u64)start_of_kernel_rodata, rodata_pages, MMU::NoExecute)); + + u64 data_pages = get_blocks_from_size((u64)(end_of_kernel_data - start_of_kernel_data), MMU::page_size()); + TRY(remap((u64)start_of_kernel_data, data_pages, MMU::NoExecute | MMU::ReadWrite)); + + return {}; + } + void init_physical_allocator() { u64 total_mem = 0; @@ -145,6 +157,33 @@ namespace MemoryManager return {}; } + Result remap(u64 address, size_t count, int flags) + { + check(is_aligned(address, MMU::page_size())); + + while (count--) + { + TRY(MMU::remap(address, flags)); + address += MMU::page_size(); + } + + return {}; + } + + Result remap_unaligned(u64 address, size_t count, int flags) + { + if (!is_aligned(address, MMU::page_size())) count++; + address = align_down(address, MMU::page_size()); + + while (count--) + { + TRY(MMU::remap(address, flags)); + address += MMU::page_size(); + } + + return {}; + } + u64 free() { return free_mem; diff --git a/kernel/src/MemoryManager.h b/kernel/src/MemoryManager.h index 59621504..ab516b5b 100644 --- a/kernel/src/MemoryManager.h +++ b/kernel/src/MemoryManager.h @@ -6,12 +6,17 @@ namespace MemoryManager { void init(); + Result protect_kernel_sections(); + Result alloc_physical_page(); Result free_physical_page(u64 page); void lock_page(u64 page); void lock_pages(u64 pages, u64 count); + Result remap(u64 address, size_t count, int flags); + Result remap_unaligned(u64 address, size_t count, int flags); + u64 free(); u64 used(); u64 reserved(); diff --git a/luna/Alignment.h b/luna/Alignment.h new file mode 100644 index 00000000..0cb7ced3 --- /dev/null +++ b/luna/Alignment.h @@ -0,0 +1,22 @@ +#pragma once + +template constexpr T is_aligned(T value, T align_base) +{ + return (value % align_base == 0); +} + +template constexpr T align_down(T value, T align_base) +{ + return value - (value % align_base); +} + +template constexpr T align_up(T value, T align_base) +{ + if (is_aligned(value, align_base)) return value; + return align_down(value, align_base) + align_base; +} + +template constexpr T get_blocks_from_size(T value, T block_size) +{ + return (value + (block_size - 1)) / block_size; +} \ No newline at end of file diff --git a/luna/Result.h b/luna/Result.h index c5777205..e5e99ae0 100644 --- a/luna/Result.h +++ b/luna/Result.h @@ -236,4 +236,11 @@ template <> class Result // clang-format off #define err Error{0} -// clang-format on \ No newline at end of file +// clang-format on + +#define TRY(expr) \ + ({ \ + auto _expr_rc = (expr); \ + if (_expr_rc.has_error()) return _expr_rc.release_error(); \ + _expr_rc.release_value(); \ + }) From 30ac95bcf82a2f1e2f4fb442d4ebe46502f7e34c Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 16 Nov 2022 20:30:34 +0100 Subject: [PATCH 023/407] Use usize/isize instead of (s)size_t Since we're using Rust-style integer types already, why not go all in? --- kernel/src/MemoryManager.cpp | 4 ++-- kernel/src/MemoryManager.h | 4 ++-- kernel/src/arch/MMU.h | 2 +- kernel/src/arch/Serial.cpp | 2 +- kernel/src/arch/Serial.h | 2 +- kernel/src/arch/x86_64/MMU.cpp | 2 +- luna/Types.h | 4 +++- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/kernel/src/MemoryManager.cpp b/kernel/src/MemoryManager.cpp index f1ae9961..63153a92 100644 --- a/kernel/src/MemoryManager.cpp +++ b/kernel/src/MemoryManager.cpp @@ -157,7 +157,7 @@ namespace MemoryManager return {}; } - Result remap(u64 address, size_t count, int flags) + Result remap(u64 address, usize count, int flags) { check(is_aligned(address, MMU::page_size())); @@ -170,7 +170,7 @@ namespace MemoryManager return {}; } - Result remap_unaligned(u64 address, size_t count, int flags) + Result remap_unaligned(u64 address, usize count, int flags) { if (!is_aligned(address, MMU::page_size())) count++; address = align_down(address, MMU::page_size()); diff --git a/kernel/src/MemoryManager.h b/kernel/src/MemoryManager.h index ab516b5b..d1ca0f5f 100644 --- a/kernel/src/MemoryManager.h +++ b/kernel/src/MemoryManager.h @@ -14,8 +14,8 @@ namespace MemoryManager void lock_page(u64 page); void lock_pages(u64 pages, u64 count); - Result remap(u64 address, size_t count, int flags); - Result remap_unaligned(u64 address, size_t count, int flags); + Result remap(u64 address, usize count, int flags); + Result remap_unaligned(u64 address, usize count, int flags); u64 free(); u64 used(); diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index 624427f6..b0ccc8b3 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -29,5 +29,5 @@ namespace MMU Result create_page_directory_for_userspace(); void setup_initial_page_directory(); - size_t page_size(); + usize page_size(); } \ No newline at end of file diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index 958557f6..ddf3a879 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -2,7 +2,7 @@ namespace Serial { - void write(const char* str, size_t size) + void write(const char* str, usize size) { while (size--) putchar(*str++); } diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h index 031aaac0..8d7b18aa 100644 --- a/kernel/src/arch/Serial.h +++ b/kernel/src/arch/Serial.h @@ -4,7 +4,7 @@ namespace Serial { void putchar(u8 c); - void write(const char* str, size_t size); + void write(const char* str, usize size); void print(const char* str); void println(const char* str); } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index e259eb47..fda4c36c 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -52,7 +52,7 @@ static_assert(sizeof(PageDirectory) == PAGE_SIZE); namespace MMU { - size_t page_size() + usize page_size() { return PAGE_SIZE; } diff --git a/luna/Types.h b/luna/Types.h index c45e4448..ad06edfe 100644 --- a/luna/Types.h +++ b/luna/Types.h @@ -8,4 +8,6 @@ typedef uint64_t u64; typedef int8_t i8; typedef int16_t i16; typedef int32_t i32; -typedef int64_t i64; \ No newline at end of file +typedef int64_t i64; +typedef size_t usize; +typedef long isize; \ No newline at end of file From 2c9329928c5133577c7b184d7bb56591554a846d Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 16 Nov 2022 20:37:32 +0100 Subject: [PATCH 024/407] Replace page_size (function) with ARCH_PAGE_SIZE (constant) --- kernel/src/MemoryManager.cpp | 44 +++++++++++++++++----------------- kernel/src/arch/MMU.h | 4 ++-- kernel/src/arch/x86_64/MMU.cpp | 6 ++--- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/kernel/src/MemoryManager.cpp b/kernel/src/MemoryManager.cpp index 63153a92..e089953a 100644 --- a/kernel/src/MemoryManager.cpp +++ b/kernel/src/MemoryManager.cpp @@ -43,10 +43,10 @@ namespace MemoryManager { Result protect_kernel_sections() { - u64 rodata_pages = get_blocks_from_size((u64)(end_of_kernel_rodata - start_of_kernel_rodata), MMU::page_size()); + u64 rodata_pages = get_blocks_from_size((u64)(end_of_kernel_rodata - start_of_kernel_rodata), ARCH_PAGE_SIZE); TRY(remap((u64)start_of_kernel_rodata, rodata_pages, MMU::NoExecute)); - u64 data_pages = get_blocks_from_size((u64)(end_of_kernel_data - start_of_kernel_data), MMU::page_size()); + u64 data_pages = get_blocks_from_size((u64)(end_of_kernel_data - start_of_kernel_data), ARCH_PAGE_SIZE); TRY(remap((u64)start_of_kernel_data, data_pages, MMU::NoExecute | MMU::ReadWrite)); return {}; @@ -81,25 +81,25 @@ namespace MemoryManager page_bitmap_addr = (char*)biggest_memory_block; page_virtual_bitmap_addr = page_bitmap_addr; // we'll map this to virtual memory as soon as the MMU is ready - if ((total_mem / MMU::page_size() / 8) >= biggest_memory_block_size) + if ((total_mem / ARCH_PAGE_SIZE / 8) >= biggest_memory_block_size) { Serial::println("ERROR: No single memory block is enough to hold the page bitmap"); for (;;) ; } - page_bitmap_size = total_mem / MMU::page_size() / 8 + 1; + page_bitmap_size = total_mem / ARCH_PAGE_SIZE / 8 + 1; memset(page_bitmap_addr, 0xFF, page_bitmap_size); ptr = &bootboot.mmap; for (uint64_t i = 0; i < mmap_entries; i++) { - uint64_t index = MMapEnt_Ptr(ptr) / MMU::page_size(); + uint64_t index = MMapEnt_Ptr(ptr) / ARCH_PAGE_SIZE; if (!MMapEnt_IsFree(ptr)) { reserved_mem += MMapEnt_Size(ptr); } else { free_mem += MMapEnt_Size(ptr); - for (uint64_t j = 0; j < (MMapEnt_Size(ptr) / MMU::page_size()); j++) + for (uint64_t j = 0; j < (MMapEnt_Size(ptr) / ARCH_PAGE_SIZE); j++) { page_bitmap_set(index + j, false); } @@ -107,7 +107,7 @@ namespace MemoryManager ptr++; } - lock_pages((u64)page_bitmap_addr, page_bitmap_size / MMU::page_size() + 1); + lock_pages((u64)page_bitmap_addr, page_bitmap_size / ARCH_PAGE_SIZE + 1); } void init() @@ -118,16 +118,16 @@ namespace MemoryManager void lock_page(u64 page) { - uint64_t index = ((uint64_t)page) / MMU::page_size(); + uint64_t index = ((uint64_t)page) / ARCH_PAGE_SIZE; if (page_bitmap_read(index)) return; page_bitmap_set(index, true); - used_mem += MMU::page_size(); - free_mem -= MMU::page_size(); + used_mem += ARCH_PAGE_SIZE; + free_mem -= ARCH_PAGE_SIZE; } void lock_pages(u64 pages, u64 count) { - for (u64 index = 0; index < count; index++) { lock_page(pages + (index * MMU::page_size())); } + for (u64 index = 0; index < count; index++) { lock_page(pages + (index * ARCH_PAGE_SIZE)); } } Result alloc_physical_page() @@ -137,9 +137,9 @@ namespace MemoryManager if (page_bitmap_read(index)) continue; page_bitmap_set(index, true); start_index = index + 1; - free_mem -= MMU::page_size(); - used_mem += MMU::page_size(); - return index * MMU::page_size(); + free_mem -= ARCH_PAGE_SIZE; + used_mem += ARCH_PAGE_SIZE; + return index * ARCH_PAGE_SIZE; } return err; // FIXME: ENOMEM. @@ -147,24 +147,24 @@ namespace MemoryManager Result free_physical_page(u64 page) { - u64 index = page / MMU::page_size(); + u64 index = page / ARCH_PAGE_SIZE; if (index > (page_bitmap_size * 8)) return err; if (!page_bitmap_read(index)) return err; page_bitmap_set(index, false); - used_mem -= MMU::page_size(); - free_mem += MMU::page_size(); + used_mem -= ARCH_PAGE_SIZE; + free_mem += ARCH_PAGE_SIZE; if (start_index > index) start_index = index; return {}; } Result remap(u64 address, usize count, int flags) { - check(is_aligned(address, MMU::page_size())); + check(is_aligned(address, ARCH_PAGE_SIZE)); while (count--) { TRY(MMU::remap(address, flags)); - address += MMU::page_size(); + address += ARCH_PAGE_SIZE; } return {}; @@ -172,13 +172,13 @@ namespace MemoryManager Result remap_unaligned(u64 address, usize count, int flags) { - if (!is_aligned(address, MMU::page_size())) count++; - address = align_down(address, MMU::page_size()); + if (!is_aligned(address, ARCH_PAGE_SIZE)) count++; + address = align_down(address, ARCH_PAGE_SIZE); while (count--) { TRY(MMU::remap(address, flags)); - address += MMU::page_size(); + address += ARCH_PAGE_SIZE; } return {}; diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index b0ccc8b3..d15c7b87 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -3,6 +3,8 @@ struct PageDirectory; +extern const usize ARCH_PAGE_SIZE; + namespace MMU { enum Flags @@ -28,6 +30,4 @@ namespace MMU Result create_page_directory_for_userspace(); void setup_initial_page_directory(); - - usize page_size(); } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index fda4c36c..e8fb1bc0 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -4,6 +4,8 @@ #define PAGE_SIZE 4096 +const usize ARCH_PAGE_SIZE = PAGE_SIZE; + const u64 rindex = 0776; // recursive index const u64 sign = 0177777UL << 48; // sign extension @@ -52,10 +54,6 @@ static_assert(sizeof(PageDirectory) == PAGE_SIZE); namespace MMU { - usize page_size() - { - return PAGE_SIZE; - } PageDirectory* l4_table() { From 9d318d50aaab13207ae100043621a03ea2464f42 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 16 Nov 2022 20:37:41 +0100 Subject: [PATCH 025/407] Use TRY in MMU.cpp --- kernel/src/arch/x86_64/MMU.cpp | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index e8fb1bc0..83606dde 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -196,10 +196,9 @@ namespace MMU auto& l4 = l4_entry(virt); if (!l4.present) { - auto addr = MemoryManager::alloc_physical_page(); - if (addr.has_error()) return addr.release_error(); + u64 addr = TRY(MemoryManager::alloc_physical_page()); l4.present = true; - l4.set_address(addr.release_value()); + l4.set_address(addr); memset(l3_table(virt), 0, PAGE_SIZE); l4.ignore0 = l4.ignore1 = 0; } @@ -209,10 +208,9 @@ namespace MMU auto& l3 = l3_entry(virt); if (!l3.present) { - auto addr = MemoryManager::alloc_physical_page(); - if (addr.has_error()) return addr.release_error(); + u64 addr = TRY(MemoryManager::alloc_physical_page()); l3.present = true; - l3.set_address(addr.release_value()); + l3.set_address(addr); memset(l2_table(virt), 0, PAGE_SIZE); l3.ignore0 = l3.ignore1 = 0; } @@ -224,10 +222,9 @@ namespace MMU auto& l2 = l2_entry(virt); if (!l2.present) { - auto addr = MemoryManager::alloc_physical_page(); - if (addr.has_error()) return addr.release_error(); + u64 addr = TRY(MemoryManager::alloc_physical_page()); l2.present = true; - l2.set_address(addr.release_value()); + l2.set_address(addr); memset(l1_table(virt), 0, PAGE_SIZE); l2.ignore0 = l2.ignore1 = 0; } @@ -251,9 +248,7 @@ namespace MMU Result remap(u64 virt, int flags) { - auto rc = apply_cascading_flags(virt, flags); - if (rc.has_error()) return rc.release_error(); - auto& l1 = *rc.release_value(); + auto& l1 = *TRY(apply_cascading_flags(virt, flags)); if (!l1.present) return err; l1.read_write = (flags & Flags::ReadWrite); l1.user = (flags & Flags::User); @@ -265,9 +260,7 @@ namespace MMU Result unmap(u64 virt) { - auto rc = find_entry(virt); - if (rc.has_error()) return rc.release_error(); - auto& l1 = *rc.release_value(); + auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err; u64 address = l1.get_address(); memset(&l1, 0, sizeof(l1)); @@ -277,18 +270,14 @@ namespace MMU Result get_physical(u64 virt) { - auto rc = find_entry(virt); - if (rc.has_error()) return rc.release_error(); - auto& l1 = *rc.release_value(); + auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err; return l1.get_address(); } Result get_flags(u64 virt) { - auto rc = find_entry(virt); - if (rc.has_error()) return rc.release_error(); - auto& l1 = *rc.release_value(); + auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err; return arch_flags_to_mmu(l1); } From 2e2656a02fdc69c08e2db0383d849e57cb305286 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 18 Nov 2022 17:59:19 +0100 Subject: [PATCH 026/407] Add static assertions to constexpr functions --- luna/Alignment.h | 19 ++++++++++++++++++- luna/Types.h | 14 +++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/luna/Alignment.h b/luna/Alignment.h index 0cb7ced3..e51af9af 100644 --- a/luna/Alignment.h +++ b/luna/Alignment.h @@ -5,18 +5,35 @@ template constexpr T is_aligned(T value, T align_base) return (value % align_base == 0); } +static_assert(is_aligned(1024, 512)); +static_assert(!is_aligned(235, 32)); +static_assert(is_aligned(40960, 4096)); + template constexpr T align_down(T value, T align_base) { return value - (value % align_base); } +static_assert(align_down(598, 512) == 512); +static_assert(align_down(194, 64) == 192); +static_assert(align_down(62, 31) == 62); + template constexpr T align_up(T value, T align_base) { if (is_aligned(value, align_base)) return value; return align_down(value, align_base) + align_base; } +static_assert(align_up(598, 512) == 1024); +static_assert(align_up(194, 64) == 256); +static_assert(align_up(62, 31) == 62); + template constexpr T get_blocks_from_size(T value, T block_size) { return (value + (block_size - 1)) / block_size; -} \ No newline at end of file +} + +static_assert(get_blocks_from_size(40960, 4096) == 10); +static_assert(get_blocks_from_size(194, 64) == 4); +static_assert(get_blocks_from_size(2, 32) == 1); +static_assert(get_blocks_from_size(0, 256) == 0); \ No newline at end of file diff --git a/luna/Types.h b/luna/Types.h index ad06edfe..a872a576 100644 --- a/luna/Types.h +++ b/luna/Types.h @@ -10,4 +10,16 @@ typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; typedef size_t usize; -typedef long isize; \ No newline at end of file +typedef long isize; + +static_assert(sizeof(u8) == 1UL); +static_assert(sizeof(u16) == 2UL); +static_assert(sizeof(u32) == 4UL); +static_assert(sizeof(u64) == 8UL); +static_assert(sizeof(i8) == 1UL); +static_assert(sizeof(i16) == 2UL); +static_assert(sizeof(i32) == 4UL); +static_assert(sizeof(i64) == 8UL); + +static_assert(sizeof(usize) == 8UL); +static_assert(sizeof(isize) == 8UL); \ No newline at end of file From 860f13cd7e517c7f508ff350cb0f89defe21f2d7 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 18 Nov 2022 18:02:38 +0100 Subject: [PATCH 027/407] Rename align_base to alignment --- luna/Alignment.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/luna/Alignment.h b/luna/Alignment.h index e51af9af..e69c0aad 100644 --- a/luna/Alignment.h +++ b/luna/Alignment.h @@ -1,27 +1,27 @@ #pragma once -template constexpr T is_aligned(T value, T align_base) +template constexpr T is_aligned(T value, T alignment) { - return (value % align_base == 0); + return (value % alignment == 0); } static_assert(is_aligned(1024, 512)); static_assert(!is_aligned(235, 32)); static_assert(is_aligned(40960, 4096)); -template constexpr T align_down(T value, T align_base) +template constexpr T align_down(T value, T alignment) { - return value - (value % align_base); + return value - (value % alignment); } static_assert(align_down(598, 512) == 512); static_assert(align_down(194, 64) == 192); static_assert(align_down(62, 31) == 62); -template constexpr T align_up(T value, T align_base) +template constexpr T align_up(T value, T alignment) { - if (is_aligned(value, align_base)) return value; - return align_down(value, align_base) + align_base; + if (is_aligned(value, alignment)) return value; + return align_down(value, alignment) + alignment; } static_assert(align_up(598, 512) == 1024); From 109de54822c0739a3d9dfd15d09b70b6757d65bd Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 18 Nov 2022 20:51:25 +0100 Subject: [PATCH 028/407] Provide stubbed handlers for many more x86 exceptions I am now officially a big-boy OS developer, I read the Intel manuals for this!! (Not that the OSDev wiki doesn't have the information, but it was missing descriptions for some more obscure exceptions) --- kernel/src/arch/x86_64/CPU.asm | 41 +++++++++++++--- kernel/src/arch/x86_64/CPU.cpp | 90 +++++++++++++++++++++++++++++++--- kernel/src/main.cpp | 6 +-- 3 files changed, 121 insertions(+), 16 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 329f576f..f59fca57 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -1,8 +1,3 @@ -section .data -global __divisor -__divisor: - dd 0 - section .text global enable_sse enable_sse: @@ -77,6 +72,8 @@ load_tr: %endmacro extern arch_interrupt_entry +extern arch_double_fault +extern arch_machine_check _asm_interrupt_entry: push rax @@ -120,4 +117,36 @@ _asm_interrupt_entry: iretq -ISR 0 ; divide by zero \ No newline at end of file +ISR 0 ; divide by zero (#DE) +ISR 1 ; debug (#DB) +ISR 2 ; non-maskable interrupt +ISR 3 ; breakpoint (#BP) +ISR 4 ; overflow (#OF) +ISR 5 ; bound range exceeded (#BR) +ISR 6 ; invalid opcode (#UD) +ISR 7 ; device not available (#NM) + +global _isr8 +_isr8: ; double fault (#DF) + jmp arch_double_fault + ud2 ; we aren't even pushing a return address for arch_double_fault, this is truly UNREACHABLE + +; ISR 9 obsolete +ISR_ERROR 10 ; invalid tss (#TS) +ISR_ERROR 11 ; segment not present (#NP) +ISR_ERROR 12 ; stack-segment fault (#SS) +ISR_ERROR 13 ; general protection fault (#GP) +ISR_ERROR 14 ; page fault (#PF) +; ISR 15 reserved +ISR 16 ; x87 floating-point exception (#MF) +ISR_ERROR 17 ; alignment check (#AC) + +global _isr18 +_isr18: ; machine check (#MC) + jmp arch_machine_check + ud2 ; same as above + +ISR 19 ; SIMD floating-point exception (#XM) +ISR 20 ; virtualization exception (#VE) +ISR_ERROR 21 ; control-protection exception (#CP) +; ISR 22-31 reserved \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 941f464f..e5144ed8 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -162,10 +162,50 @@ static void idt_add_handler(short num, void* handler, u8 type_attr) #define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) INT(0); +INT(1); +INT(2); +INT(3); +INT(4); +INT(5); +INT(6); +INT(7); +INT(8); +INT(10); +INT(11); +INT(12); +INT(13); +INT(14); +INT(16); +INT(17); +INT(18); +INT(19); +INT(20); +INT(21); static void setup_idt() { - TRAP(0); // divide by zero + memset(idt, 0, sizeof(idt)); + + TRAP(0); + TRAP(1); + TRAP(2); + TRAP(3); + TRAP(4); + TRAP(5); + TRAP(6); + TRAP(7); + TRAP(8); + TRAP(10); + TRAP(11); + TRAP(12); + TRAP(13); + TRAP(14); + TRAP(16); + TRAP(17); + TRAP(18); + TRAP(19); + TRAP(20); + TRAP(21); static IDTR idtr; idtr.limit = 0x0FFF; @@ -175,14 +215,40 @@ static void setup_idt() // Interrupt handling +#define FIXME_UNHANDLED_INTERRUPT(name) \ + Serial::println("FIXME(interrupt): " name); \ + CPU::efficient_halt(); + +extern "C" void handle_x86_exception([[maybe_unused]] Registers* regs) +{ + switch (regs->isr) + { + case 0: FIXME_UNHANDLED_INTERRUPT("Division by zero"); + case 1: FIXME_UNHANDLED_INTERRUPT("Debug interrupt"); + case 2: FIXME_UNHANDLED_INTERRUPT("NMI (Non-maskable interrupt)"); + case 3: FIXME_UNHANDLED_INTERRUPT("Breakpoint"); + case 4: FIXME_UNHANDLED_INTERRUPT("Overflow"); + case 5: FIXME_UNHANDLED_INTERRUPT("Bound range exceeded"); + case 6: FIXME_UNHANDLED_INTERRUPT("Invalid opcode"); + case 7: FIXME_UNHANDLED_INTERRUPT("Device not available"); + case 10: FIXME_UNHANDLED_INTERRUPT("Invalid TSS"); + case 11: FIXME_UNHANDLED_INTERRUPT("Segment not present"); + case 12: FIXME_UNHANDLED_INTERRUPT("Stack-segment fault"); + case 13: FIXME_UNHANDLED_INTERRUPT("General protection fault"); + case 14: FIXME_UNHANDLED_INTERRUPT("Page fault"); + case 16: FIXME_UNHANDLED_INTERRUPT("x87 floating-point exception"); + case 17: FIXME_UNHANDLED_INTERRUPT("Alignment check"); + case 19: FIXME_UNHANDLED_INTERRUPT("SIMD floating-point exception"); + case 20: FIXME_UNHANDLED_INTERRUPT("Virtualization exception"); + case 21: FIXME_UNHANDLED_INTERRUPT("Control-protection exception"); + default: FIXME_UNHANDLED_INTERRUPT("Reserved exception or #DF/#MC, which shouldn't call handle_x86_exception"); + } +} + // Called from _asm_interrupt_entry extern "C" void arch_interrupt_entry(Registers* regs) { - if (regs->isr < 32) - { - Serial::println("Exception catched! Halting."); - CPU::efficient_halt(); - } + if (regs->isr < 32) handle_x86_exception(regs); else { Serial::println("IRQ catched! Halting."); @@ -190,6 +256,18 @@ extern "C" void arch_interrupt_entry(Registers* regs) } } +extern "C" [[noreturn]] void arch_double_fault() +{ + Serial::println("ERROR: Catched double fault"); + CPU::efficient_halt(); +} + +extern "C" [[noreturn]] void arch_machine_check() +{ + Serial::println("ERROR: Machine check failed"); + CPU::efficient_halt(); +} + // Generic CPU code static bool test_nx() diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index a7be3ce5..deec4804 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -84,11 +84,9 @@ extern "C" [[noreturn]] void _start() Serial::println("Successfully unmapped address"); - extern int __divisor; // divisor is defined as 0, we do it this way so the compiler doesn't catch it (this is - // testing exception handling) - [[maybe_unused]] volatile int div_rc = 4 / __divisor; + *ptr = 16; - Serial::println("ERROR: Still here after division by zero"); + Serial::println("ERROR: Still here after page fault"); CPU::efficient_halt(); } \ No newline at end of file From 762ca844d8a1989d6de2c3d8c9e8c39574944d53 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 18 Nov 2022 21:04:53 +0100 Subject: [PATCH 029/407] Add CPU::platform_string --- kernel/src/arch/CPU.h | 2 ++ kernel/src/arch/x86_64/CPU.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index a471b0d0..e2d2313c 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -6,6 +6,8 @@ struct Registers; namespace CPU { Result identify(); + const char* platform_string(); + void platform_init(); [[noreturn]] void efficient_halt(); diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index e5144ed8..c9a2010f 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -296,6 +296,11 @@ namespace CPU return brand_string; } + const char* platform_string() + { + return "x86_64"; + } + void platform_init() { enable_sse(); From 1b3243a80cf22ff62d0a8d9463a0d40ca3bd36a7 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 18 Nov 2022 21:12:54 +0100 Subject: [PATCH 030/407] Add ctype.h functions to the Luna library --- luna/CType.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 luna/CType.h diff --git a/luna/CType.h b/luna/CType.h new file mode 100644 index 00000000..5e8fc45c --- /dev/null +++ b/luna/CType.h @@ -0,0 +1,78 @@ +#pragma once + +inline constexpr int _isascii(int c) +{ + return !(c & ~0x7f); +} + +inline constexpr int _isblank(int c) +{ + return c == ' ' || c == '\t'; +} + +inline constexpr int _iscntrl(int c) +{ + return (unsigned int)c < 0x20 || c == 0x7f; +} + +inline constexpr int _isdigit(int c) +{ + return c >= '0' && c < ':'; +} + +inline constexpr int _isgraph(int c) +{ + return (unsigned int)c - 0x21 < 0x5e; +} + +inline constexpr int _islower(int c) +{ + return c >= 'a' && c < '{'; +} + +inline constexpr int _isupper(int c) +{ + return c >= 'A' && c < '['; +} + +inline constexpr int _isprint(int c) +{ + return (unsigned int)c - 0x20 < 0x5f; +} + +inline constexpr int _isalpha(int c) +{ + return _islower(c) || _isupper(c); +} + +inline constexpr int _isalnum(int c) +{ + return _isalpha(c) || _isdigit(c); +} + +inline constexpr int _ispunct(int c) +{ + return _isgraph(c) && !_isalnum(c); +} + +inline constexpr int _isspace(int c) +{ + return c == ' ' || (unsigned int)c - '\t' < 5; +} + +inline constexpr int _isxdigit(int c) +{ + return _isdigit(c) || ((unsigned int)c | 32) - 'a' < 6; +} + +inline constexpr int _tolower(int c) +{ + if (_isupper(c)) return c | 32; + return c; +} + +inline constexpr int _toupper(int c) +{ + if (_islower(c)) return c & 0x5f; + return c; +} \ No newline at end of file From be2e915d0d0ee62afc79854a74d11d18f6d1dce4 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 18 Nov 2022 21:17:26 +0100 Subject: [PATCH 031/407] Use the standard names for ctype functions if inside moon or _LUNA_OVERRIDE_STDC is defined --- luna/CType.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/luna/CType.h b/luna/CType.h index 5e8fc45c..79daf531 100644 --- a/luna/CType.h +++ b/luna/CType.h @@ -75,4 +75,22 @@ inline constexpr int _toupper(int c) { if (_islower(c)) return c & 0x5f; return c; -} \ No newline at end of file +} + +#if defined(_LUNA_OVERRIDE_STDC) || defined(IN_MOON) +#define isalnum _isalnum +#define isalpha _isalpha +#define isascii _isascii +#define iscntrl _iscntrl +#define isdigit _isdigit +#define isxdigit _isxdigit +#define isspace _isspace +#define ispunct _ispunct +#define isprint _isprint +#define isgraph _isgraph +#define islower _islower +#define isupper _isupper +#define isblank _isblank +#define tolower _tolower +#define toupper _toupper +#endif \ No newline at end of file From 603ff46d8c6e46219f9b9e20c49a510b910398bc Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 12:30:36 +0100 Subject: [PATCH 032/407] Add a format implementation --- kernel/CMakeLists.txt | 3 +- kernel/src/arch/Serial.cpp | 16 ++ kernel/src/arch/Serial.h | 1 + kernel/src/luna/Format.cpp | 3 + kernel/src/luna/String.cpp | 3 + kernel/src/main.cpp | 2 + kernel/src/string.cpp | 2 - luna/Format.h | 290 +++++++++++++++++++++++++++++++++++++ luna/NumberParsing.h | 40 +++++ 9 files changed, 357 insertions(+), 3 deletions(-) create mode 100644 kernel/src/luna/Format.cpp create mode 100644 kernel/src/luna/String.cpp delete mode 100644 kernel/src/string.cpp create mode 100644 luna/Format.h create mode 100644 luna/NumberParsing.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 85aad645..fbe0b719 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,10 +1,11 @@ set(SOURCES src/main.cpp - src/string.cpp + src/luna/String.cpp src/Framebuffer.cpp src/MemoryManager.cpp src/Init.cpp src/arch/Serial.cpp + src/luna/Format.cpp ) # x86-64 specific diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index ddf3a879..07d9ce26 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -1,4 +1,5 @@ #include "arch/Serial.h" +#include namespace Serial { @@ -17,4 +18,19 @@ namespace Serial print(str); putchar('\n'); } + + int printf(const char* format, ...) + { + va_list ap; + va_start(ap, format); + isize rc = cstyle_format( + format, + [](char c, void*) -> int { + putchar(c); + return 0; + }, + nullptr, ap); + va_end(ap); + return (int)rc; + } } \ No newline at end of file diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h index 8d7b18aa..92a0725e 100644 --- a/kernel/src/arch/Serial.h +++ b/kernel/src/arch/Serial.h @@ -7,4 +7,5 @@ namespace Serial void write(const char* str, usize size); void print(const char* str); void println(const char* str); + int printf(const char* str, ...); } \ No newline at end of file diff --git a/kernel/src/luna/Format.cpp b/kernel/src/luna/Format.cpp new file mode 100644 index 00000000..c1307639 --- /dev/null +++ b/kernel/src/luna/Format.cpp @@ -0,0 +1,3 @@ +/* This file instantiates the functions from Luna's Format.h into a translation unit, and serves no other purpose. */ +#define _LUNA_IMPLEMENTATION +#include \ No newline at end of file diff --git a/kernel/src/luna/String.cpp b/kernel/src/luna/String.cpp new file mode 100644 index 00000000..20590d5d --- /dev/null +++ b/kernel/src/luna/String.cpp @@ -0,0 +1,3 @@ +/* This file instantiates the functions from Luna's String.h into a translation unit, and serves no other purpose. */ +#define _LUNA_IMPLEMENTATION +#include \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index deec4804..e0c7d376 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -14,6 +14,8 @@ extern "C" [[noreturn]] void _start() Serial::println("Hello, world!"); + Serial::printf("Current platform: %s\n", CPU::platform_string()); + Framebuffer::rect(0, 0, 200, 200, 0xFF00FF00); auto cpu_name_or_error = CPU::identify(); diff --git a/kernel/src/string.cpp b/kernel/src/string.cpp deleted file mode 100644 index 7c431e6c..00000000 --- a/kernel/src/string.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define _LUNA_IMPLEMENTATION -#include \ No newline at end of file diff --git a/luna/Format.h b/luna/Format.h new file mode 100644 index 00000000..1be99216 --- /dev/null +++ b/luna/Format.h @@ -0,0 +1,290 @@ +#pragma once +#include +#include +#include + +typedef int (*callback_t)(char, void*); + +#ifdef _LUNA_IMPLEMENTATION +#include + +extern "C" usize strlen(const char*); + +typedef usize flags_t; +#define FLAG_ZERO_PAD 1 << 0 +#define FLAG_LEFT_ALIGN 1 << 1 +#define FLAG_BLANK_SIGNED 1 << 2 +#define FLAG_ALTERNATE 1 << 3 +#define FLAG_SIGN 1 << 4 +#define FLAG_USE_PRECISION 1 << 5 +#define FLAG_LONG 1 << 6 +#define FLAG_LONG_LONG 1 << 7 +#define FLAG_SHORT 1 << 8 +#define FLAG_CHAR 1 << 9 + +struct format_state +{ + usize count; + callback_t callback; + void* arg; +}; + +struct conv_state +{ + flags_t flags; + usize width; + usize precision; +}; + +static inline int cstyle_format_putchar(char c, format_state& state) +{ + state.count++; + return state.callback(c, state.arg); +} + +static inline int cstyle_format_puts(const char* s, format_state& state) +{ + while (*s) + { + if (cstyle_format_putchar(*s, state)) return -1; + s++; + } + + return 0; +} + +#define TRY_PUTCHAR(c, state) \ + if (cstyle_format_putchar(c, state)) return -1; + +#define TRY_PUTS(s, state) \ + if (cstyle_format_puts(s, state)) return -1; + +static int start_pad(const conv_state& vstate, format_state& state, usize start) +{ + if (!(vstate.flags & FLAG_LEFT_ALIGN)) + { + while (start++ < vstate.width) TRY_PUTCHAR(' ', state); + } + + return 0; +} + +#define TRY_START_PAD(vstate, state, start) \ + if (start_pad(vstate, state, start)) return -1; + +static int end_pad(const conv_state& vstate, format_state& state, usize start) +{ + if (vstate.flags & FLAG_LEFT_ALIGN) + { + while (start++ < vstate.width) TRY_PUTCHAR(' ', state); + } + + return 0; +} + +#define TRY_END_PAD(vstate, state, start) \ + if (end_pad(vstate, state, start)) return -1; + +static flags_t parse_flags(const char** format) +{ + flags_t result = 0; + + while (true) + { + switch (**format) + { + case '#': + result |= FLAG_ALTERNATE; + (*format)++; + break; + case '0': + result |= FLAG_ZERO_PAD; + (*format)++; + break; + case ' ': + result |= FLAG_BLANK_SIGNED; + (*format)++; + break; + case '-': + result |= FLAG_LEFT_ALIGN; + (*format)++; + break; + case '+': + result |= FLAG_SIGN; + (*format)++; + break; + default: return result; + } + } +} + +static usize parse_width(const char** format, flags_t& flags, va_list ap) +{ + usize result = 0; + + if (_isdigit(**format)) result = _atou(format); + else if (**format == '*') + { + const int width = va_arg(ap, int); + if (width >= 0) result = (usize)width; + else + { + flags |= FLAG_LEFT_ALIGN; + result = (usize)-width; + } + } + + return result; +} + +static usize parse_precision(const char** format, flags_t& flags, va_list ap) +{ + usize result = 0; + + if (**format == '.') + { + (*format)++; + + flags |= FLAG_USE_PRECISION; + + if (_isdigit(**format)) result = _atou(format); + else if (**format == '*') + { + const int precision = va_arg(ap, int); + if (precision >= 0) result = (usize)precision; + else + result = 0; + } + } + + return result; +} + +static void parse_length(const char** format, flags_t& flags) +{ + // FIXME: Support %j (intmax_t/uintmax_t) + switch (**format) + { + case 'h': + flags |= FLAG_SHORT; + (*format)++; + if (**format == 'h') + { + flags |= FLAG_CHAR; + (*format)++; + } + break; + case 'l': + flags |= FLAG_LONG; + (*format)++; + if (**format == 'l') + { + flags |= FLAG_LONG_LONG; + (*format)++; + } + break; + case 't': + flags |= (sizeof(ptrdiff_t) == sizeof(long)) ? FLAG_LONG : FLAG_LONG_LONG; + (*format)++; + break; + case 'z': + flags |= (sizeof(size_t) == sizeof(long)) ? FLAG_LONG : FLAG_LONG_LONG; + (*format)++; + break; + default: break; + } +} + +static bool is_integer_format_specifier(char c) +{ + return (c == 'd') || (c == 'i') || (c == 'u') || (c == 'x') || (c == 'X') || (c == 'o') || (c == 'b'); +} + +static int output_integer(char, const conv_state&, format_state&, va_list) +{ + return -1; // FIXME: Implement this. +} + +#endif + +isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap) +#ifdef _LUNA_IMPLEMENTATION +{ + format_state state; + state.callback = callback; + state.arg = arg; + state.count = 0; + + while (*format) + { + if (*format != '%') + { + TRY_PUTCHAR(*format, state); + format++; + continue; + } + + format++; + + // %[flags][width][.precision][length]conversion + + flags_t flags = parse_flags(&format); + usize width = parse_width(&format, flags, ap); + usize precision = parse_precision(&format, flags, ap); + parse_length(&format, flags); + + conv_state vstate = {flags, width, precision}; + + char specifier = *format; + format++; + + if (is_integer_format_specifier(specifier)) + { + if (output_integer(specifier, vstate, state, ap)) return -1; + } + else if (specifier == 'c') + { + const char c = (char)va_arg(ap, int); + + TRY_START_PAD(vstate, state, 1); + TRY_PUTCHAR(c, state); + TRY_END_PAD(vstate, state, 1); + + continue; + } + else if (specifier == 's') + { + const char* str = va_arg(ap, const char*); + if (str == nullptr) + { + TRY_START_PAD(vstate, state, 6); + TRY_PUTS("(null)", state); + TRY_END_PAD(vstate, state, 6); + continue; + } + else + { + usize len = strlen(str); + + bool use_precision = (flags & FLAG_USE_PRECISION); + if (use_precision && len > precision) len = precision; + + TRY_START_PAD(vstate, state, len); + while (*str && (!use_precision || precision)) + { + TRY_PUTCHAR(*str, state); + precision--; + str++; + } + TRY_END_PAD(vstate, state, len); + continue; + } + } + else { continue; } + } + + return (isize)state.count; +} +#else + ; +#endif \ No newline at end of file diff --git a/luna/NumberParsing.h b/luna/NumberParsing.h new file mode 100644 index 00000000..aaa20c62 --- /dev/null +++ b/luna/NumberParsing.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include + +inline usize _atou(const char** str) +{ + usize val = 0; + + while (_isdigit(**str)) + { + val = (10 * val) + (**str - '0'); + (*str)++; + } + + return val; +} + +inline isize _atos(const char** str) +{ + bool neg = false; + isize val = 0; + + switch (**str) + { + case '-': + neg = true; + (*str)++; + break; + case '+': (*str)++; break; + default: break; + } + + while (_isdigit(**str)) + { + val = (10 * val) + (**str - '0'); + (*str)++; + } + + return neg ? -val : val; +} From 4ebf244d3bbee104ac41c61bf1c50566d7fe2964 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 13:15:13 +0100 Subject: [PATCH 033/407] Support printing some integers in output_integer --- kernel/src/main.cpp | 2 + luna/Format.h | 147 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index e0c7d376..258e35ee 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -26,6 +26,8 @@ extern "C" [[noreturn]] void _start() const u64 address = 0xfffffffff8000000; + Serial::printf("Mapping address 0x%lx\n", address); + u64 physical = MemoryManager::alloc_physical_page().release_value(); auto rc = MMU::map(address, physical, MMU::ReadWrite); diff --git a/luna/Format.h b/luna/Format.h index 1be99216..c683d882 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -200,9 +200,152 @@ static bool is_integer_format_specifier(char c) return (c == 'd') || (c == 'i') || (c == 'u') || (c == 'x') || (c == 'X') || (c == 'o') || (c == 'b'); } -static int output_integer(char, const conv_state&, format_state&, va_list) +template static usize to_string(T value, T base, char* buf, usize max, bool uppercase) { - return -1; // FIXME: Implement this. + usize i = 0; + if (!value && max) + { + buf[i] = '0'; + return 1; + } + do { + int digit = (int)(value % base); + char c = (char)(digit < 10 ? '0' + digit : ((uppercase ? 'A' : 'a') + (digit - 10))); + buf[i++] = c; + value /= base; + } while (value && i < max); + return i; +} + +static int output_integer(char specifier, const conv_state& vstate, format_state& state, va_list ap) +{ + usize base = 10; + bool is_signed = false; + bool uppercase = false; + bool negative = false; + + if (specifier == 'd' || specifier == 'i') is_signed = true; + switch (specifier) + { + case 'x': + case 'X': base = 16; break; + case 'o': base = 8; break; + case 'b': base = 2; break; + default: break; + } + if (specifier == 'X') uppercase = true; + + char buf[1024]; + usize buflen; + if (vstate.flags & FLAG_CHAR) + { + if (is_signed) + { + char v = (char)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (char)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned char v = (unsigned char)va_arg(ap, unsigned int); + buflen = to_string(v, (unsigned char)base, buf, sizeof(buf), uppercase); + } + } + else if (vstate.flags & FLAG_SHORT) + { + if (is_signed) + { + short v = (short)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (short)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned short v = (unsigned short)va_arg(ap, unsigned int); + buflen = to_string(v, (unsigned short)base, buf, sizeof(buf), uppercase); + } + } + else if (vstate.flags & FLAG_LONG_LONG) + { + if (is_signed) + { + long long v = va_arg(ap, long long); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (long long)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned long long v = va_arg(ap, unsigned long long); + buflen = to_string(v, (unsigned long long)base, buf, sizeof(buf), uppercase); + } + } + else if (vstate.flags & FLAG_LONG) + { + if (is_signed) + { + long v = va_arg(ap, long); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (long)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned long v = va_arg(ap, unsigned long); + buflen = to_string(v, (unsigned long)base, buf, sizeof(buf), uppercase); + } + } + else + { + if (is_signed) + { + int v = va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (int)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned int v = va_arg(ap, unsigned int); + buflen = to_string(v, (unsigned int)base, buf, sizeof(buf), uppercase); + } + } + + // FIXME: Start padding and alternate forms. + + if (buflen < sizeof(buf)) + { + if (negative) buf[buflen++] = '-'; + else if (vstate.flags & FLAG_SIGN) + buf[buflen++] = '+'; + else if (vstate.flags & FLAG_BLANK_SIGNED) + buf[buflen++] = ' '; + } + + usize i = buflen; + + while (i--) TRY_PUTCHAR(buf[i], state); + + TRY_END_PAD(vstate, state, buflen); + + return 0; } #endif From c48203997a0b9b2bfcaf2f66b1e5e33ac80f2963 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 13:21:21 +0100 Subject: [PATCH 034/407] Move output_integer into a function that accepts value arguments --- luna/Format.h | 199 ++++++++++++++++++++++++++------------------------ 1 file changed, 103 insertions(+), 96 deletions(-) diff --git a/luna/Format.h b/luna/Format.h index c683d882..b2b47506 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -217,14 +217,12 @@ template static usize to_string(T value, T base, char* buf, usize m return i; } -static int output_integer(char specifier, const conv_state& vstate, format_state& state, va_list ap) +template +static int output_integer(char specifier, const conv_state& vstate, format_state& state, T value, bool negative) { usize base = 10; - bool is_signed = false; bool uppercase = false; - bool negative = false; - if (specifier == 'd' || specifier == 'i') is_signed = true; switch (specifier) { case 'x': @@ -236,97 +234,7 @@ static int output_integer(char specifier, const conv_state& vstate, format_state if (specifier == 'X') uppercase = true; char buf[1024]; - usize buflen; - if (vstate.flags & FLAG_CHAR) - { - if (is_signed) - { - char v = (char)va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (char)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned char v = (unsigned char)va_arg(ap, unsigned int); - buflen = to_string(v, (unsigned char)base, buf, sizeof(buf), uppercase); - } - } - else if (vstate.flags & FLAG_SHORT) - { - if (is_signed) - { - short v = (short)va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (short)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned short v = (unsigned short)va_arg(ap, unsigned int); - buflen = to_string(v, (unsigned short)base, buf, sizeof(buf), uppercase); - } - } - else if (vstate.flags & FLAG_LONG_LONG) - { - if (is_signed) - { - long long v = va_arg(ap, long long); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (long long)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned long long v = va_arg(ap, unsigned long long); - buflen = to_string(v, (unsigned long long)base, buf, sizeof(buf), uppercase); - } - } - else if (vstate.flags & FLAG_LONG) - { - if (is_signed) - { - long v = va_arg(ap, long); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (long)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned long v = va_arg(ap, unsigned long); - buflen = to_string(v, (unsigned long)base, buf, sizeof(buf), uppercase); - } - } - else - { - if (is_signed) - { - int v = va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (int)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned int v = va_arg(ap, unsigned int); - buflen = to_string(v, (unsigned int)base, buf, sizeof(buf), uppercase); - } - } + usize buflen = to_string(value, (T)base, buf, sizeof(buf), uppercase); // FIXME: Start padding and alternate forms. @@ -348,6 +256,105 @@ static int output_integer(char specifier, const conv_state& vstate, format_state return 0; } +static int va_output_integer(char specifier, const conv_state& vstate, format_state& state, va_list ap) +{ + bool is_signed = false; + bool negative = false; + + if (specifier == 'd' || specifier == 'i') is_signed = true; + + if (vstate.flags & FLAG_CHAR) + { + if (is_signed) + { + char v = (char)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned char v = (unsigned char)va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_SHORT) + { + if (is_signed) + { + short v = (short)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned short v = (unsigned short)va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_LONG_LONG) + { + if (is_signed) + { + long long v = va_arg(ap, long long); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned long long v = va_arg(ap, unsigned long long); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_LONG) + { + if (is_signed) + { + long v = va_arg(ap, long); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned long v = va_arg(ap, unsigned long); + return output_integer(specifier, vstate, state, v, false); + } + } + else + { + if (is_signed) + { + int v = va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned int v = va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } +} + #endif isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap) @@ -383,7 +390,7 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list if (is_integer_format_specifier(specifier)) { - if (output_integer(specifier, vstate, state, ap)) return -1; + if (va_output_integer(specifier, vstate, state, ap)) return -1; } else if (specifier == 'c') { From 88af7a915b29b484e4673ebff0da46c106650d3f Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 13:59:06 +0100 Subject: [PATCH 035/407] Start padding and alternate forms for integers --- luna/Format.h | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/luna/Format.h b/luna/Format.h index b2b47506..f3c38144 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -200,7 +200,7 @@ static bool is_integer_format_specifier(char c) return (c == 'd') || (c == 'i') || (c == 'u') || (c == 'x') || (c == 'X') || (c == 'o') || (c == 'b'); } -template static usize to_string(T value, T base, char* buf, usize max, bool uppercase) +static usize to_string(usize value, usize base, char* buf, usize max, bool uppercase) { usize i = 0; if (!value && max) @@ -217,8 +217,7 @@ template static usize to_string(T value, T base, char* buf, usize m return i; } -template -static int output_integer(char specifier, const conv_state& vstate, format_state& state, T value, bool negative) +static int output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) { usize base = 10; bool uppercase = false; @@ -233,10 +232,37 @@ static int output_integer(char specifier, const conv_state& vstate, format_state } if (specifier == 'X') uppercase = true; - char buf[1024]; - usize buflen = to_string(value, (T)base, buf, sizeof(buf), uppercase); + if (base == 10) vstate.flags &= ~FLAG_ALTERNATE; // decimal doesn't have an alternate form - // FIXME: Start padding and alternate forms. + char buf[1024]; + usize buflen = to_string(value, base, buf, sizeof(buf), uppercase); + + if (!(vstate.flags & FLAG_LEFT_ALIGN) && + (vstate.flags & FLAG_ZERO_PAD)) // we're padding with zeroes from the beginning + { + bool extra_char = + negative || ((vstate.flags & FLAG_SIGN) || + (vstate.flags & FLAG_BLANK_SIGNED)); // are we adding an extra character after the buffer? + if (vstate.width && extra_char) vstate.width--; + + if (vstate.width && (vstate.flags & FLAG_ALTERNATE)) // fit in the characters we're using for the alternate form + { + vstate.width--; + if (vstate.width && (base == 2 || base == 16)) vstate.width--; + } + + while (buflen < vstate.width && buflen < sizeof(buf)) buf[buflen++] = '0'; + } + + while (buflen < vstate.precision && buflen < sizeof(buf)) buf[buflen++] = '0'; + + if (vstate.flags & FLAG_ALTERNATE) + { + if (base == 16 && !uppercase && buflen < sizeof(buf)) buf[buflen++] = 'x'; + if (base == 16 && uppercase && buflen < sizeof(buf)) buf[buflen++] = 'X'; + if (base == 2 && buflen < sizeof(buf)) buf[buflen++] = 'b'; + if (buflen < sizeof(buf)) buf[buflen++] = '0'; + } if (buflen < sizeof(buf)) { @@ -247,6 +273,8 @@ static int output_integer(char specifier, const conv_state& vstate, format_state buf[buflen++] = ' '; } + if (!(vstate.flags & FLAG_ZERO_PAD)) TRY_START_PAD(vstate, state, buflen); + usize i = buflen; while (i--) TRY_PUTCHAR(buf[i], state); @@ -256,7 +284,7 @@ static int output_integer(char specifier, const conv_state& vstate, format_state return 0; } -static int va_output_integer(char specifier, const conv_state& vstate, format_state& state, va_list ap) +static int va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) { bool is_signed = false; bool negative = false; From bad856afe0dabd96641a97b8144daf0962dd00bc Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 15:26:29 +0100 Subject: [PATCH 036/407] Add %p and %% to cstyle_format --- luna/Format.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/luna/Format.h b/luna/Format.h index f3c38144..10f43c30 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -10,7 +10,7 @@ typedef int (*callback_t)(char, void*); extern "C" usize strlen(const char*); -typedef usize flags_t; +typedef int flags_t; #define FLAG_ZERO_PAD 1 << 0 #define FLAG_LEFT_ALIGN 1 << 1 #define FLAG_BLANK_SIGNED 1 << 2 @@ -224,6 +224,7 @@ static int output_integer(char specifier, conv_state& vstate, format_state& stat switch (specifier) { + case 'p': case 'x': case 'X': base = 16; break; case 'o': base = 8; break; @@ -291,6 +292,8 @@ static int va_output_integer(char specifier, conv_state& vstate, format_state& s if (specifier == 'd' || specifier == 'i') is_signed = true; + if (!is_signed) vstate.flags &= ~(FLAG_SIGN | FLAG_BLANK_SIGNED); + if (vstate.flags & FLAG_CHAR) { if (is_signed) @@ -404,6 +407,12 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list format++; + if (*format == '%') + { + TRY_PUTCHAR('%', state); + continue; + } + // %[flags][width][.precision][length]conversion flags_t flags = parse_flags(&format); @@ -419,6 +428,22 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list if (is_integer_format_specifier(specifier)) { if (va_output_integer(specifier, vstate, state, ap)) return -1; + continue; + } + else if (specifier == 'p') + { + void* ptr = va_arg(ap, void*); + if (ptr == nullptr) + { + TRY_START_PAD(vstate, state, 5); + TRY_PUTS("(nil)", state); + TRY_END_PAD(vstate, state, 5); + continue; + } + vstate.width = (sizeof(void*) * 2) + 2; + vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE); + if (output_integer('p', vstate, state, (usize)ptr, false)) return -1; + continue; } else if (specifier == 'c') { From 56c2ca3381a34573b9759843193a6d7777ca011e Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 15:27:55 +0100 Subject: [PATCH 037/407] Add _strtoi and _strtou --- luna/NumberParsing.h | 113 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/luna/NumberParsing.h b/luna/NumberParsing.h index aaa20c62..a0fca6f2 100644 --- a/luna/NumberParsing.h +++ b/luna/NumberParsing.h @@ -38,3 +38,116 @@ inline isize _atos(const char** str) return neg ? -val : val; } + +inline usize _strtou(const char* str, const char** endptr, int base) +{ + usize val = 0; + + auto valid_digit = [](int _base, char c) -> bool { + if (_base <= 10) + { + if (!_isdigit(c)) return false; + if ((c - '0') < _base) return true; + } + else + { + if (!_isalnum(c)) return false; + if (_isdigit(c)) return true; + bool lower = _islower(c); + if (((c - lower ? 'a' : 'A') + 10) < _base) return true; + return false; + } + }; + + auto to_digit = [](char c) -> usize { + if (_isdigit(c)) return c - '0'; + if (_islower(c)) return (c - 'a') + 10; + return (c - 'A') + 10; + }; + + while (_isspace(*str)) str++; + + if ((base == 0 || base == 16) && *str == '0') + { + str++; + if (_tolower(*str) == 'x') + { + base = 16; + str++; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + while (valid_digit(base, *str)) + { + val = (base * val) + to_digit(*str); + str++; + } + + if (endptr) *endptr = str; + + return val; +} + +inline isize _strtoi(const char* str, const char** endptr, int base) +{ + isize val = 0; + bool negative = false; + + auto valid_digit = [](int _base, char c) -> bool { + if (_base <= 10) + { + if (!_isdigit(c)) return false; + if ((c - '0') < _base) return true; + } + else + { + if (!_isalnum(c)) return false; + if (_isdigit(c)) return true; + bool lower = _islower(c); + if (((c - lower ? 'a' : 'A') + 10) < _base) return true; + return false; + } + }; + + auto to_digit = [](char c) -> isize { + if (_isdigit(c)) return c - '0'; + if (_islower(c)) return (c - 'a') + 10; + return (c - 'A') + 10; + }; + + while (_isspace(*str)) str++; + + if (*str == '-' || *str == '+') + { + if (*str == '-') negative = true; + str++; + } + + if ((base == 0 || base == 16) && *str == '0') + { + str++; + if (_tolower(*str) == 'x') + { + base = 16; + str++; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + while (valid_digit(base, *str)) + { + val = (base * val) + to_digit(*str); + str++; + } + + if (endptr) *endptr = str; + + return negative ? -val : val; +} From dadc3e570b81c129316d664a30af6a5ec72b9b77 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 15:43:09 +0100 Subject: [PATCH 038/407] Move a few functions out of line --- CMakeLists.txt | 1 + kernel/CMakeLists.txt | 3 +- luna/CMakeLists.txt | 35 +++ luna/Format.cpp | 480 ++++++++++++++++++++++++++++++++++++++++ luna/Format.h | 487 +---------------------------------------- luna/NumberParsing.cpp | 153 +++++++++++++ luna/NumberParsing.h | 153 +------------ luna/String.cpp | 47 ++++ luna/String.h | 75 +------ 9 files changed, 728 insertions(+), 706 deletions(-) create mode 100644 luna/CMakeLists.txt create mode 100644 luna/Format.cpp create mode 100644 luna/NumberParsing.cpp create mode 100644 luna/String.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 576771e5..b14ad4b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,4 +16,5 @@ set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) +add_subdirectory(luna) add_subdirectory(kernel) \ No newline at end of file diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index fbe0b719..c9eddc8e 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -26,7 +26,7 @@ add_library(moon-asm STATIC ${ASM_SOURCES}) add_executable(moon ${SOURCES}) -target_link_libraries(moon moon-asm) +target_link_libraries(moon moon-asm luna-freestanding) target_compile_definitions(moon PRIVATE IN_MOON) @@ -51,7 +51,6 @@ target_link_options(moon PRIVATE -mno-red-zone) set_target_properties(moon PROPERTIES CXX_STANDARD 20) -target_include_directories(moon PUBLIC ${LUNA_ROOT}/luna) target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) target_link_options(moon PRIVATE LINKER:-T ${CMAKE_CURRENT_LIST_DIR}/moon.ld -nostdlib -nodefaultlibs) diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt new file mode 100644 index 00000000..bfb5d3f7 --- /dev/null +++ b/luna/CMakeLists.txt @@ -0,0 +1,35 @@ +set(FREESTANDING_SOURCES + Format.cpp + NumberParsing.cpp + String.cpp +) + +set(SOURCES + ${FREESTANDING_SOURCES} +) + +add_library(luna-freestanding ${FREESTANDING_SOURCES}) +target_compile_definitions(luna-freestanding PRIVATE USE_FREESTANDING) +target_compile_options(luna-freestanding PRIVATE -Wall -Wextra -Werror -Wvla) +target_compile_options(luna-freestanding PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) +target_compile_options(luna-freestanding PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) +target_compile_options(luna-freestanding PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) +target_compile_options(luna-freestanding PRIVATE -fno-rtti -ffreestanding -fno-exceptions) +target_compile_options(luna-freestanding PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) +target_compile_options(luna-freestanding PRIVATE -nostdlib -mcmodel=kernel) + +# x86-64 specific +target_compile_options(luna-freestanding PRIVATE -mno-red-zone) +target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) + +target_include_directories(luna-freestanding PUBLIC ${LUNA_ROOT}/luna) +set_target_properties(luna-freestanding PROPERTIES CXX_STANDARD 20) + +add_library(luna ${SOURCES}) +target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) +target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) +target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) +target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) +target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) +target_include_directories(luna PUBLIC ${LUNA_ROOT}/luna) +set_target_properties(luna PROPERTIES CXX_STANDARD 20) \ No newline at end of file diff --git a/luna/Format.cpp b/luna/Format.cpp new file mode 100644 index 00000000..c16ff222 --- /dev/null +++ b/luna/Format.cpp @@ -0,0 +1,480 @@ +#include +#include + +extern "C" usize strlen(const char*); + +typedef int flags_t; +#define FLAG_ZERO_PAD 1 << 0 +#define FLAG_LEFT_ALIGN 1 << 1 +#define FLAG_BLANK_SIGNED 1 << 2 +#define FLAG_ALTERNATE 1 << 3 +#define FLAG_SIGN 1 << 4 +#define FLAG_USE_PRECISION 1 << 5 +#define FLAG_LONG 1 << 6 +#define FLAG_LONG_LONG 1 << 7 +#define FLAG_SHORT 1 << 8 +#define FLAG_CHAR 1 << 9 + +struct format_state +{ + usize count; + callback_t callback; + void* arg; +}; + +struct conv_state +{ + flags_t flags; + usize width; + usize precision; +}; + +static inline int cstyle_format_putchar(char c, format_state& state) +{ + state.count++; + return state.callback(c, state.arg); +} + +static inline int cstyle_format_puts(const char* s, format_state& state) +{ + while (*s) + { + if (cstyle_format_putchar(*s, state)) return -1; + s++; + } + + return 0; +} + +#define TRY_PUTCHAR(c, state) \ + if (cstyle_format_putchar(c, state)) return -1; + +#define TRY_PUTS(s, state) \ + if (cstyle_format_puts(s, state)) return -1; + +static int start_pad(const conv_state& vstate, format_state& state, usize start) +{ + if (!(vstate.flags & FLAG_LEFT_ALIGN)) + { + while (start++ < vstate.width) TRY_PUTCHAR(' ', state); + } + + return 0; +} + +#define TRY_START_PAD(vstate, state, start) \ + if (start_pad(vstate, state, start)) return -1; + +static int end_pad(const conv_state& vstate, format_state& state, usize start) +{ + if (vstate.flags & FLAG_LEFT_ALIGN) + { + while (start++ < vstate.width) TRY_PUTCHAR(' ', state); + } + + return 0; +} + +#define TRY_END_PAD(vstate, state, start) \ + if (end_pad(vstate, state, start)) return -1; + +static flags_t parse_flags(const char** format) +{ + flags_t result = 0; + + while (true) + { + switch (**format) + { + case '#': + result |= FLAG_ALTERNATE; + (*format)++; + break; + case '0': + result |= FLAG_ZERO_PAD; + (*format)++; + break; + case ' ': + result |= FLAG_BLANK_SIGNED; + (*format)++; + break; + case '-': + result |= FLAG_LEFT_ALIGN; + (*format)++; + break; + case '+': + result |= FLAG_SIGN; + (*format)++; + break; + default: return result; + } + } +} + +static usize parse_width(const char** format, flags_t& flags, va_list ap) +{ + usize result = 0; + + if (_isdigit(**format)) result = _atou(format); + else if (**format == '*') + { + const int width = va_arg(ap, int); + if (width >= 0) result = (usize)width; + else + { + flags |= FLAG_LEFT_ALIGN; + result = (usize)-width; + } + } + + return result; +} + +static usize parse_precision(const char** format, flags_t& flags, va_list ap) +{ + usize result = 0; + + if (**format == '.') + { + (*format)++; + + flags |= FLAG_USE_PRECISION; + + if (_isdigit(**format)) result = _atou(format); + else if (**format == '*') + { + const int precision = va_arg(ap, int); + if (precision >= 0) result = (usize)precision; + else + result = 0; + } + } + + return result; +} + +static void parse_length(const char** format, flags_t& flags) +{ + // FIXME: Support %j (intmax_t/uintmax_t) + switch (**format) + { + case 'h': + flags |= FLAG_SHORT; + (*format)++; + if (**format == 'h') + { + flags |= FLAG_CHAR; + (*format)++; + } + break; + case 'l': + flags |= FLAG_LONG; + (*format)++; + if (**format == 'l') + { + flags |= FLAG_LONG_LONG; + (*format)++; + } + break; + case 't': + flags |= (sizeof(ptrdiff_t) == sizeof(long)) ? FLAG_LONG : FLAG_LONG_LONG; + (*format)++; + break; + case 'z': + flags |= (sizeof(size_t) == sizeof(long)) ? FLAG_LONG : FLAG_LONG_LONG; + (*format)++; + break; + default: break; + } +} + +static bool is_integer_format_specifier(char c) +{ + return (c == 'd') || (c == 'i') || (c == 'u') || (c == 'x') || (c == 'X') || (c == 'o') || (c == 'b'); +} + +static usize to_string(usize value, usize base, char* buf, usize max, bool uppercase) +{ + usize i = 0; + if (!value && max) + { + buf[i] = '0'; + return 1; + } + do { + int digit = (int)(value % base); + char c = (char)(digit < 10 ? '0' + digit : ((uppercase ? 'A' : 'a') + (digit - 10))); + buf[i++] = c; + value /= base; + } while (value && i < max); + return i; +} + +static int output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) +{ + usize base = 10; + bool uppercase = false; + + switch (specifier) + { + case 'p': + case 'x': + case 'X': base = 16; break; + case 'o': base = 8; break; + case 'b': base = 2; break; + default: break; + } + if (specifier == 'X') uppercase = true; + + if (base == 10) vstate.flags &= ~FLAG_ALTERNATE; // decimal doesn't have an alternate form + + char buf[1024]; + usize buflen = to_string(value, base, buf, sizeof(buf), uppercase); + + if (!(vstate.flags & FLAG_LEFT_ALIGN) && + (vstate.flags & FLAG_ZERO_PAD)) // we're padding with zeroes from the beginning + { + bool extra_char = + negative || ((vstate.flags & FLAG_SIGN) || + (vstate.flags & FLAG_BLANK_SIGNED)); // are we adding an extra character after the buffer? + if (vstate.width && extra_char) vstate.width--; + + if (vstate.width && (vstate.flags & FLAG_ALTERNATE)) // fit in the characters we're using for the alternate form + { + vstate.width--; + if (vstate.width && (base == 2 || base == 16)) vstate.width--; + } + + while (buflen < vstate.width && buflen < sizeof(buf)) buf[buflen++] = '0'; + } + + while (buflen < vstate.precision && buflen < sizeof(buf)) buf[buflen++] = '0'; + + if (vstate.flags & FLAG_ALTERNATE) + { + if (base == 16 && !uppercase && buflen < sizeof(buf)) buf[buflen++] = 'x'; + if (base == 16 && uppercase && buflen < sizeof(buf)) buf[buflen++] = 'X'; + if (base == 2 && buflen < sizeof(buf)) buf[buflen++] = 'b'; + if (buflen < sizeof(buf)) buf[buflen++] = '0'; + } + + if (buflen < sizeof(buf)) + { + if (negative) buf[buflen++] = '-'; + else if (vstate.flags & FLAG_SIGN) + buf[buflen++] = '+'; + else if (vstate.flags & FLAG_BLANK_SIGNED) + buf[buflen++] = ' '; + } + + if (!(vstate.flags & FLAG_ZERO_PAD)) TRY_START_PAD(vstate, state, buflen); + + usize i = buflen; + + while (i--) TRY_PUTCHAR(buf[i], state); + + TRY_END_PAD(vstate, state, buflen); + + return 0; +} + +static int va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) +{ + bool is_signed = false; + bool negative = false; + + if (specifier == 'd' || specifier == 'i') is_signed = true; + + if (!is_signed) vstate.flags &= ~(FLAG_SIGN | FLAG_BLANK_SIGNED); + + if (vstate.flags & FLAG_CHAR) + { + if (is_signed) + { + char v = (char)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned char v = (unsigned char)va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_SHORT) + { + if (is_signed) + { + short v = (short)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned short v = (unsigned short)va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_LONG_LONG) + { + if (is_signed) + { + long long v = va_arg(ap, long long); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned long long v = va_arg(ap, unsigned long long); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_LONG) + { + if (is_signed) + { + long v = va_arg(ap, long); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned long v = va_arg(ap, unsigned long); + return output_integer(specifier, vstate, state, v, false); + } + } + else + { + if (is_signed) + { + int v = va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned int v = va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } +} + +isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap) +{ + format_state state; + state.callback = callback; + state.arg = arg; + state.count = 0; + + while (*format) + { + if (*format != '%') + { + TRY_PUTCHAR(*format, state); + format++; + continue; + } + + format++; + + if (*format == '%') + { + TRY_PUTCHAR('%', state); + continue; + } + + // %[flags][width][.precision][length]conversion + + flags_t flags = parse_flags(&format); + usize width = parse_width(&format, flags, ap); + usize precision = parse_precision(&format, flags, ap); + parse_length(&format, flags); + + conv_state vstate = {flags, width, precision}; + + char specifier = *format; + format++; + + if (is_integer_format_specifier(specifier)) + { + if (va_output_integer(specifier, vstate, state, ap)) return -1; + continue; + } + else if (specifier == 'p') + { + void* ptr = va_arg(ap, void*); + if (ptr == nullptr) + { + TRY_START_PAD(vstate, state, 5); + TRY_PUTS("(nil)", state); + TRY_END_PAD(vstate, state, 5); + continue; + } + vstate.width = (sizeof(void*) * 2) + 2; + vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE); + if (output_integer('p', vstate, state, (usize)ptr, false)) return -1; + continue; + } + else if (specifier == 'c') + { + const char c = (char)va_arg(ap, int); + + TRY_START_PAD(vstate, state, 1); + TRY_PUTCHAR(c, state); + TRY_END_PAD(vstate, state, 1); + + continue; + } + else if (specifier == 's') + { + const char* str = va_arg(ap, const char*); + if (str == nullptr) + { + TRY_START_PAD(vstate, state, 6); + TRY_PUTS("(null)", state); + TRY_END_PAD(vstate, state, 6); + continue; + } + else + { + usize len = strlen(str); + + bool use_precision = (flags & FLAG_USE_PRECISION); + if (use_precision && len > precision) len = precision; + + TRY_START_PAD(vstate, state, len); + while (*str && (!use_precision || precision)) + { + TRY_PUTCHAR(*str, state); + precision--; + str++; + } + TRY_END_PAD(vstate, state, len); + continue; + } + } + else { continue; } + } + + return (isize)state.count; +} \ No newline at end of file diff --git a/luna/Format.h b/luna/Format.h index 10f43c30..71ad0659 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -5,489 +5,4 @@ typedef int (*callback_t)(char, void*); -#ifdef _LUNA_IMPLEMENTATION -#include - -extern "C" usize strlen(const char*); - -typedef int flags_t; -#define FLAG_ZERO_PAD 1 << 0 -#define FLAG_LEFT_ALIGN 1 << 1 -#define FLAG_BLANK_SIGNED 1 << 2 -#define FLAG_ALTERNATE 1 << 3 -#define FLAG_SIGN 1 << 4 -#define FLAG_USE_PRECISION 1 << 5 -#define FLAG_LONG 1 << 6 -#define FLAG_LONG_LONG 1 << 7 -#define FLAG_SHORT 1 << 8 -#define FLAG_CHAR 1 << 9 - -struct format_state -{ - usize count; - callback_t callback; - void* arg; -}; - -struct conv_state -{ - flags_t flags; - usize width; - usize precision; -}; - -static inline int cstyle_format_putchar(char c, format_state& state) -{ - state.count++; - return state.callback(c, state.arg); -} - -static inline int cstyle_format_puts(const char* s, format_state& state) -{ - while (*s) - { - if (cstyle_format_putchar(*s, state)) return -1; - s++; - } - - return 0; -} - -#define TRY_PUTCHAR(c, state) \ - if (cstyle_format_putchar(c, state)) return -1; - -#define TRY_PUTS(s, state) \ - if (cstyle_format_puts(s, state)) return -1; - -static int start_pad(const conv_state& vstate, format_state& state, usize start) -{ - if (!(vstate.flags & FLAG_LEFT_ALIGN)) - { - while (start++ < vstate.width) TRY_PUTCHAR(' ', state); - } - - return 0; -} - -#define TRY_START_PAD(vstate, state, start) \ - if (start_pad(vstate, state, start)) return -1; - -static int end_pad(const conv_state& vstate, format_state& state, usize start) -{ - if (vstate.flags & FLAG_LEFT_ALIGN) - { - while (start++ < vstate.width) TRY_PUTCHAR(' ', state); - } - - return 0; -} - -#define TRY_END_PAD(vstate, state, start) \ - if (end_pad(vstate, state, start)) return -1; - -static flags_t parse_flags(const char** format) -{ - flags_t result = 0; - - while (true) - { - switch (**format) - { - case '#': - result |= FLAG_ALTERNATE; - (*format)++; - break; - case '0': - result |= FLAG_ZERO_PAD; - (*format)++; - break; - case ' ': - result |= FLAG_BLANK_SIGNED; - (*format)++; - break; - case '-': - result |= FLAG_LEFT_ALIGN; - (*format)++; - break; - case '+': - result |= FLAG_SIGN; - (*format)++; - break; - default: return result; - } - } -} - -static usize parse_width(const char** format, flags_t& flags, va_list ap) -{ - usize result = 0; - - if (_isdigit(**format)) result = _atou(format); - else if (**format == '*') - { - const int width = va_arg(ap, int); - if (width >= 0) result = (usize)width; - else - { - flags |= FLAG_LEFT_ALIGN; - result = (usize)-width; - } - } - - return result; -} - -static usize parse_precision(const char** format, flags_t& flags, va_list ap) -{ - usize result = 0; - - if (**format == '.') - { - (*format)++; - - flags |= FLAG_USE_PRECISION; - - if (_isdigit(**format)) result = _atou(format); - else if (**format == '*') - { - const int precision = va_arg(ap, int); - if (precision >= 0) result = (usize)precision; - else - result = 0; - } - } - - return result; -} - -static void parse_length(const char** format, flags_t& flags) -{ - // FIXME: Support %j (intmax_t/uintmax_t) - switch (**format) - { - case 'h': - flags |= FLAG_SHORT; - (*format)++; - if (**format == 'h') - { - flags |= FLAG_CHAR; - (*format)++; - } - break; - case 'l': - flags |= FLAG_LONG; - (*format)++; - if (**format == 'l') - { - flags |= FLAG_LONG_LONG; - (*format)++; - } - break; - case 't': - flags |= (sizeof(ptrdiff_t) == sizeof(long)) ? FLAG_LONG : FLAG_LONG_LONG; - (*format)++; - break; - case 'z': - flags |= (sizeof(size_t) == sizeof(long)) ? FLAG_LONG : FLAG_LONG_LONG; - (*format)++; - break; - default: break; - } -} - -static bool is_integer_format_specifier(char c) -{ - return (c == 'd') || (c == 'i') || (c == 'u') || (c == 'x') || (c == 'X') || (c == 'o') || (c == 'b'); -} - -static usize to_string(usize value, usize base, char* buf, usize max, bool uppercase) -{ - usize i = 0; - if (!value && max) - { - buf[i] = '0'; - return 1; - } - do { - int digit = (int)(value % base); - char c = (char)(digit < 10 ? '0' + digit : ((uppercase ? 'A' : 'a') + (digit - 10))); - buf[i++] = c; - value /= base; - } while (value && i < max); - return i; -} - -static int output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) -{ - usize base = 10; - bool uppercase = false; - - switch (specifier) - { - case 'p': - case 'x': - case 'X': base = 16; break; - case 'o': base = 8; break; - case 'b': base = 2; break; - default: break; - } - if (specifier == 'X') uppercase = true; - - if (base == 10) vstate.flags &= ~FLAG_ALTERNATE; // decimal doesn't have an alternate form - - char buf[1024]; - usize buflen = to_string(value, base, buf, sizeof(buf), uppercase); - - if (!(vstate.flags & FLAG_LEFT_ALIGN) && - (vstate.flags & FLAG_ZERO_PAD)) // we're padding with zeroes from the beginning - { - bool extra_char = - negative || ((vstate.flags & FLAG_SIGN) || - (vstate.flags & FLAG_BLANK_SIGNED)); // are we adding an extra character after the buffer? - if (vstate.width && extra_char) vstate.width--; - - if (vstate.width && (vstate.flags & FLAG_ALTERNATE)) // fit in the characters we're using for the alternate form - { - vstate.width--; - if (vstate.width && (base == 2 || base == 16)) vstate.width--; - } - - while (buflen < vstate.width && buflen < sizeof(buf)) buf[buflen++] = '0'; - } - - while (buflen < vstate.precision && buflen < sizeof(buf)) buf[buflen++] = '0'; - - if (vstate.flags & FLAG_ALTERNATE) - { - if (base == 16 && !uppercase && buflen < sizeof(buf)) buf[buflen++] = 'x'; - if (base == 16 && uppercase && buflen < sizeof(buf)) buf[buflen++] = 'X'; - if (base == 2 && buflen < sizeof(buf)) buf[buflen++] = 'b'; - if (buflen < sizeof(buf)) buf[buflen++] = '0'; - } - - if (buflen < sizeof(buf)) - { - if (negative) buf[buflen++] = '-'; - else if (vstate.flags & FLAG_SIGN) - buf[buflen++] = '+'; - else if (vstate.flags & FLAG_BLANK_SIGNED) - buf[buflen++] = ' '; - } - - if (!(vstate.flags & FLAG_ZERO_PAD)) TRY_START_PAD(vstate, state, buflen); - - usize i = buflen; - - while (i--) TRY_PUTCHAR(buf[i], state); - - TRY_END_PAD(vstate, state, buflen); - - return 0; -} - -static int va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) -{ - bool is_signed = false; - bool negative = false; - - if (specifier == 'd' || specifier == 'i') is_signed = true; - - if (!is_signed) vstate.flags &= ~(FLAG_SIGN | FLAG_BLANK_SIGNED); - - if (vstate.flags & FLAG_CHAR) - { - if (is_signed) - { - char v = (char)va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - return output_integer(specifier, vstate, state, v, negative); - } - else - { - unsigned char v = (unsigned char)va_arg(ap, unsigned int); - return output_integer(specifier, vstate, state, v, false); - } - } - else if (vstate.flags & FLAG_SHORT) - { - if (is_signed) - { - short v = (short)va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - return output_integer(specifier, vstate, state, v, negative); - } - else - { - unsigned short v = (unsigned short)va_arg(ap, unsigned int); - return output_integer(specifier, vstate, state, v, false); - } - } - else if (vstate.flags & FLAG_LONG_LONG) - { - if (is_signed) - { - long long v = va_arg(ap, long long); - if (v < 0) - { - v = -v; - negative = true; - } - return output_integer(specifier, vstate, state, v, negative); - } - else - { - unsigned long long v = va_arg(ap, unsigned long long); - return output_integer(specifier, vstate, state, v, false); - } - } - else if (vstate.flags & FLAG_LONG) - { - if (is_signed) - { - long v = va_arg(ap, long); - if (v < 0) - { - v = -v; - negative = true; - } - return output_integer(specifier, vstate, state, v, negative); - } - else - { - unsigned long v = va_arg(ap, unsigned long); - return output_integer(specifier, vstate, state, v, false); - } - } - else - { - if (is_signed) - { - int v = va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - return output_integer(specifier, vstate, state, v, negative); - } - else - { - unsigned int v = va_arg(ap, unsigned int); - return output_integer(specifier, vstate, state, v, false); - } - } -} - -#endif - -isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap) -#ifdef _LUNA_IMPLEMENTATION -{ - format_state state; - state.callback = callback; - state.arg = arg; - state.count = 0; - - while (*format) - { - if (*format != '%') - { - TRY_PUTCHAR(*format, state); - format++; - continue; - } - - format++; - - if (*format == '%') - { - TRY_PUTCHAR('%', state); - continue; - } - - // %[flags][width][.precision][length]conversion - - flags_t flags = parse_flags(&format); - usize width = parse_width(&format, flags, ap); - usize precision = parse_precision(&format, flags, ap); - parse_length(&format, flags); - - conv_state vstate = {flags, width, precision}; - - char specifier = *format; - format++; - - if (is_integer_format_specifier(specifier)) - { - if (va_output_integer(specifier, vstate, state, ap)) return -1; - continue; - } - else if (specifier == 'p') - { - void* ptr = va_arg(ap, void*); - if (ptr == nullptr) - { - TRY_START_PAD(vstate, state, 5); - TRY_PUTS("(nil)", state); - TRY_END_PAD(vstate, state, 5); - continue; - } - vstate.width = (sizeof(void*) * 2) + 2; - vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE); - if (output_integer('p', vstate, state, (usize)ptr, false)) return -1; - continue; - } - else if (specifier == 'c') - { - const char c = (char)va_arg(ap, int); - - TRY_START_PAD(vstate, state, 1); - TRY_PUTCHAR(c, state); - TRY_END_PAD(vstate, state, 1); - - continue; - } - else if (specifier == 's') - { - const char* str = va_arg(ap, const char*); - if (str == nullptr) - { - TRY_START_PAD(vstate, state, 6); - TRY_PUTS("(null)", state); - TRY_END_PAD(vstate, state, 6); - continue; - } - else - { - usize len = strlen(str); - - bool use_precision = (flags & FLAG_USE_PRECISION); - if (use_precision && len > precision) len = precision; - - TRY_START_PAD(vstate, state, len); - while (*str && (!use_precision || precision)) - { - TRY_PUTCHAR(*str, state); - precision--; - str++; - } - TRY_END_PAD(vstate, state, len); - continue; - } - } - else { continue; } - } - - return (isize)state.count; -} -#else - ; -#endif \ No newline at end of file +isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); \ No newline at end of file diff --git a/luna/NumberParsing.cpp b/luna/NumberParsing.cpp new file mode 100644 index 00000000..4387407e --- /dev/null +++ b/luna/NumberParsing.cpp @@ -0,0 +1,153 @@ +#include + +usize _atou(const char** str) +{ + usize val = 0; + + while (_isdigit(**str)) + { + val = (10 * val) + (**str - '0'); + (*str)++; + } + + return val; +} + +isize _atos(const char** str) +{ + bool neg = false; + isize val = 0; + + switch (**str) + { + case '-': + neg = true; + (*str)++; + break; + case '+': (*str)++; break; + default: break; + } + + while (_isdigit(**str)) + { + val = (10 * val) + (**str - '0'); + (*str)++; + } + + return neg ? -val : val; +} + +usize _strtou(const char* str, const char** endptr, int base) +{ + usize val = 0; + + auto valid_digit = [](int _base, char c) -> bool { + if (_base <= 10) + { + if (!_isdigit(c)) return false; + if ((c - '0') < _base) return true; + return false; + } + else + { + if (!_isalnum(c)) return false; + if (_isdigit(c)) return true; + bool lower = _islower(c); + if (((c - lower ? 'a' : 'A') + 10) < _base) return true; + return false; + } + }; + + auto to_digit = [](char c) -> usize { + if (_isdigit(c)) return c - '0'; + if (_islower(c)) return (c - 'a') + 10; + return (c - 'A') + 10; + }; + + while (_isspace(*str)) str++; + + if ((base == 0 || base == 16) && *str == '0') + { + str++; + if (_tolower(*str) == 'x') + { + base = 16; + str++; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + while (valid_digit(base, *str)) + { + val = (base * val) + to_digit(*str); + str++; + } + + if (endptr) *endptr = str; + + return val; +} + +isize _strtoi(const char* str, const char** endptr, int base) +{ + isize val = 0; + bool negative = false; + + auto valid_digit = [](int _base, char c) -> bool { + if (_base <= 10) + { + if (!_isdigit(c)) return false; + if ((c - '0') < _base) return true; + return false; + } + else + { + if (!_isalnum(c)) return false; + if (_isdigit(c)) return true; + bool lower = _islower(c); + if (((c - lower ? 'a' : 'A') + 10) < _base) return true; + return false; + } + }; + + auto to_digit = [](char c) -> isize { + if (_isdigit(c)) return c - '0'; + if (_islower(c)) return (c - 'a') + 10; + return (c - 'A') + 10; + }; + + while (_isspace(*str)) str++; + + if (*str == '-' || *str == '+') + { + if (*str == '-') negative = true; + str++; + } + + if ((base == 0 || base == 16) && *str == '0') + { + str++; + if (_tolower(*str) == 'x') + { + base = 16; + str++; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + while (valid_digit(base, *str)) + { + val = (base * val) + to_digit(*str); + str++; + } + + if (endptr) *endptr = str; + + return negative ? -val : val; +} diff --git a/luna/NumberParsing.h b/luna/NumberParsing.h index a0fca6f2..c3c83fce 100644 --- a/luna/NumberParsing.h +++ b/luna/NumberParsing.h @@ -2,152 +2,7 @@ #include #include -inline usize _atou(const char** str) -{ - usize val = 0; - - while (_isdigit(**str)) - { - val = (10 * val) + (**str - '0'); - (*str)++; - } - - return val; -} - -inline isize _atos(const char** str) -{ - bool neg = false; - isize val = 0; - - switch (**str) - { - case '-': - neg = true; - (*str)++; - break; - case '+': (*str)++; break; - default: break; - } - - while (_isdigit(**str)) - { - val = (10 * val) + (**str - '0'); - (*str)++; - } - - return neg ? -val : val; -} - -inline usize _strtou(const char* str, const char** endptr, int base) -{ - usize val = 0; - - auto valid_digit = [](int _base, char c) -> bool { - if (_base <= 10) - { - if (!_isdigit(c)) return false; - if ((c - '0') < _base) return true; - } - else - { - if (!_isalnum(c)) return false; - if (_isdigit(c)) return true; - bool lower = _islower(c); - if (((c - lower ? 'a' : 'A') + 10) < _base) return true; - return false; - } - }; - - auto to_digit = [](char c) -> usize { - if (_isdigit(c)) return c - '0'; - if (_islower(c)) return (c - 'a') + 10; - return (c - 'A') + 10; - }; - - while (_isspace(*str)) str++; - - if ((base == 0 || base == 16) && *str == '0') - { - str++; - if (_tolower(*str) == 'x') - { - base = 16; - str++; - } - else if (base == 0) - base = 8; - } - else if (base == 0) - base = 10; - - while (valid_digit(base, *str)) - { - val = (base * val) + to_digit(*str); - str++; - } - - if (endptr) *endptr = str; - - return val; -} - -inline isize _strtoi(const char* str, const char** endptr, int base) -{ - isize val = 0; - bool negative = false; - - auto valid_digit = [](int _base, char c) -> bool { - if (_base <= 10) - { - if (!_isdigit(c)) return false; - if ((c - '0') < _base) return true; - } - else - { - if (!_isalnum(c)) return false; - if (_isdigit(c)) return true; - bool lower = _islower(c); - if (((c - lower ? 'a' : 'A') + 10) < _base) return true; - return false; - } - }; - - auto to_digit = [](char c) -> isize { - if (_isdigit(c)) return c - '0'; - if (_islower(c)) return (c - 'a') + 10; - return (c - 'A') + 10; - }; - - while (_isspace(*str)) str++; - - if (*str == '-' || *str == '+') - { - if (*str == '-') negative = true; - str++; - } - - if ((base == 0 || base == 16) && *str == '0') - { - str++; - if (_tolower(*str) == 'x') - { - base = 16; - str++; - } - else if (base == 0) - base = 8; - } - else if (base == 0) - base = 10; - - while (valid_digit(base, *str)) - { - val = (base * val) + to_digit(*str); - str++; - } - - if (endptr) *endptr = str; - - return negative ? -val : val; -} +usize _atou(const char** str); +isize _atos(const char** str); +usize _strtou(const char* str, const char** endptr, int base); +isize _strtoi(const char* str, const char** endptr, int base); diff --git a/luna/String.cpp b/luna/String.cpp new file mode 100644 index 00000000..2b2113b4 --- /dev/null +++ b/luna/String.cpp @@ -0,0 +1,47 @@ +#include + +extern "C" +{ + void* memcpy(void* dest, const void* src, size_t n) + { + for (size_t i = 0; i < n; ++i) { *((u8*)dest + i) = *((const u8*)src + i); } + return dest; + } + + void* memset(void* buf, int c, size_t n) + { + for (size_t i = 0; i < n; ++i) { *((u8*)buf + i) = (u8)c; } + return buf; + } + + int memcmp(const void* a, const void* b, size_t n) + { + if (!n) return 0; + const u8* ap = (const u8*)a; + const u8* bp = (const u8*)b; + while (--n && *ap == *bp) + { + ap++; + bp++; + } + return *ap - *bp; + } + + void* memmove(void* dest, const void* src, size_t n) + { + if (dest == src) return dest; + if (dest > src) + for (long i = n - 1; i >= 0; i++) { *((u8*)dest + i) = *((const u8*)src + i); } + else + for (long i = 0; i < (long)n; i++) { *((u8*)dest + i) = *((const u8*)src + i); } + return dest; + } + + size_t strlen(const char* str) + { + const char* i = str; + for (; *i; ++i) + ; + return (i - str); + } +} \ No newline at end of file diff --git a/luna/String.h b/luna/String.h index 9bfc8230..b11961f6 100644 --- a/luna/String.h +++ b/luna/String.h @@ -1,74 +1,11 @@ #pragma once #include -#ifndef NO_EXTERN_C extern "C" { -#endif - - void* memcpy(void* dest, const void* src, size_t n) -#ifdef _LUNA_IMPLEMENTATION - { - for (size_t i = 0; i < n; ++i) { *((u8*)dest + i) = *((const u8*)src + i); } - return dest; - } -#else - ; -#endif - - void* memset(void* buf, int c, size_t n) -#ifdef _LUNA_IMPLEMENTATION - { - for (size_t i = 0; i < n; ++i) { *((u8*)buf + i) = (u8)c; } - return buf; - } -#else - ; -#endif - - int memcmp(const void* a, const void* b, size_t n) -#ifdef _LUNA_IMPLEMENTATION - { - if (!n) return 0; - const u8* ap = (const u8*)a; - const u8* bp = (const u8*)b; - while (--n && *ap == *bp) - { - ap++; - bp++; - } - return *ap - *bp; - } -#else - ; -#endif - - void* memmove(void* dest, const void* src, size_t n) -#ifdef _LUNA_IMPLEMENTATION - { - if (dest == src) return dest; - if (dest > src) - for (long i = n - 1; i >= 0; i++) { *((u8*)dest + i) = *((const u8*)src + i); } - else - for (long i = 0; i < (long)n; i++) { *((u8*)dest + i) = *((const u8*)src + i); } - return dest; - } -#else - ; -#endif - - size_t strlen(const char* str) -#ifdef _LUNA_IMPLEMENTATION - { - const char* i = str; - for (; *i; ++i) - ; - return (i - str); - } -#else - ; -#endif - -#ifndef NO_EXTERN_C -} -#endif \ No newline at end of file + void* memcpy(void* dest, const void* src, size_t n); + void* memset(void* buf, int c, size_t n); + int memcmp(const void* a, const void* b, size_t n); + void* memmove(void* dest, const void* src, size_t n); + size_t strlen(const char* str); +} \ No newline at end of file From 3cdf224b90fb2951d59b19ede1108a91aaf1c7c2 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 15:46:46 +0100 Subject: [PATCH 039/407] Remove useless files now that functions are out of line --- kernel/CMakeLists.txt | 2 -- kernel/src/luna/Format.cpp | 3 --- kernel/src/luna/String.cpp | 3 --- 3 files changed, 8 deletions(-) delete mode 100644 kernel/src/luna/Format.cpp delete mode 100644 kernel/src/luna/String.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index c9eddc8e..304f59a5 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,11 +1,9 @@ set(SOURCES src/main.cpp - src/luna/String.cpp src/Framebuffer.cpp src/MemoryManager.cpp src/Init.cpp src/arch/Serial.cpp - src/luna/Format.cpp ) # x86-64 specific diff --git a/kernel/src/luna/Format.cpp b/kernel/src/luna/Format.cpp deleted file mode 100644 index c1307639..00000000 --- a/kernel/src/luna/Format.cpp +++ /dev/null @@ -1,3 +0,0 @@ -/* This file instantiates the functions from Luna's Format.h into a translation unit, and serves no other purpose. */ -#define _LUNA_IMPLEMENTATION -#include \ No newline at end of file diff --git a/kernel/src/luna/String.cpp b/kernel/src/luna/String.cpp deleted file mode 100644 index 20590d5d..00000000 --- a/kernel/src/luna/String.cpp +++ /dev/null @@ -1,3 +0,0 @@ -/* This file instantiates the functions from Luna's String.h into a translation unit, and serves no other purpose. */ -#define _LUNA_IMPLEMENTATION -#include \ No newline at end of file From 31673c0ac9b8164860833cbf416f17c233d90457 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 15:53:58 +0100 Subject: [PATCH 040/407] Introduce format attribute --- kernel/src/arch/Serial.h | 3 ++- luna/Format.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h index 92a0725e..70553b25 100644 --- a/kernel/src/arch/Serial.h +++ b/kernel/src/arch/Serial.h @@ -1,4 +1,5 @@ #pragma once +#include #include namespace Serial @@ -7,5 +8,5 @@ namespace Serial void write(const char* str, usize size); void print(const char* str); void println(const char* str); - int printf(const char* str, ...); + int printf(const char* str, ...) _format(1, 2); } \ No newline at end of file diff --git a/luna/Format.h b/luna/Format.h index 71ad0659..e908f76c 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -3,6 +3,8 @@ #include #include +#define _format(n, m) __attribute__((format(printf, n, m))) + typedef int (*callback_t)(char, void*); isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); \ No newline at end of file From 648bd3fb619b94887bc3487c28e98c5c6bf8d349 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 16:13:25 +0100 Subject: [PATCH 041/407] Switch format.h to use Result --- kernel/src/arch/Serial.cpp | 10 ++--- kernel/src/arch/Serial.h | 6 ++- luna/Format.cpp | 80 ++++++++++++++++---------------------- luna/Format.h | 9 ++--- luna/FormatAttribute.h | 2 + 5 files changed, 49 insertions(+), 58 deletions(-) create mode 100644 luna/FormatAttribute.h diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index 07d9ce26..db860f2c 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -19,18 +19,18 @@ namespace Serial putchar('\n'); } - int printf(const char* format, ...) + Result printf(const char* format, ...) { va_list ap; va_start(ap, format); - isize rc = cstyle_format( + auto rc = cstyle_format( format, - [](char c, void*) -> int { + [](char c, void*) -> Result { putchar(c); - return 0; + return {}; }, nullptr, ap); va_end(ap); - return (int)rc; + return rc; } } \ No newline at end of file diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h index 70553b25..61ca9000 100644 --- a/kernel/src/arch/Serial.h +++ b/kernel/src/arch/Serial.h @@ -1,12 +1,14 @@ #pragma once -#include +#include #include +template class Result; + namespace Serial { void putchar(u8 c); void write(const char* str, usize size); void print(const char* str); void println(const char* str); - int printf(const char* str, ...) _format(1, 2); + Result printf(const char* str, ...) _format(1, 2); } \ No newline at end of file diff --git a/luna/Format.cpp b/luna/Format.cpp index c16ff222..6a98be26 100644 --- a/luna/Format.cpp +++ b/luna/Format.cpp @@ -29,55 +29,43 @@ struct conv_state usize precision; }; -static inline int cstyle_format_putchar(char c, format_state& state) +static Result format_putchar(char c, format_state& state) { state.count++; return state.callback(c, state.arg); } -static inline int cstyle_format_puts(const char* s, format_state& state) +static Result format_puts(const char* s, format_state& state) { while (*s) { - if (cstyle_format_putchar(*s, state)) return -1; + TRY(format_putchar(*s, state)); s++; } - return 0; + return {}; } -#define TRY_PUTCHAR(c, state) \ - if (cstyle_format_putchar(c, state)) return -1; - -#define TRY_PUTS(s, state) \ - if (cstyle_format_puts(s, state)) return -1; - -static int start_pad(const conv_state& vstate, format_state& state, usize start) +static Result start_pad(const conv_state& vstate, format_state& state, usize start) { if (!(vstate.flags & FLAG_LEFT_ALIGN)) { - while (start++ < vstate.width) TRY_PUTCHAR(' ', state); + while (start++ < vstate.width) TRY(format_putchar(' ', state)); } - return 0; + return {}; } -#define TRY_START_PAD(vstate, state, start) \ - if (start_pad(vstate, state, start)) return -1; - -static int end_pad(const conv_state& vstate, format_state& state, usize start) +static Result end_pad(const conv_state& vstate, format_state& state, usize start) { if (vstate.flags & FLAG_LEFT_ALIGN) { - while (start++ < vstate.width) TRY_PUTCHAR(' ', state); + while (start++ < vstate.width) TRY(format_putchar(' ', state)); } - return 0; + return {}; } -#define TRY_END_PAD(vstate, state, start) \ - if (end_pad(vstate, state, start)) return -1; - static flags_t parse_flags(const char** format) { flags_t result = 0; @@ -210,7 +198,7 @@ static usize to_string(usize value, usize base, char* buf, usize max, bool upper return i; } -static int output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) +static Result output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) { usize base = 10; bool uppercase = false; @@ -267,18 +255,18 @@ static int output_integer(char specifier, conv_state& vstate, format_state& stat buf[buflen++] = ' '; } - if (!(vstate.flags & FLAG_ZERO_PAD)) TRY_START_PAD(vstate, state, buflen); + if (!(vstate.flags & FLAG_ZERO_PAD)) TRY(start_pad(vstate, state, buflen)); usize i = buflen; - while (i--) TRY_PUTCHAR(buf[i], state); + while (i--) TRY(format_putchar(buf[i], state)); - TRY_END_PAD(vstate, state, buflen); + TRY(end_pad(vstate, state, buflen)); - return 0; + return {}; } -static int va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) +static Result va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) { bool is_signed = false; bool negative = false; @@ -379,7 +367,7 @@ static int va_output_integer(char specifier, conv_state& vstate, format_state& s } } -isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap) +Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap) { format_state state; state.callback = callback; @@ -390,7 +378,7 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list { if (*format != '%') { - TRY_PUTCHAR(*format, state); + TRY(format_putchar(*format, state)); format++; continue; } @@ -399,7 +387,7 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list if (*format == '%') { - TRY_PUTCHAR('%', state); + TRY(format_putchar('%', state)); continue; } @@ -417,7 +405,7 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list if (is_integer_format_specifier(specifier)) { - if (va_output_integer(specifier, vstate, state, ap)) return -1; + TRY(va_output_integer(specifier, vstate, state, ap)); continue; } else if (specifier == 'p') @@ -425,23 +413,23 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list void* ptr = va_arg(ap, void*); if (ptr == nullptr) { - TRY_START_PAD(vstate, state, 5); - TRY_PUTS("(nil)", state); - TRY_END_PAD(vstate, state, 5); + TRY(start_pad(vstate, state, 5)); + TRY(format_puts("(nil)", state)); + TRY(end_pad(vstate, state, 5)); continue; } vstate.width = (sizeof(void*) * 2) + 2; vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE); - if (output_integer('p', vstate, state, (usize)ptr, false)) return -1; + TRY(output_integer('p', vstate, state, (usize)ptr, false)); continue; } else if (specifier == 'c') { const char c = (char)va_arg(ap, int); - TRY_START_PAD(vstate, state, 1); - TRY_PUTCHAR(c, state); - TRY_END_PAD(vstate, state, 1); + TRY(start_pad(vstate, state, 1)); + TRY(format_putchar(c, state)); + TRY(end_pad(vstate, state, 1)); continue; } @@ -450,9 +438,9 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list const char* str = va_arg(ap, const char*); if (str == nullptr) { - TRY_START_PAD(vstate, state, 6); - TRY_PUTS("(null)", state); - TRY_END_PAD(vstate, state, 6); + TRY(start_pad(vstate, state, 6)); + TRY(format_puts("(null)", state)); + TRY(end_pad(vstate, state, 6)); continue; } else @@ -462,19 +450,19 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list bool use_precision = (flags & FLAG_USE_PRECISION); if (use_precision && len > precision) len = precision; - TRY_START_PAD(vstate, state, len); + TRY(start_pad(vstate, state, len)); while (*str && (!use_precision || precision)) { - TRY_PUTCHAR(*str, state); + TRY(format_putchar(*str, state)); precision--; str++; } - TRY_END_PAD(vstate, state, len); + TRY(end_pad(vstate, state, len)); continue; } } else { continue; } } - return (isize)state.count; + return state.count; } \ No newline at end of file diff --git a/luna/Format.h b/luna/Format.h index e908f76c..cb63c290 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -1,10 +1,9 @@ #pragma once #include -#include +#include +#include #include -#define _format(n, m) __attribute__((format(printf, n, m))) +typedef Result (*callback_t)(char, void*); -typedef int (*callback_t)(char, void*); - -isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); \ No newline at end of file +Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); \ No newline at end of file diff --git a/luna/FormatAttribute.h b/luna/FormatAttribute.h new file mode 100644 index 00000000..abed32dc --- /dev/null +++ b/luna/FormatAttribute.h @@ -0,0 +1,2 @@ +#pragma once +#define _format(n, m) __attribute__((format(printf, n, m))) \ No newline at end of file From b8c136eeb4772498cbd6cdbe56a2d30b833c6b71 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 17:18:51 +0100 Subject: [PATCH 042/407] Make a common header for attribute shorthands --- kernel/src/arch/Serial.h | 2 +- luna/Attributes.h | 6 ++++++ luna/Format.h | 2 +- luna/FormatAttribute.h | 2 -- 4 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 luna/Attributes.h delete mode 100644 luna/FormatAttribute.h diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h index 61ca9000..097a7408 100644 --- a/kernel/src/arch/Serial.h +++ b/kernel/src/arch/Serial.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include template class Result; diff --git a/luna/Attributes.h b/luna/Attributes.h new file mode 100644 index 00000000..f137161d --- /dev/null +++ b/luna/Attributes.h @@ -0,0 +1,6 @@ +#pragma once + +#define _weak __attribute__((weak)) +#define _format(n, m) __attribute__((format(printf, n, m))) +#define _align(x) __attribute__((aligned(x))) +#define _noreturn __attribute__((noreturn)) \ No newline at end of file diff --git a/luna/Format.h b/luna/Format.h index cb63c290..fd9d95a5 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -1,6 +1,6 @@ #pragma once +#include #include -#include #include #include diff --git a/luna/FormatAttribute.h b/luna/FormatAttribute.h deleted file mode 100644 index abed32dc..00000000 --- a/luna/FormatAttribute.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -#define _format(n, m) __attribute__((format(printf, n, m))) \ No newline at end of file From 2b9bdf560e8c9665b7a12efa3966110d81d91a48 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 17:19:25 +0100 Subject: [PATCH 043/407] Move include to .cpp file --- luna/Format.cpp | 1 + luna/Format.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/luna/Format.cpp b/luna/Format.cpp index 6a98be26..02eb0ff6 100644 --- a/luna/Format.cpp +++ b/luna/Format.cpp @@ -1,3 +1,4 @@ +#include #include #include diff --git a/luna/Format.h b/luna/Format.h index fd9d95a5..1d06050e 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include From 8cae20a82cbaae46df5271571adc5d29c9bc1958 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 17:20:10 +0100 Subject: [PATCH 044/407] Move __check_failed out of line so anyone can implement it --- kernel/src/arch/Serial.cpp | 13 +++++++++++++ luna/CMakeLists.txt | 1 + luna/Check.cpp | 6 ++++++ luna/Check.h | 19 +++---------------- 4 files changed, 23 insertions(+), 16 deletions(-) create mode 100644 luna/Check.cpp diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index db860f2c..9a00a751 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -1,4 +1,5 @@ #include "arch/Serial.h" +#include "arch/CPU.h" #include namespace Serial @@ -33,4 +34,16 @@ namespace Serial va_end(ap); return rc; } +} + +static bool g_check_already_failed = false; + +_noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr) +{ + if (!g_check_already_failed) + { // Avoid endlessly failing when trying to report a failed check. + g_check_already_failed = true; + Serial::printf("ERROR: Check failed at %s:%s, in %s: %s\n", file, line, func, expr); + } + CPU::efficient_halt(); } \ No newline at end of file diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index bfb5d3f7..54f2f78d 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -6,6 +6,7 @@ set(FREESTANDING_SOURCES set(SOURCES ${FREESTANDING_SOURCES} + Check.cpp ) add_library(luna-freestanding ${FREESTANDING_SOURCES}) diff --git a/luna/Check.cpp b/luna/Check.cpp new file mode 100644 index 00000000..e464ca86 --- /dev/null +++ b/luna/Check.cpp @@ -0,0 +1,6 @@ +#include + +_weak _noreturn bool __check_failed(const char*, const char*, const char*, const char*) +{ + __builtin_trap(); +} \ No newline at end of file diff --git a/luna/Check.h b/luna/Check.h index f8c4fd13..1e24fb66 100644 --- a/luna/Check.h +++ b/luna/Check.h @@ -1,22 +1,9 @@ #pragma once -#ifdef IN_MOON -#include "arch/Serial.h" +#include -[[noreturn]] inline bool __check_failed(const char* string) -{ - Serial::print("CHECK FAILED: "); - Serial::println(string); - for (;;) - ; -} -#else -[[noreturn]] inline bool __check_failed(const char*) -{ - __builtin_trap(); -} -#endif +extern _noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr); #define STRINGIZE(x) #x #define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#define check(expr) (expr) || __check_failed("at " __FILE__ ":" STRINGIZE_VALUE_OF(__LINE__) ": " #expr) \ No newline at end of file +#define check(expr) (expr) || __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, #expr) From 83e6bd13223d48cc00a68b83548f56a4f048efac Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 17:46:53 +0100 Subject: [PATCH 045/407] Make the build system more platform-agnostic --- CMakeLists.txt | 4 +++ kernel/CMakeLists.txt | 21 ++++++++++---- luna/CMakeLists.txt | 3 +- tools/build-iso.sh | 11 +++----- tools/build.sh | 9 ++---- tools/clean.sh | 4 +-- tools/debug.sh | 2 +- tools/env.sh | 15 +++++++++- tools/fast-run.sh | 2 +- tools/install-built-ports.sh | 53 ------------------------------------ tools/install.sh | 2 +- tools/rebuild-iso.sh | 11 ++++---- tools/rebuild.sh | 9 +++--- tools/sync-libc.sh | 13 --------- 14 files changed, 59 insertions(+), 100 deletions(-) delete mode 100755 tools/install-built-ports.sh delete mode 100755 tools/sync-libc.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index b14ad4b8..23c53e13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,5 +16,9 @@ set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) +set(ARCH $ENV{ARCH}) + +message(STATUS "Configuring Luna for ${ARCH}") + add_subdirectory(luna) add_subdirectory(kernel) \ No newline at end of file diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 304f59a5..0db461df 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -6,7 +6,7 @@ set(SOURCES src/arch/Serial.cpp ) -# x86-64 specific +if("${ARCH}" MATCHES "x86_64") set(SOURCES ${SOURCES} src/arch/x86_64/IO.cpp @@ -14,17 +14,26 @@ set(SOURCES src/arch/x86_64/MMU.cpp src/arch/x86_64/CPU.cpp ) +endif() -# x86-64 specific +set(ASM_SOURCES) + +if("${ARCH}" MATCHES "x86_64") set(ASM_SOURCES + ${ASM_SOURCES} src/arch/x86_64/CPU.asm ) add_library(moon-asm STATIC ${ASM_SOURCES}) +endif() add_executable(moon ${SOURCES}) -target_link_libraries(moon moon-asm luna-freestanding) +if("${ARCH}" MATCHES "x86_64") +target_link_libraries(moon moon-asm) +endif() + +target_link_libraries(moon luna-freestanding) target_compile_definitions(moon PRIVATE IN_MOON) @@ -38,14 +47,16 @@ target_compile_options(moon PRIVATE -fno-rtti -ffreestanding -fno-exceptions) target_compile_options(moon PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel) -# x86-64 specific +if("${ARCH}" MATCHES "x86_64") target_compile_options(moon PRIVATE -mno-red-zone) target_compile_options(moon PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) +endif() target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mcmodel=kernel) -# x86-64 specific +if("${ARCH}" MATCHES "x86_64") target_link_options(moon PRIVATE -mno-red-zone) +endif() set_target_properties(moon PROPERTIES CXX_STANDARD 20) diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 54f2f78d..7481c08b 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -19,9 +19,10 @@ target_compile_options(luna-freestanding PRIVATE -fno-rtti -ffreestanding -fno-e target_compile_options(luna-freestanding PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) target_compile_options(luna-freestanding PRIVATE -nostdlib -mcmodel=kernel) -# x86-64 specific +if("${ARCH}" MATCHES "x86_64") target_compile_options(luna-freestanding PRIVATE -mno-red-zone) target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) +endif() target_include_directories(luna-freestanding PUBLIC ${LUNA_ROOT}/luna) set_target_properties(luna-freestanding PROPERTIES CXX_STANDARD 20) diff --git a/tools/build-iso.sh b/tools/build-iso.sh index ac9c3c6e..168b75ac 100755 --- a/tools/build-iso.sh +++ b/tools/build-iso.sh @@ -9,12 +9,9 @@ tools/setup.sh #tools/install-headers.sh -mkdir -p build -if [ "$USE_NINJA" = "1" ] -then -cmake -S . -B build -G Ninja -fi -cmake --build build -cmake --install build +mkdir -p $BUILD_DIR +cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" +cmake --build $BUILD_DIR +cmake --install $BUILD_DIR mkbootimg luna.json Luna.iso \ No newline at end of file diff --git a/tools/build.sh b/tools/build.sh index b5855836..ee07e209 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -9,9 +9,6 @@ tools/setup.sh #tools/install-headers.sh -mkdir -p build -if [ "$USE_NINJA" = "1" ] -then -cmake -S . -B build -G Ninja -fi -cmake --build build \ No newline at end of file +mkdir -p $BUILD_DIR +cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" +cmake --build $BUILD_DIR \ No newline at end of file diff --git a/tools/clean.sh b/tools/clean.sh index e005b12c..6d9139c6 100755 --- a/tools/clean.sh +++ b/tools/clean.sh @@ -3,6 +3,6 @@ set -e source $(dirname $0)/env.sh -cd $LUNA_ROOT +cd $BUILD_DIR -make clean \ No newline at end of file +$BUILD clean \ No newline at end of file diff --git a/tools/debug.sh b/tools/debug.sh index ad05afad..9623df96 100755 --- a/tools/debug.sh +++ b/tools/debug.sh @@ -3,4 +3,4 @@ set -e source $(dirname $0)/env.sh -qemu-system-x86_64 -cdrom Luna.iso -smp 1 -m 256M -serial stdio -d int,cpu_reset -s $@ \ No newline at end of file +qemu-system-$ARCH -cdrom Luna.iso -smp 1 -m 256M -serial stdio -d int,cpu_reset -s $@ \ No newline at end of file diff --git a/tools/env.sh b/tools/env.sh index 6d99f72b..7b21c968 100755 --- a/tools/env.sh +++ b/tools/env.sh @@ -3,4 +3,17 @@ export LUNA_ROOT=${LUNA_ROOT:-$(realpath $(dirname $0)/..)} export LUNA_BASE=${LUNA_BASE:-$LUNA_ROOT/base} export PATH=$LUNA_ROOT/toolchain/x86-64-luna/bin:$LUNA_ROOT/toolchain/dist:$PATH -[ -f "$LUNA_ROOT/env-local.sh" ] && source $LUNA_ROOT/env-local.sh \ No newline at end of file +[ -f "$LUNA_ROOT/env-local.sh" ] && source $LUNA_ROOT/env-local.sh + +export ARCH=${ARCH:-x86_64} + +if [ "$USE_NINJA" = "1" ] +then +export BUILD=ninja +export CMAKE_GEN=Ninja +else +export BUILD=make +export CMAKE_GEN="Unix Makefiles" +fi + +export BUILD_DIR=$LUNA_ROOT/build/$BUILD-$ARCH \ No newline at end of file diff --git a/tools/fast-run.sh b/tools/fast-run.sh index 1d9f21c3..49f43dd9 100755 --- a/tools/fast-run.sh +++ b/tools/fast-run.sh @@ -5,4 +5,4 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -qemu-system-x86_64 -cdrom Luna.iso -smp 1 -m 256M -serial stdio -enable-kvm $@ \ No newline at end of file +qemu-system-$ARCH -cdrom Luna.iso -smp 1 -m 256M -serial stdio -enable-kvm $@ \ No newline at end of file diff --git a/tools/install-built-ports.sh b/tools/install-built-ports.sh deleted file mode 100755 index 8e21fbc4..00000000 --- a/tools/install-built-ports.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source $(dirname $0)/env.sh - -cd $LUNA_ROOT/ports - -unset_vars() -{ - unset pkgname - unset pkgver - unset pkgurl - unset pkgmode - unset setupdir - unset builddir - unset installdir - unset srcdir - unset port_unpack - unset port_patch - unset port_configure - unset port_build - unset port_install - unset port_uninstall - unset islib -} - -if ! [ -f ./ports.list ] -then - echo "No ports built." - exit 0 -fi - -install_port() -{ - unset_vars - cd $LUNA_ROOT/ports - export DESTDIR=${DESTDIR:-"$LUNA_ROOT/initrd"} - export portdir=$PWD/$1 - export workdir=$portdir/workdir - source $portdir/package.sh - if ! [ "$islib" = "1" ] - then - echo "installing port: $pkgname version $pkgver" - mkdir -p $installdir - cd $installdir - port_install | filter-lines $pkgname "install" - fi -} - -while read package; do - install_port $package -done < ./ports.list diff --git a/tools/install.sh b/tools/install.sh index 99247915..73a507f6 100755 --- a/tools/install.sh +++ b/tools/install.sh @@ -5,4 +5,4 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -cmake --install build \ No newline at end of file +cmake --install $BUILD_DIR \ No newline at end of file diff --git a/tools/rebuild-iso.sh b/tools/rebuild-iso.sh index fb38d5b3..8537e980 100755 --- a/tools/rebuild-iso.sh +++ b/tools/rebuild-iso.sh @@ -7,11 +7,12 @@ cd $LUNA_ROOT tools/setup.sh -make clean +cd $BUILD_DIR +$BUILD clean +cd - -tools/install-headers.sh - -make -j$(nproc) -make install +cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" +cmake --build $BUILD_DIR +cmake --install $BUILD_DIR mkbootimg luna.json Luna.iso \ No newline at end of file diff --git a/tools/rebuild.sh b/tools/rebuild.sh index ee3649b0..cff4de9a 100755 --- a/tools/rebuild.sh +++ b/tools/rebuild.sh @@ -7,8 +7,9 @@ cd $LUNA_ROOT tools/setup.sh -tools/install-headers.sh +cd $BUILD_DIR +$BUILD clean +cd - -make clean - -make -j$(nproc) \ No newline at end of file +cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" +cmake --build $BUILD_DIR \ No newline at end of file diff --git a/tools/sync-libc.sh b/tools/sync-libc.sh deleted file mode 100755 index cf6df110..00000000 --- a/tools/sync-libc.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -e -source $(dirname $0)/env.sh - -cd $LUNA_ROOT - -tools/install-headers.sh - -cd libs/ - -$LUNA_ROOT/tools/buildstep.sh libc build -$LUNA_ROOT/tools/buildstep.sh libc install \ No newline at end of file From 102eabcb4b4fa1ad8eebf632995cd0550fbc9830 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 17:52:24 +0100 Subject: [PATCH 046/407] Do some more formatted logging --- kernel/src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 258e35ee..f08ea018 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -30,6 +30,8 @@ extern "C" [[noreturn]] void _start() u64 physical = MemoryManager::alloc_physical_page().release_value(); + Serial::printf("Allocated physical frame %#lx\n", physical); + auto rc = MMU::map(address, physical, MMU::ReadWrite); bool success = !rc.has_error(); @@ -80,6 +82,8 @@ extern "C" [[noreturn]] void _start() CPU::efficient_halt(); } + Serial::printf("Unmapped page, was pointing to %#lx\n", urc.value()); + if (urc.release_value() != physical) { Serial::println("unmap returned a different address than the one we mapped"); From a44e2f41fe3774a9671059b13ac8156b0034a0cc Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 17:59:39 +0100 Subject: [PATCH 047/407] Cleanup kernel/CMakeLists.txt --- kernel/CMakeLists.txt | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 0db461df..f2cbf6cc 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,8 +1,8 @@ set(SOURCES src/main.cpp - src/Framebuffer.cpp - src/MemoryManager.cpp - src/Init.cpp + src/video/Framebuffer.cpp + src/memory/MemoryManager.cpp + src/boot/Init.cpp src/arch/Serial.cpp ) @@ -16,21 +16,14 @@ set(SOURCES ) endif() -set(ASM_SOURCES) - -if("${ARCH}" MATCHES "x86_64") -set(ASM_SOURCES - ${ASM_SOURCES} - src/arch/x86_64/CPU.asm -) - -add_library(moon-asm STATIC ${ASM_SOURCES}) -endif() - add_executable(moon ${SOURCES}) if("${ARCH}" MATCHES "x86_64") -target_link_libraries(moon moon-asm) + set(ASM_SOURCES + src/arch/x86_64/CPU.asm + ) + add_library(moon-asm STATIC ${ASM_SOURCES}) + target_link_libraries(moon moon-asm) endif() target_link_libraries(moon luna-freestanding) @@ -48,16 +41,13 @@ target_compile_options(moon PRIVATE -fno-asynchronous-unwind-tables -fno-omit-fr target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel) if("${ARCH}" MATCHES "x86_64") -target_compile_options(moon PRIVATE -mno-red-zone) -target_compile_options(moon PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) + target_compile_options(moon PRIVATE -mno-red-zone) + target_compile_options(moon PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) + target_link_options(moon PRIVATE -mno-red-zone) endif() target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mcmodel=kernel) -if("${ARCH}" MATCHES "x86_64") -target_link_options(moon PRIVATE -mno-red-zone) -endif() - set_target_properties(moon PROPERTIES CXX_STANDARD 20) target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) From 70c6b78e35d627b1d609a4b7728f10b2198cd9ff Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 17:59:49 +0100 Subject: [PATCH 048/407] Organize source tree --- kernel/src/arch/x86_64/MMU.cpp | 2 +- kernel/src/{ => boot}/Init.cpp | 8 ++++---- kernel/src/{ => boot}/Init.h | 0 kernel/src/{ => boot}/bootboot.h | 2 +- kernel/src/main.cpp | 6 +++--- kernel/src/{ => memory}/MemoryManager.cpp | 4 ++-- kernel/src/{ => memory}/MemoryManager.h | 0 kernel/src/{ => video}/Framebuffer.cpp | 4 ++-- kernel/src/{ => video}/Framebuffer.h | 0 9 files changed, 13 insertions(+), 13 deletions(-) rename kernel/src/{ => boot}/Init.cpp (79%) rename kernel/src/{ => boot}/Init.h (100%) rename kernel/src/{ => boot}/bootboot.h (99%) rename kernel/src/{ => memory}/MemoryManager.cpp (98%) rename kernel/src/{ => memory}/MemoryManager.h (100%) rename kernel/src/{ => video}/Framebuffer.cpp (96%) rename kernel/src/{ => video}/Framebuffer.h (100%) diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 83606dde..474e648d 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -1,5 +1,5 @@ #include "arch/MMU.h" -#include "MemoryManager.h" +#include "memory/MemoryManager.h" #include #define PAGE_SIZE 4096 diff --git a/kernel/src/Init.cpp b/kernel/src/boot/Init.cpp similarity index 79% rename from kernel/src/Init.cpp rename to kernel/src/boot/Init.cpp index 781d1473..46791f34 100644 --- a/kernel/src/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -1,9 +1,9 @@ -#include "Init.h" -#include "Framebuffer.h" -#include "MemoryManager.h" +#include "boot/Init.h" #include "arch/CPU.h" #include "arch/Serial.h" -#include "bootboot.h" +#include "boot/bootboot.h" +#include "memory/MemoryManager.h" +#include "video/Framebuffer.h" #include extern BOOTBOOT bootboot; diff --git a/kernel/src/Init.h b/kernel/src/boot/Init.h similarity index 100% rename from kernel/src/Init.h rename to kernel/src/boot/Init.h diff --git a/kernel/src/bootboot.h b/kernel/src/boot/bootboot.h similarity index 99% rename from kernel/src/bootboot.h rename to kernel/src/boot/bootboot.h index 8ac1207e..7e6b6a17 100644 --- a/kernel/src/bootboot.h +++ b/kernel/src/boot/bootboot.h @@ -1,5 +1,5 @@ /* - * bootboot.h + * boot/bootboot.h * https://gitlab.com/bztsrc/bootboot * * Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index f08ea018..75ea1339 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,9 +1,9 @@ -#include "Framebuffer.h" -#include "Init.h" -#include "MemoryManager.h" #include "arch/CPU.h" #include "arch/MMU.h" #include "arch/Serial.h" +#include "boot/Init.h" +#include "memory/MemoryManager.h" +#include "video/Framebuffer.h" extern u8 fb[1]; diff --git a/kernel/src/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp similarity index 98% rename from kernel/src/MemoryManager.cpp rename to kernel/src/memory/MemoryManager.cpp index e089953a..74357446 100644 --- a/kernel/src/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -1,7 +1,7 @@ -#include "MemoryManager.h" +#include "memory/MemoryManager.h" #include "arch/MMU.h" #include "arch/Serial.h" -#include "bootboot.h" +#include "boot/bootboot.h" #include #include #include diff --git a/kernel/src/MemoryManager.h b/kernel/src/memory/MemoryManager.h similarity index 100% rename from kernel/src/MemoryManager.h rename to kernel/src/memory/MemoryManager.h diff --git a/kernel/src/Framebuffer.cpp b/kernel/src/video/Framebuffer.cpp similarity index 96% rename from kernel/src/Framebuffer.cpp rename to kernel/src/video/Framebuffer.cpp index 6328c33b..8de99d62 100644 --- a/kernel/src/Framebuffer.cpp +++ b/kernel/src/video/Framebuffer.cpp @@ -1,5 +1,5 @@ -#include "Framebuffer.h" -#include "bootboot.h" +#include "video/Framebuffer.h" +#include "boot/bootboot.h" static u8* g_fb_ptr = nullptr; static u32 g_fb_size; diff --git a/kernel/src/Framebuffer.h b/kernel/src/video/Framebuffer.h similarity index 100% rename from kernel/src/Framebuffer.h rename to kernel/src/video/Framebuffer.h From 883a1da0d72082554ea92b1e8a5c301a48f4cc12 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 18:00:45 +0100 Subject: [PATCH 049/407] More indentation in CMakeLists.txt --- kernel/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index f2cbf6cc..24a4acd9 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -7,13 +7,13 @@ set(SOURCES ) if("${ARCH}" MATCHES "x86_64") -set(SOURCES - ${SOURCES} - src/arch/x86_64/IO.cpp - src/arch/x86_64/Serial.cpp - src/arch/x86_64/MMU.cpp - src/arch/x86_64/CPU.cpp -) + set(SOURCES + ${SOURCES} + src/arch/x86_64/IO.cpp + src/arch/x86_64/Serial.cpp + src/arch/x86_64/MMU.cpp + src/arch/x86_64/CPU.cpp + ) endif() add_executable(moon ${SOURCES}) From db3e34b2bac0b5e4d55fa8a174c2bb776074b632 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 18:38:01 +0100 Subject: [PATCH 050/407] Result: Add try_set_value() This helper returns true if the Result contains a value, or false if it doesn't. Additionally, if it has a value, it sets the passed reference to it. --- luna/Result.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/luna/Result.h b/luna/Result.h index e5e99ae0..1aec130f 100644 --- a/luna/Result.h +++ b/luna/Result.h @@ -104,6 +104,13 @@ template class Result return other; } + bool try_set_value(T& ref) + { + if (!has_value()) return false; + ref = m_storage.fetch_reference(); + return true; + } + T release_value() { check(has_value()); From 424b069d55fadff2802dbc72d9174b37555d3ea7 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 18:38:32 +0100 Subject: [PATCH 051/407] Kernel: Start the call stack with a null RBP on x86_64 --- kernel/CMakeLists.txt | 1 + kernel/moon.ld | 2 +- kernel/src/arch/x86_64/Entry.asm | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 kernel/src/arch/x86_64/Entry.asm diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 24a4acd9..28e9451a 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -21,6 +21,7 @@ add_executable(moon ${SOURCES}) if("${ARCH}" MATCHES "x86_64") set(ASM_SOURCES src/arch/x86_64/CPU.asm + src/arch/x86_64/Entry.asm ) add_library(moon-asm STATIC ${ASM_SOURCES}) target_link_libraries(moon moon-asm) diff --git a/kernel/moon.ld b/kernel/moon.ld index 5b99a57b..c3b72198 100644 --- a/kernel/moon.ld +++ b/kernel/moon.ld @@ -1,4 +1,4 @@ -ENTRY(_start) +ENTRY(_main) OUTPUT_FORMAT(elf64-x86-64) mmio = 0xfffffffff8000000; /* these are configurable for level 2 loaders */ diff --git a/kernel/src/arch/x86_64/Entry.asm b/kernel/src/arch/x86_64/Entry.asm new file mode 100644 index 00000000..92eee7f3 --- /dev/null +++ b/kernel/src/arch/x86_64/Entry.asm @@ -0,0 +1,6 @@ +global _main +extern _start + +_main: + xor rbp, rbp + call _start \ No newline at end of file From 047f445651360cc735a206f81a7a658fd9d01871 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 18:38:47 +0100 Subject: [PATCH 052/407] Kernel: Add helpers to validate memory addresses --- kernel/src/memory/MemoryManager.cpp | 15 +++++++++++++++ kernel/src/memory/MemoryManager.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 74357446..c8ce477b 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -184,6 +184,21 @@ namespace MemoryManager return {}; } + bool validate_readable_page(u64 address) + { + auto rc = MMU::get_flags(address); + if (rc.has_error()) return false; + return true; + } + + bool validate_writable_page(u64 address) + { + auto rc = MMU::get_flags(address); + if (rc.has_error()) return false; + if (rc.release_value() & MMU::ReadWrite) return true; + return false; + } + u64 free() { return free_mem; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index d1ca0f5f..6250b863 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -17,6 +17,9 @@ namespace MemoryManager Result remap(u64 address, usize count, int flags); Result remap_unaligned(u64 address, usize count, int flags); + bool validate_readable_page(u64 address); + bool validate_writable_page(u64 address); + u64 free(); u64 used(); u64 reserved(); From 83bcac7a1635d7af5870808a9fc6aeda87454ccd Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 20:01:01 +0100 Subject: [PATCH 053/407] Kernel: Introduce a timer interface --- kernel/CMakeLists.txt | 2 + kernel/src/arch/CPU.h | 5 ++ kernel/src/arch/Timer.cpp | 80 ++++++++++++++++++++++++++++++ kernel/src/arch/Timer.h | 33 +++++++++++++ kernel/src/arch/x86_64/CPU.asm | 3 +- kernel/src/arch/x86_64/CPU.cpp | 83 ++++++++++++++++++++++++++++++++ kernel/src/arch/x86_64/Entry.asm | 1 + kernel/src/arch/x86_64/Timer.cpp | 16 ++++++ kernel/src/boot/Init.cpp | 2 + kernel/src/main.cpp | 16 +++++- luna/Format.cpp | 3 +- 11 files changed, 240 insertions(+), 4 deletions(-) create mode 100644 kernel/src/arch/Timer.cpp create mode 100644 kernel/src/arch/Timer.h create mode 100644 kernel/src/arch/x86_64/Timer.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 28e9451a..12f1a041 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES src/memory/MemoryManager.cpp src/boot/Init.cpp src/arch/Serial.cpp + src/arch/Timer.cpp ) if("${ARCH}" MATCHES "x86_64") @@ -13,6 +14,7 @@ if("${ARCH}" MATCHES "x86_64") src/arch/x86_64/Serial.cpp src/arch/x86_64/MMU.cpp src/arch/x86_64/CPU.cpp + src/arch/x86_64/Timer.cpp ) endif() diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index e2d2313c..daad9bd0 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -9,8 +9,13 @@ namespace CPU const char* platform_string(); void platform_init(); + void platform_finish_init(); [[noreturn]] void efficient_halt(); void switch_kernel_stack(u64 top); + + void enable_interrupts(); + void disable_interrupts(); + void wait_for_interrupt(); } \ No newline at end of file diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp new file mode 100644 index 00000000..c06b003c --- /dev/null +++ b/kernel/src/arch/Timer.cpp @@ -0,0 +1,80 @@ +#include "arch/Timer.h" + +static u64 timer_ticks = 0; +static u64 boot_timestamp; + +namespace Timer +{ + void tick() + { + timer_ticks++; + } + + usize ticks() + { + return ticks_ms() / 1000; + } + + usize ticks_ms() + { + return timer_ticks / ARCH_TIMER_FREQ; + } + + usize ticks_us() // We want a bit of precision; if there are 10 ticks/ms, do not return the truncated ms value * + // 1000, but ticks * 100 (1000/10), which is more precise + { + if (ARCH_TIMER_FREQ > 1000) [[unlikely]] + return timer_ticks / (ARCH_TIMER_FREQ / 1000); + return timer_ticks * (1000 / ARCH_TIMER_FREQ); + } + + usize ticks_ns() + { + return ticks_us() * 1000; + } + + usize boot() + { + return boot_timestamp; + } + + usize boot_ms() + { + return boot_timestamp * MS_PER_SECOND; + } + + usize boot_us() + { + return boot_timestamp * US_PER_SECOND; + } + + usize boot_ns() + { + return boot_timestamp * NS_PER_SECOND; + } + + usize clock() + { + return boot() + ticks(); + } + + usize clock_ms() + { + return boot_ms() + ticks_ms(); + } + + usize clock_us() + { + return boot_us() + ticks_us(); + } + + usize clock_ns() + { + return boot_ns() + ticks_ns(); + } + + void init() + { + arch_init(); + } +} \ No newline at end of file diff --git a/kernel/src/arch/Timer.h b/kernel/src/arch/Timer.h new file mode 100644 index 00000000..d2895de3 --- /dev/null +++ b/kernel/src/arch/Timer.h @@ -0,0 +1,33 @@ +#pragma once +#include + +extern const usize ARCH_TIMER_FREQ; // How many timer ticks in one millisecond? + +static const usize MS_PER_SECOND = 1000; +static const usize US_PER_SECOND = MS_PER_SECOND * 1000; +static const usize NS_PER_SECOND = US_PER_SECOND * 1000; + +namespace Timer +{ + void tick(); + + usize raw_ticks(); + + usize ticks(); + usize ticks_ms(); + usize ticks_us(); + usize ticks_ns(); + + usize boot(); + usize boot_ms(); + usize boot_us(); + usize boot_ns(); + + usize clock(); + usize clock_ms(); + usize clock_us(); + usize clock_ns(); + + void arch_init(); + void init(); +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index f59fca57..c5b37810 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -149,4 +149,5 @@ _isr18: ; machine check (#MC) ISR 19 ; SIMD floating-point exception (#XM) ISR 20 ; virtualization exception (#VE) ISR_ERROR 21 ; control-protection exception (#CP) -; ISR 22-31 reserved \ No newline at end of file +; ISR 22-31 reserved +IRQ 32, 0 ; timer interrupt \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index c9a2010f..8f77a652 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -1,5 +1,7 @@ #include "arch/x86_64/CPU.h" #include "arch/Serial.h" +#include "arch/Timer.h" +#include "arch/x86_64/IO.h" #include #include #include @@ -105,6 +107,59 @@ static void setup_gdt() load_tr(0x2b); } +// PIC code + +#define PIC1_COMMAND 0x20 +#define PIC1_DATA 0x21 +#define PIC2_COMMAND 0xA0 +#define PIC2_DATA 0xA1 +#define PIC_EOI 0x20 + +#define ICW1_INIT 0x10 +#define ICW1_ICW4 0x01 +#define ICW4_8086 0x01 + +#define io_delay() IO::outb(0x80, 0) + +static void remap_pic() +{ + IO::outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); + io_delay(); + IO::outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); + io_delay(); + + IO::outb(PIC1_DATA, 0x20); + io_delay(); + + IO::outb(PIC2_DATA, 0x28); + io_delay(); + + IO::outb(PIC1_DATA, 4); + io_delay(); + IO::outb(PIC2_DATA, 2); + io_delay(); + + IO::outb(PIC1_DATA, ICW4_8086); + io_delay(); + IO::outb(PIC2_DATA, ICW4_8086); + io_delay(); + + IO::outb(PIC1_DATA, 0b11111110); + io_delay(); + IO::outb(PIC2_DATA, 0b11111111); +} + +static void pic_eoi(unsigned char irq) +{ + if (irq >= 8) IO::outb(PIC2_COMMAND, PIC_EOI); + IO::outb(PIC1_COMMAND, PIC_EOI); +} + +static void pic_eoi(Registers* regs) +{ + pic_eoi((unsigned char)(regs->error)); // On IRQs, the error code is the IRQ number +} + // IDT code and definitions struct IDTEntry @@ -160,6 +215,7 @@ static void idt_add_handler(short num, void* handler, u8 type_attr) #define INT(x) extern "C" void _isr##x() #define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) +#define IRQ(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_InterruptGate) INT(0); INT(1); @@ -181,6 +237,7 @@ INT(18); INT(19); INT(20); INT(21); +INT(32); static void setup_idt() { @@ -206,6 +263,7 @@ static void setup_idt() TRAP(19); TRAP(20); TRAP(21); + IRQ(32); static IDTR idtr; idtr.limit = 0x0FFF; @@ -249,6 +307,11 @@ extern "C" void handle_x86_exception([[maybe_unused]] Registers* regs) extern "C" void arch_interrupt_entry(Registers* regs) { if (regs->isr < 32) handle_x86_exception(regs); + else if (regs->isr == 32) + { + Timer::tick(); + pic_eoi(regs); + } else { Serial::println("IRQ catched! Halting."); @@ -310,6 +373,26 @@ namespace CPU setup_idt(); } + void platform_finish_init() + { + remap_pic(); + } + + void enable_interrupts() + { + asm volatile("sti"); + } + + void disable_interrupts() + { + asm volatile("cli"); + } + + void wait_for_interrupt() + { + asm volatile("hlt"); + } + [[noreturn]] void efficient_halt() // Halt the CPU, using the lowest power possible. On x86-64 we do this using the // "hlt" instruction, which puts the CPU into a low-power idle state until the // next interrupt arrives... and we disable interrupts beforehand. diff --git a/kernel/src/arch/x86_64/Entry.asm b/kernel/src/arch/x86_64/Entry.asm index 92eee7f3..62dee46c 100644 --- a/kernel/src/arch/x86_64/Entry.asm +++ b/kernel/src/arch/x86_64/Entry.asm @@ -3,4 +3,5 @@ extern _start _main: xor rbp, rbp + cld call _start \ No newline at end of file diff --git a/kernel/src/arch/x86_64/Timer.cpp b/kernel/src/arch/x86_64/Timer.cpp new file mode 100644 index 00000000..da8dc528 --- /dev/null +++ b/kernel/src/arch/x86_64/Timer.cpp @@ -0,0 +1,16 @@ +#include "arch/Timer.h" +#include "arch/x86_64/IO.h" + +#define PIT_CHANNEL_0 0x40 + +const u64 base_frequency = 1193182; +const usize ARCH_TIMER_FREQ = 10; + +void Timer::arch_init() +{ + constexpr u16 divisor = (uint16_t)(base_frequency / (ARCH_TIMER_FREQ * 1000)); + static_assert(divisor >= 100); + IO::outb(PIT_CHANNEL_0, (uint8_t)(divisor & 0xFF)); + IO::outb(0x80, 0); // short delay + IO::outb(PIT_CHANNEL_0, (uint8_t)((divisor & 0xFF00) >> 8)); +} \ No newline at end of file diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 46791f34..ab7a0ee1 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -20,6 +20,8 @@ void Init::check_magic() void Init::early_init() { + CPU::disable_interrupts(); + Framebuffer::init(); MemoryManager::init(); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 75ea1339..4442ceef 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,6 +1,7 @@ #include "arch/CPU.h" #include "arch/MMU.h" #include "arch/Serial.h" +#include "arch/Timer.h" #include "boot/Init.h" #include "memory/MemoryManager.h" #include "video/Framebuffer.h" @@ -92,9 +93,20 @@ extern "C" [[noreturn]] void _start() Serial::println("Successfully unmapped address"); - *ptr = 16; + Timer::init(); - Serial::println("ERROR: Still here after page fault"); + CPU::platform_finish_init(); + + CPU::enable_interrupts(); + + usize start = 0; + + while (1) + { + while ((Timer::ticks_ms() - start) < 20) { CPU::wait_for_interrupt(); } + start = Timer::ticks_ms(); + Serial::printf("%8zu milliseconds have passed!\n", start); + } CPU::efficient_halt(); } \ No newline at end of file diff --git a/luna/Format.cpp b/luna/Format.cpp index 02eb0ff6..6f3a2e56 100644 --- a/luna/Format.cpp +++ b/luna/Format.cpp @@ -185,7 +185,8 @@ static bool is_integer_format_specifier(char c) static usize to_string(usize value, usize base, char* buf, usize max, bool uppercase) { usize i = 0; - if (!value && max) + if (!max) return 0; + if (!value) { buf[i] = '0'; return 1; From 847f2b4f4c4d5e456d0f60728cc66b8d8cd06303 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 22:25:03 +0100 Subject: [PATCH 054/407] Replace more usage of stdint.h types with Luna's Types.h --- kernel/src/arch/x86_64/CPU.cpp | 4 ++-- kernel/src/arch/x86_64/Timer.cpp | 6 +++--- kernel/src/memory/MemoryManager.cpp | 19 ++++++++----------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 8f77a652..968ba063 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -199,8 +199,8 @@ static IDTEntry idt[256]; struct IDTR { - uint16_t limit; - uint64_t offset; + u16 limit; + u64 offset; } __attribute__((packed)); static void idt_add_handler(short num, void* handler, u8 type_attr) diff --git a/kernel/src/arch/x86_64/Timer.cpp b/kernel/src/arch/x86_64/Timer.cpp index da8dc528..c5c693f8 100644 --- a/kernel/src/arch/x86_64/Timer.cpp +++ b/kernel/src/arch/x86_64/Timer.cpp @@ -8,9 +8,9 @@ const usize ARCH_TIMER_FREQ = 10; void Timer::arch_init() { - constexpr u16 divisor = (uint16_t)(base_frequency / (ARCH_TIMER_FREQ * 1000)); + constexpr u16 divisor = (u16)(base_frequency / (ARCH_TIMER_FREQ * 1000)); static_assert(divisor >= 100); - IO::outb(PIT_CHANNEL_0, (uint8_t)(divisor & 0xFF)); + IO::outb(PIT_CHANNEL_0, (u8)(divisor & 0xFF)); IO::outb(0x80, 0); // short delay - IO::outb(PIT_CHANNEL_0, (uint8_t)((divisor & 0xFF00) >> 8)); + IO::outb(PIT_CHANNEL_0, (u8)((divisor & 0xFF00) >> 8)); } \ No newline at end of file diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index c8ce477b..fd2c4ac5 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -33,10 +33,10 @@ static bool page_bitmap_read(u64 index) static void page_bitmap_set(u64 index, bool value) { - uint64_t byteIndex = index / 8; - uint8_t bitIndexer = 0b10000000 >> (index % 8); - page_virtual_bitmap_addr[byteIndex] &= (uint8_t)(~bitIndexer); - if (value) { page_virtual_bitmap_addr[byteIndex] |= bitIndexer; } + u64 byte_index = index / 8; + u8 mask = 0b10000000 >> (index % 8); + page_virtual_bitmap_addr[byte_index] &= (u8)(~mask); + if (value) { page_virtual_bitmap_addr[byte_index] |= mask; } } namespace MemoryManager @@ -61,7 +61,7 @@ namespace MemoryManager // walk the memory map MMapEnt* ptr = &bootboot.mmap; - uint64_t mmap_entries = (bootboot.size - 128) / 16; + u64 mmap_entries = (bootboot.size - 128) / 16; for (u64 i = 0; i < mmap_entries; i++) { u64 size = MMapEnt_Size(ptr); @@ -92,17 +92,14 @@ namespace MemoryManager memset(page_bitmap_addr, 0xFF, page_bitmap_size); ptr = &bootboot.mmap; - for (uint64_t i = 0; i < mmap_entries; i++) + for (u64 i = 0; i < mmap_entries; i++) { - uint64_t index = MMapEnt_Ptr(ptr) / ARCH_PAGE_SIZE; + u64 index = MMapEnt_Ptr(ptr) / ARCH_PAGE_SIZE; if (!MMapEnt_IsFree(ptr)) { reserved_mem += MMapEnt_Size(ptr); } else { free_mem += MMapEnt_Size(ptr); - for (uint64_t j = 0; j < (MMapEnt_Size(ptr) / ARCH_PAGE_SIZE); j++) - { - page_bitmap_set(index + j, false); - } + for (u64 j = 0; j < (MMapEnt_Size(ptr) / ARCH_PAGE_SIZE); j++) { page_bitmap_set(index + j, false); } } ptr++; } From d96cb73995b63b7ea097027827310c5117beefb4 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 22:27:08 +0100 Subject: [PATCH 055/407] Rename physical "pages" to "frames" AFAIK, this is the proper naming scheme. "Pages" are virtual, and "frames" physical. --- kernel/src/arch/x86_64/MMU.cpp | 6 +++--- kernel/src/main.cpp | 2 +- kernel/src/memory/MemoryManager.cpp | 16 ++++++++-------- kernel/src/memory/MemoryManager.h | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 474e648d..613fcacb 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -196,7 +196,7 @@ namespace MMU auto& l4 = l4_entry(virt); if (!l4.present) { - u64 addr = TRY(MemoryManager::alloc_physical_page()); + u64 addr = TRY(MemoryManager::alloc_frame()); l4.present = true; l4.set_address(addr); memset(l3_table(virt), 0, PAGE_SIZE); @@ -208,7 +208,7 @@ namespace MMU auto& l3 = l3_entry(virt); if (!l3.present) { - u64 addr = TRY(MemoryManager::alloc_physical_page()); + u64 addr = TRY(MemoryManager::alloc_frame()); l3.present = true; l3.set_address(addr); memset(l2_table(virt), 0, PAGE_SIZE); @@ -222,7 +222,7 @@ namespace MMU auto& l2 = l2_entry(virt); if (!l2.present) { - u64 addr = TRY(MemoryManager::alloc_physical_page()); + u64 addr = TRY(MemoryManager::alloc_frame()); l2.present = true; l2.set_address(addr); memset(l1_table(virt), 0, PAGE_SIZE); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 4442ceef..6229e480 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -29,7 +29,7 @@ extern "C" [[noreturn]] void _start() Serial::printf("Mapping address 0x%lx\n", address); - u64 physical = MemoryManager::alloc_physical_page().release_value(); + u64 physical = MemoryManager::alloc_frame().release_value(); Serial::printf("Allocated physical frame %#lx\n", physical); diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index fd2c4ac5..57222223 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -104,7 +104,7 @@ namespace MemoryManager ptr++; } - lock_pages((u64)page_bitmap_addr, page_bitmap_size / ARCH_PAGE_SIZE + 1); + lock_frames((u64)page_bitmap_addr, page_bitmap_size / ARCH_PAGE_SIZE + 1); } void init() @@ -113,21 +113,21 @@ namespace MemoryManager MMU::setup_initial_page_directory(); } - void lock_page(u64 page) + void lock_frame(u64 frame) { - uint64_t index = ((uint64_t)page) / ARCH_PAGE_SIZE; + const u64 index = ((u64)frame) / ARCH_PAGE_SIZE; if (page_bitmap_read(index)) return; page_bitmap_set(index, true); used_mem += ARCH_PAGE_SIZE; free_mem -= ARCH_PAGE_SIZE; } - void lock_pages(u64 pages, u64 count) + void lock_frames(u64 frames, u64 count) { - for (u64 index = 0; index < count; index++) { lock_page(pages + (index * ARCH_PAGE_SIZE)); } + for (u64 index = 0; index < count; index++) { lock_frame(frames + (index * ARCH_PAGE_SIZE)); } } - Result alloc_physical_page() + Result alloc_frame() { for (u64 index = start_index; index < (page_bitmap_size * 8); index++) { @@ -142,9 +142,9 @@ namespace MemoryManager return err; // FIXME: ENOMEM. } - Result free_physical_page(u64 page) + Result free_frame(u64 frame) { - u64 index = page / ARCH_PAGE_SIZE; + const u64 index = frame / ARCH_PAGE_SIZE; if (index > (page_bitmap_size * 8)) return err; if (!page_bitmap_read(index)) return err; page_bitmap_set(index, false); diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 6250b863..21ab26f8 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -8,11 +8,11 @@ namespace MemoryManager Result protect_kernel_sections(); - Result alloc_physical_page(); - Result free_physical_page(u64 page); + Result alloc_frame(); + Result free_frame(u64 frame); - void lock_page(u64 page); - void lock_pages(u64 pages, u64 count); + void lock_frame(u64 frame); + void lock_frames(u64 frames, u64 count); Result remap(u64 address, usize count, int flags); Result remap_unaligned(u64 address, usize count, int flags); From c886669d561f3b6b2413c9dd06ce7288b16d4a52 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 22:27:59 +0100 Subject: [PATCH 056/407] Break down operations to make protect_kernel_sections() more readable --- kernel/src/memory/MemoryManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 57222223..335c3d54 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -43,10 +43,12 @@ namespace MemoryManager { Result protect_kernel_sections() { - u64 rodata_pages = get_blocks_from_size((u64)(end_of_kernel_rodata - start_of_kernel_rodata), ARCH_PAGE_SIZE); + const u64 rodata_size = (u64)(end_of_kernel_rodata - start_of_kernel_rodata); + const u64 rodata_pages = get_blocks_from_size(rodata_size, ARCH_PAGE_SIZE); TRY(remap((u64)start_of_kernel_rodata, rodata_pages, MMU::NoExecute)); - u64 data_pages = get_blocks_from_size((u64)(end_of_kernel_data - start_of_kernel_data), ARCH_PAGE_SIZE); + const u64 data_size = (u64)(end_of_kernel_data - start_of_kernel_data); + const u64 data_pages = get_blocks_from_size(data_size, ARCH_PAGE_SIZE); TRY(remap((u64)start_of_kernel_data, data_pages, MMU::NoExecute | MMU::ReadWrite)); return {}; From 1b41a3e9cfcbf4224ff206661f1a7997d6a25d9c Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 22:28:45 +0100 Subject: [PATCH 057/407] Introduce a few helpers to allocate/map/unmap several pages, which wrap around the MMU functionality --- kernel/src/memory/MemoryManager.cpp | 60 ++++++++++++++++++++++++++++- kernel/src/memory/MemoryManager.h | 7 ++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 335c3d54..b3fc2f8c 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -39,6 +39,8 @@ static void page_bitmap_set(u64 index, bool value) if (value) { page_virtual_bitmap_addr[byte_index] |= mask; } } +#define CHECK_PAGE_ALIGNED(address) check(is_aligned(address, ARCH_PAGE_SIZE)) + namespace MemoryManager { Result protect_kernel_sections() @@ -158,7 +160,7 @@ namespace MemoryManager Result remap(u64 address, usize count, int flags) { - check(is_aligned(address, ARCH_PAGE_SIZE)); + CHECK_PAGE_ALIGNED(address); while (count--) { @@ -169,6 +171,62 @@ namespace MemoryManager return {}; } + Result map(u64 virt, u64 phys, usize count, int flags) + { + CHECK_PAGE_ALIGNED(virt); + CHECK_PAGE_ALIGNED(phys); + + while (count--) + { + TRY(MMU::map(virt, phys, flags)); + virt += ARCH_PAGE_SIZE; + phys += ARCH_PAGE_SIZE; + } + + return {}; + } + + Result alloc_at(u64 virt, usize count, int flags) + { + CHECK_PAGE_ALIGNED(virt); + + while (count--) + { + u64 frame = TRY(alloc_frame()); + TRY(MMU::map(virt, frame, flags)); + virt += ARCH_PAGE_SIZE; + } + + return virt; + } + + Result unmap_owned(u64 virt, usize count) + { + CHECK_PAGE_ALIGNED(virt); + + while (count--) + { + u64 frame = TRY(MMU::unmap(virt)); + TRY(free_frame(frame)); + virt += ARCH_PAGE_SIZE; + } + + return {}; + } + + Result unmap_weak(u64 virt, usize count) + { + CHECK_PAGE_ALIGNED(virt); + + while (count--) + { + TRY(MMU::unmap(virt)); + virt += ARCH_PAGE_SIZE; + } + + return {}; + } + Result remap_unaligned(u64 address, usize count, int flags) { if (!is_aligned(address, ARCH_PAGE_SIZE)) count++; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 21ab26f8..734aa87c 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -20,6 +20,13 @@ namespace MemoryManager bool validate_readable_page(u64 address); bool validate_writable_page(u64 address); + Result map(u64 virt, u64 phys, usize count, int flags); + + Result alloc_at(u64 virt, usize count, int flags); + + Result unmap_owned(u64 virt, usize count); + Result unmap_weak(u64 virt, usize count); + u64 free(); u64 used(); u64 reserved(); From af267772f0af1303728fa98fe786153950c1b2e4 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 22:32:48 +0100 Subject: [PATCH 058/407] Rename MemoryManager::map to map_frames_at To make it clearer that this API is only intented for mapping contiguous frames of physical memory (for MMIO perhaps?) --- kernel/src/memory/MemoryManager.cpp | 2 +- kernel/src/memory/MemoryManager.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index b3fc2f8c..978a0b98 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -171,7 +171,7 @@ namespace MemoryManager return {}; } - Result map(u64 virt, u64 phys, usize count, int flags) + Result map_frames_at(u64 virt, u64 phys, usize count, int flags) { CHECK_PAGE_ALIGNED(virt); CHECK_PAGE_ALIGNED(phys); diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 734aa87c..17bf0136 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -20,7 +20,7 @@ namespace MemoryManager bool validate_readable_page(u64 address); bool validate_writable_page(u64 address); - Result map(u64 virt, u64 phys, usize count, int flags); + Result map_frames_at(u64 virt, u64 phys, usize count, int flags); Result alloc_at(u64 virt, usize count, int flags); From 30a7d760ae6b8761a870b8d84812a8de2a4af5cc Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 22:48:20 +0100 Subject: [PATCH 059/407] Move a few repeated lambdas into their own functions --- luna/NumberParsing.cpp | 80 ++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/luna/NumberParsing.cpp b/luna/NumberParsing.cpp index 4387407e..742b2447 100644 --- a/luna/NumberParsing.cpp +++ b/luna/NumberParsing.cpp @@ -37,33 +37,36 @@ isize _atos(const char** str) return neg ? -val : val; } +static bool is_valid_digit_for_base(int base, char c) +{ + if (base <= 10) + { + if (!_isdigit(c)) return false; // Bases lower than 10 only use decimal digits. + if ((c - '0') < base) return true; + return false; + } + else + { + if (!_isalnum(c)) return false; // Any valid base (2-36) only uses 0-9 and a-z. + if (_isdigit(c)) return true; // Any base higher than decimal will include all decimal digits. + bool lower = _islower(c); + if (((c - lower ? 'a' : 'A') + 10) < base) return true; + return false; + } +} + +// This function assumes you have called is_valid_digit_for_base() to validate the digit first. +static isize parse_digit_unchecked(char c) +{ + if (_isdigit(c)) return c - '0'; + if (_islower(c)) return (c - 'a') + 10; + return (c - 'A') + 10; +} + usize _strtou(const char* str, const char** endptr, int base) { usize val = 0; - auto valid_digit = [](int _base, char c) -> bool { - if (_base <= 10) - { - if (!_isdigit(c)) return false; - if ((c - '0') < _base) return true; - return false; - } - else - { - if (!_isalnum(c)) return false; - if (_isdigit(c)) return true; - bool lower = _islower(c); - if (((c - lower ? 'a' : 'A') + 10) < _base) return true; - return false; - } - }; - - auto to_digit = [](char c) -> usize { - if (_isdigit(c)) return c - '0'; - if (_islower(c)) return (c - 'a') + 10; - return (c - 'A') + 10; - }; - while (_isspace(*str)) str++; if ((base == 0 || base == 16) && *str == '0') @@ -80,9 +83,9 @@ usize _strtou(const char* str, const char** endptr, int base) else if (base == 0) base = 10; - while (valid_digit(base, *str)) + while (is_valid_digit_for_base(base, *str)) { - val = (base * val) + to_digit(*str); + val = (base * val) + parse_digit_unchecked(*str); str++; } @@ -96,29 +99,6 @@ isize _strtoi(const char* str, const char** endptr, int base) isize val = 0; bool negative = false; - auto valid_digit = [](int _base, char c) -> bool { - if (_base <= 10) - { - if (!_isdigit(c)) return false; - if ((c - '0') < _base) return true; - return false; - } - else - { - if (!_isalnum(c)) return false; - if (_isdigit(c)) return true; - bool lower = _islower(c); - if (((c - lower ? 'a' : 'A') + 10) < _base) return true; - return false; - } - }; - - auto to_digit = [](char c) -> isize { - if (_isdigit(c)) return c - '0'; - if (_islower(c)) return (c - 'a') + 10; - return (c - 'A') + 10; - }; - while (_isspace(*str)) str++; if (*str == '-' || *str == '+') @@ -141,9 +121,9 @@ isize _strtoi(const char* str, const char** endptr, int base) else if (base == 0) base = 10; - while (valid_digit(base, *str)) + while (is_valid_digit_for_base(base, *str)) { - val = (base * val) + to_digit(*str); + val = (base * val) + parse_digit_unchecked(*str); str++; } From 44f44aedca172ffadf875adbe02b745aa36eb421 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 22:52:08 +0100 Subject: [PATCH 060/407] Make _strtoi call _strtou, to deduplicate code --- luna/NumberParsing.cpp | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/luna/NumberParsing.cpp b/luna/NumberParsing.cpp index 742b2447..428cbfa1 100644 --- a/luna/NumberParsing.cpp +++ b/luna/NumberParsing.cpp @@ -96,7 +96,6 @@ usize _strtou(const char* str, const char** endptr, int base) isize _strtoi(const char* str, const char** endptr, int base) { - isize val = 0; bool negative = false; while (_isspace(*str)) str++; @@ -107,27 +106,8 @@ isize _strtoi(const char* str, const char** endptr, int base) str++; } - if ((base == 0 || base == 16) && *str == '0') - { - str++; - if (_tolower(*str) == 'x') - { - base = 16; - str++; - } - else if (base == 0) - base = 8; - } - else if (base == 0) - base = 10; + usize rc = _strtou(str, endptr, + base); // FIXME: Check for overflow (the unsigned usize value might not fit into a signed isize) - while (is_valid_digit_for_base(base, *str)) - { - val = (base * val) + parse_digit_unchecked(*str); - str++; - } - - if (endptr) *endptr = str; - - return negative ? -val : val; + return negative ? -(isize)rc : (isize)rc; } From bde5de68ca8c3ca3a1881dae2e6c671b327a47cc Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 09:24:21 +0100 Subject: [PATCH 061/407] Simplify is_valid_digit_for_base by reaching out to parse_digit_unchecked --- luna/NumberParsing.cpp | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/luna/NumberParsing.cpp b/luna/NumberParsing.cpp index 428cbfa1..7304a851 100644 --- a/luna/NumberParsing.cpp +++ b/luna/NumberParsing.cpp @@ -37,24 +37,6 @@ isize _atos(const char** str) return neg ? -val : val; } -static bool is_valid_digit_for_base(int base, char c) -{ - if (base <= 10) - { - if (!_isdigit(c)) return false; // Bases lower than 10 only use decimal digits. - if ((c - '0') < base) return true; - return false; - } - else - { - if (!_isalnum(c)) return false; // Any valid base (2-36) only uses 0-9 and a-z. - if (_isdigit(c)) return true; // Any base higher than decimal will include all decimal digits. - bool lower = _islower(c); - if (((c - lower ? 'a' : 'A') + 10) < base) return true; - return false; - } -} - // This function assumes you have called is_valid_digit_for_base() to validate the digit first. static isize parse_digit_unchecked(char c) { @@ -63,6 +45,13 @@ static isize parse_digit_unchecked(char c) return (c - 'A') + 10; } +static bool is_valid_digit_for_base(int base, char c) +{ + if (!_isalnum(c)) return false; + if (parse_digit_unchecked(c) >= (isize)base) return false; + return true; +} + usize _strtou(const char* str, const char** endptr, int base) { usize val = 0; From 33876dcda446d50ed852e476771cec3c5fbedff8 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 09:28:17 +0100 Subject: [PATCH 062/407] Use _strto{i,u} in _atou and _atos --- luna/NumberParsing.cpp | 47 +++++++++--------------------------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/luna/NumberParsing.cpp b/luna/NumberParsing.cpp index 7304a851..0e46b314 100644 --- a/luna/NumberParsing.cpp +++ b/luna/NumberParsing.cpp @@ -1,42 +1,5 @@ #include -usize _atou(const char** str) -{ - usize val = 0; - - while (_isdigit(**str)) - { - val = (10 * val) + (**str - '0'); - (*str)++; - } - - return val; -} - -isize _atos(const char** str) -{ - bool neg = false; - isize val = 0; - - switch (**str) - { - case '-': - neg = true; - (*str)++; - break; - case '+': (*str)++; break; - default: break; - } - - while (_isdigit(**str)) - { - val = (10 * val) + (**str - '0'); - (*str)++; - } - - return neg ? -val : val; -} - // This function assumes you have called is_valid_digit_for_base() to validate the digit first. static isize parse_digit_unchecked(char c) { @@ -100,3 +63,13 @@ isize _strtoi(const char* str, const char** endptr, int base) return negative ? -(isize)rc : (isize)rc; } + +usize _atou(const char** str) +{ + return _strtou(*str, str, 10); +} + +isize _atos(const char** str) +{ + return _strtoi(*str, str, 10); +} From cb88630d86ae4375b1812d41ad072e3efec04dce Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 15:11:53 +0100 Subject: [PATCH 063/407] Bugfix: Make alloc_at return the start of the virtual memory range instead of the end --- kernel/src/memory/MemoryManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 978a0b98..ebfb7b0e 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -190,6 +190,8 @@ namespace MemoryManager { CHECK_PAGE_ALIGNED(virt); + u64 start = virt; + while (count--) { u64 frame = TRY(alloc_frame()); @@ -197,7 +199,7 @@ namespace MemoryManager virt += ARCH_PAGE_SIZE; } - return virt; + return start; } Result unmap_owned(u64 virt, usize count) From 3815f9aa9f02648e535a90f7b604f1744ae4bd8d Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 15:12:18 +0100 Subject: [PATCH 064/407] Introduce an offset_ptr function to avoid quirky C pointer arithmetic --- luna/Alignment.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/luna/Alignment.h b/luna/Alignment.h index e69c0aad..0721aae5 100644 --- a/luna/Alignment.h +++ b/luna/Alignment.h @@ -36,4 +36,11 @@ template constexpr T get_blocks_from_size(T value, T block_size) static_assert(get_blocks_from_size(40960, 4096) == 10); static_assert(get_blocks_from_size(194, 64) == 4); static_assert(get_blocks_from_size(2, 32) == 1); -static_assert(get_blocks_from_size(0, 256) == 0); \ No newline at end of file +static_assert(get_blocks_from_size(0, 256) == 0); + +// Offset a pointer by exactly bytes, no matter the type. Useful to avoid the quirks that come from C pointer +// arithmetic. +template constexpr T* offset_ptr(T* ptr, Offset offset) +{ + return (T*)((char*)ptr + offset); +} \ No newline at end of file From caf6d1563c47433519b7abd07ddf724fc689af14 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 15:15:26 +0100 Subject: [PATCH 065/407] Kernel: Add a heap memory allocator This is the first time I've actually dropped liballoc in favor of writing my own implementation. Usually, malloc() and such looked so complicated that I preferred to let a nice external library do the job. But I've decided to try writing my own allocator, and now we have heap memory without any 3rd party code! --- kernel/CMakeLists.txt | 1 + kernel/src/main.cpp | 11 ++ kernel/src/memory/Heap.cpp | 331 +++++++++++++++++++++++++++++++++++++ kernel/src/memory/Heap.h | 7 + 4 files changed, 350 insertions(+) create mode 100644 kernel/src/memory/Heap.cpp create mode 100644 kernel/src/memory/Heap.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 12f1a041..5fe6a323 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES src/main.cpp src/video/Framebuffer.cpp src/memory/MemoryManager.cpp + src/memory/Heap.cpp src/boot/Init.cpp src/arch/Serial.cpp src/arch/Timer.cpp diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 6229e480..e328b55f 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -3,6 +3,7 @@ #include "arch/Serial.h" #include "arch/Timer.h" #include "boot/Init.h" +#include "memory/Heap.h" #include "memory/MemoryManager.h" #include "video/Framebuffer.h" @@ -101,6 +102,16 @@ extern "C" [[noreturn]] void _start() usize start = 0; + int* mem = (int*)kmalloc(sizeof(int)).release_value(); + *(volatile int*)mem = 6; + Serial::printf("Read %d from memory\n", *mem); + + mem = (int*)krealloc(mem, 60).release_value(); + + Serial::printf("Resized to %p\n", (void*)mem); + + kfree(mem); + while (1) { while ((Timer::ticks_ms() - start) < 20) { CPU::wait_for_interrupt(); } diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp new file mode 100644 index 00000000..59f4660d --- /dev/null +++ b/kernel/src/memory/Heap.cpp @@ -0,0 +1,331 @@ +#include "memory/Heap.h" +#include "arch/MMU.h" +#include "arch/Serial.h" +#include "memory/MemoryManager.h" +#include +#include + +static constexpr int BLOCK_USED = 1 << 0; +static constexpr int BLOCK_START_MEM = 1 << 1; +static constexpr int BLOCK_END_MEM = 1 << 2; + +static constexpr usize BLOCK_MAGIC = 0x6d616c6c6f63210a; // echo "malloc\!" | hexdump -C +static constexpr usize BLOCK_DEAD = 0xdeaddeaddeaddead; + +static constexpr usize MINIMUM_PAGES_PER_ALLOCATION = 4; + +struct HeapBlock +{ + usize req_size; + usize full_size; + int status; + HeapBlock* next; + HeapBlock* last; + usize magic; +}; + +static_assert(sizeof(HeapBlock) == 48UL); + +static HeapBlock* heap_start = nullptr; +static HeapBlock* heap_end = nullptr; + +static usize start_addr = 0xffffffff80000000; + +static Result allocate_pages( + usize count) // FIXME: Keep track of virtual address space usage. For now, since the address + // space is so huge, we can just start at a fairly large address and assume + // we'll never run into anything, but this will probably bite us in the future. +{ + void* ptr = (void*)TRY(MemoryManager::alloc_at(start_addr, count, MMU::ReadWrite | MMU::NoExecute)); + if (ptr) start_addr += (count * ARCH_PAGE_SIZE); + return (HeapBlock*)ptr; +} + +static Result release_pages(void* ptr, usize count) +{ + return MemoryManager::unmap_owned((u64)ptr, count); +} + +// If we're allocating a large amount of memory, map enough pages for it, but otherwise just use the default amount of +// pages. +static usize get_pages_for_allocation(usize bytes) +{ + usize pages = get_blocks_from_size(bytes, ARCH_PAGE_SIZE); + if (pages < MINIMUM_PAGES_PER_ALLOCATION) pages = MINIMUM_PAGES_PER_ALLOCATION; + return pages; +} + +static bool is_block_free(HeapBlock* block) +{ + return !(block->status & BLOCK_USED); +} + +static usize space_available(HeapBlock* block) +{ + check(!is_block_free(block)); + return block->full_size - block->req_size; +} + +static HeapBlock* get_heap_block_for_pointer(void* ptr) +{ + return (HeapBlock*)offset_ptr(ptr, -48); +} + +static void* get_pointer_from_heap_block(HeapBlock* block) +{ + return (void*)offset_ptr(block, 48); +} + +static usize get_fair_offset_to_split_at(HeapBlock* block, usize min) +{ + usize available = space_available(block); + + available -= min; // reserve at least min size for the new block. + + available -= (available / + 2); // reserve half of the rest for the new block, while still leaving another half for the old one. + + return available + block->req_size; +} + +static Result split(HeapBlock* block, usize size) +{ + usize available = space_available(block); // How much space can we steal from this block? + usize old_size = + block->full_size; // Save the old value of this variable since we are going to use it after modifying it + + if (available < (size + sizeof(HeapBlock))) return err; + + usize offset = get_fair_offset_to_split_at(block, size + sizeof(HeapBlock)); + block->full_size = offset; // shrink the old block to fit this offset + + HeapBlock* new_block = offset_ptr(block, offset + sizeof(HeapBlock)); + + new_block->magic = BLOCK_MAGIC; + new_block->status = (block->status & BLOCK_END_MEM) ? BLOCK_END_MEM : 0; + new_block->full_size = old_size - (offset + sizeof(HeapBlock)); + new_block->next = block->next; + new_block->last = block; + + block->status &= ~BLOCK_END_MEM; // this block is no longer the last block in this memory range + block->next = new_block; + + return new_block; +} + +static Result combine_forward(HeapBlock* block) +{ + HeapBlock* next = block->next; + if (next == heap_end) heap_end = block; + next->magic = BLOCK_DEAD; + + block->next = block->next->next; + if (block->next) block->next->last = block; + + if (next->status & BLOCK_END_MEM) + { + if (next->status & BLOCK_START_MEM) + { + TRY(release_pages(next, get_blocks_from_size(next->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE))); + return {}; + } + else + block->status |= BLOCK_END_MEM; + } + + block->full_size += next->full_size + sizeof(HeapBlock); + + return {}; +} + +static Result combine_backward(HeapBlock* block) +{ + HeapBlock* last = block->last; + if (block == heap_end) heap_end = last; + block->magic = BLOCK_DEAD; + + last->next = block->next; + if (last->next) last->next->last = last; + + if (block->status & BLOCK_END_MEM) + { + if (block->status & BLOCK_START_MEM) + { + TRY(release_pages(block, get_blocks_from_size(block->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE))); + return last; + } + else + last->status |= BLOCK_END_MEM; + } + + last->full_size += block->full_size + sizeof(HeapBlock); + + return last; +} + +Result kmalloc(usize size) +{ + if (!size) return (void*)BLOCK_MAGIC; + + size = align_up(size, 16UL); + + if (!heap_start) + { + usize pages = get_pages_for_allocation(size); + auto* block = TRY(allocate_pages(pages)); + + block->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); + block->magic = BLOCK_MAGIC; + block->status = BLOCK_START_MEM | BLOCK_END_MEM; + block->next = block->last = nullptr; + heap_start = block; + + if (!heap_end) heap_end = heap_start; + } + + HeapBlock* block = heap_start; + while (block) + { + // Trying to find a free block... + if (is_block_free(block)) + { + if (block->full_size < size) + { + block = block->next; // Let's not try to split this block, it's not big enough + continue; + } + break; // We found a free block that's big enough!! + } + auto rc = split(block, size); + if (rc.has_value()) + { + block = rc.release_value(); // We managed to get a free block from a larger used block!! + break; + } + block = block->next; + } + + if (!block) // No free blocks, let's allocate a new one + { + usize pages = get_pages_for_allocation(size); + block = TRY(allocate_pages(pages)); + + block->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); + block->magic = BLOCK_MAGIC; + block->status = BLOCK_START_MEM | BLOCK_END_MEM; + block->next = nullptr; + block->last = heap_end; + + heap_end = block; + } + + block->req_size = size; + block->status |= BLOCK_USED; + + return get_pointer_from_heap_block(block); +} + +Result kfree(void* ptr) +{ + if (ptr == (void*)BLOCK_MAGIC) return {}; // This pointer was returned from a call to malloc(0) + if (!ptr) return {}; + + HeapBlock* block = get_heap_block_for_pointer(ptr); + + if (block->magic != BLOCK_MAGIC) + { + if (block->magic == BLOCK_DEAD) + { + Serial::printf("ERROR: Attempt to free memory at %p, which was already freed\n", ptr); + } + else + Serial::printf("ERROR: Attempt to free memory at %p, which wasn't allocated with kmalloc\n", ptr); + + return err; + } + + if (is_block_free(block)) + { + Serial::printf("ERROR: Attempt to free memory at %p, which was already freed\n", ptr); + return err; + } + else + block->status &= ~BLOCK_USED; + + if (block->next && is_block_free(block->next)) + { + // The next block is also free, thus we can merge! + TRY(combine_forward(block)); + } + + if (block->last && is_block_free(block->last)) + { + // The last block is also free, thus we can merge! + block = TRY(combine_backward(block)); + } + + if ((block->status & BLOCK_START_MEM) && (block->status & BLOCK_END_MEM)) + { + if (block == heap_start) heap_start = block->next; + if (block == heap_end) heap_end = block->last; + if (block->last) block->last->next = block->next; + if (block->next) block->next->last = block->last; + TRY(release_pages(block, get_blocks_from_size(block->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE))); + } + + return {}; +} + +Result krealloc(void* ptr, usize size) +{ + if (!ptr) return kmalloc(size); + if (ptr == (void*)BLOCK_MAGIC) return kmalloc(size); + if (!size) + { + TRY(kfree(ptr)); + return (void*)BLOCK_MAGIC; + } + + HeapBlock* block = get_heap_block_for_pointer(ptr); + + if (block->magic != BLOCK_MAGIC) + { + if (block->magic == BLOCK_DEAD) + { + Serial::printf("ERROR: Attempt to realloc memory at %p, which was already freed\n", ptr); + } + else + Serial::printf("ERROR: Attempt to realloc memory at %p, which wasn't allocated with kmalloc\n", ptr); + + return err; + } + + size = align_up(size, 16UL); + + if (is_block_free(block)) + { + Serial::printf("ERROR: Attempt to realloc memory at %p, which was already freed\n", ptr); + return err; + } + + if (block->full_size >= size) + { + // This block is already large enough! + block->req_size = size; + return ptr; + } + + void* new_ptr = TRY(kmalloc(size)); + memcpy(new_ptr, ptr, block->req_size > size ? size : block->req_size); + TRY(kfree(ptr)); + + return new_ptr; +} + +Result kcalloc(usize nmemb, usize size) +{ + // FIXME: Check for overflows. + usize realsize = nmemb * size; + void* ptr = TRY(kmalloc(realsize)); + return memset(ptr, 0, realsize); +} \ No newline at end of file diff --git a/kernel/src/memory/Heap.h b/kernel/src/memory/Heap.h new file mode 100644 index 00000000..3bb4a3bf --- /dev/null +++ b/kernel/src/memory/Heap.h @@ -0,0 +1,7 @@ +#pragma once +#include + +Result kmalloc(usize size); +Result kcalloc(usize nmemb, usize size); +Result krealloc(void* ptr, usize size); +Result kfree(void* ptr); \ No newline at end of file From d54c882c63a96d6af6702bd79f053286a590a04d Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 15:48:08 +0100 Subject: [PATCH 066/407] Add new/delete-like functions but with Results --- kernel/src/main.cpp | 4 ++-- kernel/src/memory/Heap.h | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index e328b55f..7b3faf7c 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -102,7 +102,7 @@ extern "C" [[noreturn]] void _start() usize start = 0; - int* mem = (int*)kmalloc(sizeof(int)).release_value(); + int* mem = make().release_value(); *(volatile int*)mem = 6; Serial::printf("Read %d from memory\n", *mem); @@ -110,7 +110,7 @@ extern "C" [[noreturn]] void _start() Serial::printf("Resized to %p\n", (void*)mem); - kfree(mem); + destroy(mem).release_value(); while (1) { diff --git a/kernel/src/memory/Heap.h b/kernel/src/memory/Heap.h index 3bb4a3bf..b7bf53e9 100644 --- a/kernel/src/memory/Heap.h +++ b/kernel/src/memory/Heap.h @@ -1,7 +1,20 @@ #pragma once +#include #include Result kmalloc(usize size); Result kcalloc(usize nmemb, usize size); Result krealloc(void* ptr, usize size); -Result kfree(void* ptr); \ No newline at end of file +Result kfree(void* ptr); + +template Result make() +{ + void* ptr = TRY(kcalloc(1, sizeof(T))); + return new (ptr) T; +} + +template Result destroy(T* item) +{ + item->~T(); + return kfree(item); +} \ No newline at end of file From 29defdf54d0a4eaf41a7561a7b9c954a262a005a Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 16:33:54 +0100 Subject: [PATCH 067/407] Add a debug function to dump heap usage --- kernel/src/memory/Heap.cpp | 32 ++++++++++++++++++++++++++++++++ kernel/src/memory/Heap.h | 4 +++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 59f4660d..ac1b9bcd 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -328,4 +328,36 @@ Result kcalloc(usize nmemb, usize size) usize realsize = nmemb * size; void* ptr = TRY(kmalloc(realsize)); return memset(ptr, 0, realsize); +} + +void dump_heap_usage() +{ + Serial::println("-- Dumping usage stats for kernel heap:"); + if (!heap_start) + { + Serial::println("- Heap is not currently being used"); + return; + } + usize alloc_total = 0; + usize alloc_used = 0; + HeapBlock* block = heap_start; + while (block) + { + if (is_block_free(block)) + { + Serial::printf("- Available block, of size %zu\n", block->full_size); + alloc_total += block->full_size + sizeof(HeapBlock); + } + else + { + Serial::printf("- Used block, of size %zu, of which %zu bytes are being used\n", block->full_size, + block->req_size); + alloc_total += block->full_size + sizeof(HeapBlock); + alloc_used += block->req_size; + } + block = block->next; + } + + Serial::printf("-- Total memory allocated for heap: %zu bytes\n", alloc_total); + Serial::printf("-- Heap memory in use by the kernel: %zu bytes\n", alloc_used); } \ No newline at end of file diff --git a/kernel/src/memory/Heap.h b/kernel/src/memory/Heap.h index b7bf53e9..251e039c 100644 --- a/kernel/src/memory/Heap.h +++ b/kernel/src/memory/Heap.h @@ -17,4 +17,6 @@ template Result destroy(T* item) { item->~T(); return kfree(item); -} \ No newline at end of file +} + +void dump_heap_usage(); \ No newline at end of file From a58b60d0cfcb22282aa8d0dfd57ff33caa62cb9d Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 17:55:22 +0100 Subject: [PATCH 068/407] Add a framebuffer text renderer --- kernel/CMakeLists.txt | 1 + kernel/src/video/BuiltinFont.h | 262 +++++++++++++++++++++++++++++++ kernel/src/video/TextConsole.cpp | 162 +++++++++++++++++++ kernel/src/video/TextConsole.h | 16 ++ 4 files changed, 441 insertions(+) create mode 100644 kernel/src/video/BuiltinFont.h create mode 100644 kernel/src/video/TextConsole.cpp create mode 100644 kernel/src/video/TextConsole.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 5fe6a323..f65760a5 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES src/main.cpp src/video/Framebuffer.cpp + src/video/TextConsole.cpp src/memory/MemoryManager.cpp src/memory/Heap.cpp src/boot/Init.cpp diff --git a/kernel/src/video/BuiltinFont.h b/kernel/src/video/BuiltinFont.h new file mode 100644 index 00000000..a2a2e478 --- /dev/null +++ b/kernel/src/video/BuiltinFont.h @@ -0,0 +1,262 @@ +#pragma once +#include + +// FIXME: Load a font from disk/initrd. + +u8 font[] = {0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, /* 2 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 */ + 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 11 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 12 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 13 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 14 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 15 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 17 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 21 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 22 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 24 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 25 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 26 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 29 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 30 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32 */ + 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 33 */ + 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 34 */ + 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, /* 35 */ + 0x00, 0x00, 0x08, 0x08, 0x1e, 0x20, 0x20, 0x1c, 0x02, 0x02, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 36 */ + 0x00, 0x00, 0x00, 0x30, 0x49, 0x4a, 0x34, 0x08, 0x16, 0x29, 0x49, 0x06, 0x00, 0x00, 0x00, 0x00, /* 37 */ + 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x31, 0x49, 0x46, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, /* 38 */ + 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ + 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, /* 40 */ + 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, /* 41 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 */ + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 43 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 44 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 45 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 46 */ + 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, /* 47 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 48 */ + 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 49 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 50 */ + 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x1c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 51 */ + 0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* 52 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 53 */ + 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 54 */ + 0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 55 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 56 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* 57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 58 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 59 */ + 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, /* 60 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 61 */ + 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, /* 62 */ + 0x00, 0x00, 0x3c, 0x42, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 63 */ + 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4f, 0x51, 0x51, 0x51, 0x53, 0x4d, 0x40, 0x20, 0x1f, 0x00, 0x00, /* 64 */ + 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 65 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 66 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 67 */ + 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x00, /* 68 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 69 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 70 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x46, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 71 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 72 */ + 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 73 */ + 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 74 */ + 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 75 */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 76 */ + 0x00, 0x00, 0x00, 0x41, 0x63, 0x55, 0x49, 0x49, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 77 */ + 0x00, 0x00, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 78 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 79 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 80 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x04, 0x02, 0x00, 0x00, /* 81 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 82 */ + 0x00, 0x00, 0x00, 0x3e, 0x40, 0x40, 0x20, 0x18, 0x04, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 83 */ + 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 84 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 85 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 86 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x41, 0x49, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 87 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 88 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 89 */ + 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 90 */ + 0x00, 0x00, 0x1e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x00, 0x00, /* 91 */ + 0x00, 0x00, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* 92 */ + 0x00, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, 0x00, /* 93 */ + 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 94 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, /* 95 */ + 0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 96 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 97 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 98 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 99 */ + 0x00, 0x00, 0x02, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 100 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 101 */ + 0x00, 0x00, 0x0e, 0x10, 0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 102 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 103 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 104 */ + 0x00, 0x00, 0x08, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 105 */ + 0x00, 0x00, 0x04, 0x04, 0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x00, /* 106 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 107 */ + 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 108 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, /* 109 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 110 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 111 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, /* 112 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, /* 113 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, /* 114 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 115 */ + 0x00, 0x00, 0x00, 0x10, 0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 116 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 117 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 118 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 119 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, /* 120 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 121 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 122 */ + 0x00, 0x0e, 0x10, 0x10, 0x10, 0x10, 0x10, 0xe0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, /* 123 */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 124 */ + 0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, /* 125 */ + 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 126 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 127 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 129 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 130 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 131 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 132 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 133 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 134 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 135 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 136 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 137 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 138 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 139 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 140 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 141 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 142 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 143 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 144 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 145 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 146 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 147 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 148 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 149 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 150 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 151 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 152 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 153 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 154 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 155 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 156 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 157 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 158 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 159 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 160 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /* 161 */ + 0x00, 0x00, 0x08, 0x08, 0x1c, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 162 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 163 */ + 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x24, 0x24, 0x3c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* 164 */ + 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x3e, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 165 */ + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 166 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 167 */ + 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 168 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4d, 0x51, 0x51, 0x4d, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 169 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 170 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x12, 0x24, 0x48, 0x24, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, /* 171 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 172 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 173 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 174 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 175 */ + 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 176 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 177 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 178 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 179 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 180 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 181 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 182 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 183 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x30, 0x00, /* 184 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 185 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 186 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x09, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, /* 187 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 189 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 190 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x42, 0x3c, 0x00, /* 191 */ + 0x20, 0x10, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 192 */ + 0x04, 0x08, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 193 */ + 0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 194 */ + 0x32, 0x4c, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 195 */ + 0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 196 */ + 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 197 */ + 0x00, 0x00, 0x00, 0x0f, 0x14, 0x14, 0x24, 0x27, 0x3c, 0x44, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00, /* 198 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e, 0x08, 0x08, 0x30, 0x00, /* 199 */ + 0x20, 0x10, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 200 */ + 0x04, 0x08, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 201 */ + 0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 202 */ + 0x24, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 203 */ + 0x10, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 204 */ + 0x04, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 205 */ + 0x18, 0x24, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 206 */ + 0x22, 0x22, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 207 */ + 0x00, 0x00, 0x00, 0x3c, 0x22, 0x21, 0x21, 0x79, 0x21, 0x21, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 208 */ + 0x32, 0x4c, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 209 */ + 0x10, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 210 */ + 0x04, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 211 */ + 0x18, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 212 */ + 0x32, 0x4c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 213 */ + 0x24, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 214 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 215 */ + 0x00, 0x00, 0x02, 0x3c, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 216 */ + 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 217 */ + 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 218 */ + 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 219 */ + 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 220 */ + 0x04, 0x08, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 221 */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 222 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x44, 0x4c, 0x42, 0x42, 0x42, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* 223 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 224 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 225 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 226 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 227 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 228 */ + 0x18, 0x24, 0x24, 0x18, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 229 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09, 0x39, 0x4f, 0x48, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, /* 230 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, /* 231 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 232 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 233 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 234 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 235 */ + 0x00, 0x00, 0x10, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 236 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 237 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 238 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 239 */ + 0x00, 0x09, 0x06, 0x1a, 0x01, 0x1d, 0x23, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 240 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 241 */ + 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 242 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 243 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 244 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 245 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 246 */ + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 247 */ + 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 248 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 249 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 250 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 251 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 252 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 253 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x00, /* 254 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, + /* 255 */}; \ No newline at end of file diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp new file mode 100644 index 00000000..6d30e557 --- /dev/null +++ b/kernel/src/video/TextConsole.cpp @@ -0,0 +1,162 @@ +#include "video/TextConsole.h" +#include "boot/bootboot.h" +#include "video/Framebuffer.h" +#include +#include + +extern BOOTBOOT bootboot; + +#include "video/BuiltinFont.h" + +static constexpr u32 BLACK = 0xff000000; +static constexpr u32 WHITE = 0xffffffff; + +static u32 g_background_color = BLACK; +static u32 g_foreground_color = WHITE; + +static constexpr u32 FONT_HEIGHT = 16; +static constexpr u32 FONT_WIDTH = 8; + +static u32 g_x_position = 0; +static u32 g_y_position = 0; + +static void putchar_at(char c, u32 x, u32 y) +{ + u8* glyph = &font[c * 16]; + for (u32 i = 0; i < FONT_HEIGHT; i++) + { + for (u32 j = 0; j < FONT_WIDTH; j++) + { + volatile u8 mask = *glyph; + if (mask & (0b10000000 >> j)) Framebuffer::pixel(x + j, y + i, g_foreground_color); + else + Framebuffer::pixel(x + j, y + i, g_background_color); + } + glyph++; + } +} + +static void erase_current_line() +{ + Framebuffer::rect(0, g_y_position, Framebuffer::width(), FONT_HEIGHT, BLACK); +} + +static void scroll() +{ + memcpy(Framebuffer::ptr(), Framebuffer::ptr() + (Framebuffer::scanline() * FONT_HEIGHT), + Framebuffer::size() - (Framebuffer::scanline() * FONT_HEIGHT)); + g_y_position -= FONT_HEIGHT; + erase_current_line(); +} + +static bool should_scroll() +{ + return (g_y_position + FONT_HEIGHT) >= Framebuffer::height(); +} + +static void next_line() +{ + g_x_position = 0; + g_y_position += FONT_HEIGHT; +} + +static void next_char() +{ + g_x_position += FONT_WIDTH; +} + +static void prev_char() +{ + g_x_position -= FONT_WIDTH; +} + +static void erase_current_char() +{ + Framebuffer::rect(g_x_position, g_y_position, FONT_WIDTH, FONT_HEIGHT, BLACK); +} + +static bool at_end_of_screen() +{ + return (g_x_position + FONT_WIDTH) > Framebuffer::width(); +} + +namespace TextConsole +{ + void putchar(char c) + { + switch (c) + { + case '\n': { + next_line(); + if (should_scroll()) scroll(); + break; + } + case '\r': g_x_position = 0; break; + case '\b': + if (g_x_position != 0) + { + prev_char(); + erase_current_char(); + } + break; + default: { + putchar_at(c, g_x_position, g_y_position); + next_char(); + if (at_end_of_screen()) + { + next_line(); + if (should_scroll()) scroll(); + } + break; + } + } + } + + void set_foreground(u32 color) + { + g_foreground_color = color; + } + + void set_background(u32 color) + { + g_background_color = color; + } + + void move_to(u32 x, u32 y) + { + g_x_position = x; + g_y_position = y; + } + + void clear() + { + move_to(0, 0); + Framebuffer::rect(0, 0, Framebuffer::width(), Framebuffer::height(), BLACK); + } + + void print(const char* str) + { + while (*str) putchar(*str++); + } + + void println(const char* str) + { + print(str); + putchar('\n'); + } + + Result printf(const char* format, ...) + { + va_list ap; + va_start(ap, format); + auto rc = cstyle_format( + format, + [](char c, void*) -> Result { + putchar(c); + return {}; + }, + nullptr, ap); + va_end(ap); + return rc; + } +} \ No newline at end of file diff --git a/kernel/src/video/TextConsole.h b/kernel/src/video/TextConsole.h new file mode 100644 index 00000000..21e6de6b --- /dev/null +++ b/kernel/src/video/TextConsole.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include +#include + +namespace TextConsole +{ + void clear(); + void putchar(char c); + void set_foreground(u32 color); + void set_background(u32 color); + void move_to(u32 x, u32 y); + void print(const char* str); + void println(const char* str); + Result printf(const char* format, ...) _format(1, 2); +} \ No newline at end of file From 35b7194fb71149141c2798430a37b482aee4707e Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 17:56:07 +0100 Subject: [PATCH 069/407] Move initialization into an init() function returning Result so we can use TRY And remove a lot of testing code as well. --- kernel/src/main.cpp | 96 +++++++++++---------------------------------- 1 file changed, 22 insertions(+), 74 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 7b3faf7c..4aa3eacd 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,94 +5,37 @@ #include "boot/Init.h" #include "memory/Heap.h" #include "memory/MemoryManager.h" -#include "video/Framebuffer.h" +#include "video/TextConsole.h" -extern u8 fb[1]; - -extern "C" [[noreturn]] void _start() +Result init() { - Init::check_magic(); - Init::early_init(); - Serial::println("Hello, world!"); Serial::printf("Current platform: %s\n", CPU::platform_string()); - Framebuffer::rect(0, 0, 200, 200, 0xFF00FF00); - - auto cpu_name_or_error = CPU::identify(); - - Serial::println(cpu_name_or_error.has_error() ? "Unable to determine CPU name" : cpu_name_or_error.release_value()); - - Serial::println(MMU::get_physical((u64)fb).has_error() ? "fb is not mapped" : "fb is mapped!!"); + Serial::println(TRY(CPU::identify())); const u64 address = 0xfffffffff8000000; Serial::printf("Mapping address 0x%lx\n", address); - u64 physical = MemoryManager::alloc_frame().release_value(); + TRY(MemoryManager::alloc_at(address, 1, MMU::ReadWrite)); - Serial::printf("Allocated physical frame %#lx\n", physical); + TRY(MMU::remap(address, MMU::ReadWrite | MMU::User)); - auto rc = MMU::map(address, physical, MMU::ReadWrite); - bool success = !rc.has_error(); - - int flags; - volatile u8* ptr; - - if (success) Serial::println("Mapped page :)"); - else - { - Serial::println("Failed to map page"); - CPU::efficient_halt(); - } - - if (MMU::get_physical(address).release_value() == physical) Serial::println("Mapping is active ;)"); - else - { - Serial::println("Mapping is not active"); - CPU::efficient_halt(); - } - - flags = MMU::get_flags(address).release_value(); - - if (flags & MMU::ReadWrite) Serial::println("Mapping is writable"); - if (flags & MMU::User) Serial::println("Mapping is user accessible"); - - auto rrc = MMU::remap(address, MMU::ReadWrite | MMU::User); - if (rrc.has_error()) - { - Serial::println("Failed to change flags of mapping"); - CPU::efficient_halt(); - } - - flags = MMU::get_flags(address).release_value(); + int flags = TRY(MMU::get_flags(address)); if (flags & MMU::ReadWrite) Serial::println("Mapping is now writable"); if (flags & MMU::User) Serial::println("Mapping is now user accessible"); - ptr = (volatile u8*)address; + u64 old = TRY(MMU::unmap(address)); - *ptr = 8; + Serial::printf("Unmapped page, was pointing to %#lx\n", old); - Serial::println("Can write to pointer"); + TextConsole::set_foreground(0xff000055); + TextConsole::set_background(0xff88ff00); - auto urc = MMU::unmap(address); - if (urc.has_error()) - { - Serial::println("Failed to unmap page"); - CPU::efficient_halt(); - } - - Serial::printf("Unmapped page, was pointing to %#lx\n", urc.value()); - - if (urc.release_value() != physical) - { - Serial::println("unmap returned a different address than the one we mapped"); - CPU::efficient_halt(); - } - - Serial::println("Successfully unmapped address"); + TextConsole::printf("Hello from Moon for the %s architecture!", CPU::platform_string()); Timer::init(); @@ -102,15 +45,11 @@ extern "C" [[noreturn]] void _start() usize start = 0; - int* mem = make().release_value(); + int* mem = TRY(make()); *(volatile int*)mem = 6; Serial::printf("Read %d from memory\n", *mem); - mem = (int*)krealloc(mem, 60).release_value(); - - Serial::printf("Resized to %p\n", (void*)mem); - - destroy(mem).release_value(); + TRY(destroy(mem)); while (1) { @@ -119,5 +58,14 @@ extern "C" [[noreturn]] void _start() Serial::printf("%8zu milliseconds have passed!\n", start); } + return {}; +} + +extern "C" [[noreturn]] void _start() +{ + Init::check_magic(); + Init::early_init(); + auto rc = init(); + rc.release_value(); CPU::efficient_halt(); } \ No newline at end of file From ff952fa2e43de1c194ed9ecf562939ee106eddd0 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 18:04:29 +0100 Subject: [PATCH 070/407] Confirm alignment when calculating an offset to split at --- kernel/src/memory/Heap.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index ac1b9bcd..74866481 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -85,6 +85,9 @@ static usize get_fair_offset_to_split_at(HeapBlock* block, usize min) available -= (available / 2); // reserve half of the rest for the new block, while still leaving another half for the old one. + check(is_aligned(available, + 16UL)); // If necessary, we can just align it. This is more of a sanity check than a requirement. + return available + block->req_size; } From 285c3cc411d7211a2875663285dae5eec5415a2d Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 18:28:16 +0100 Subject: [PATCH 071/407] Add Luna sources to list of sources to be formatted --- tools/check-formatting.sh | 1 + tools/run-clang-format.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/check-formatting.sh b/tools/check-formatting.sh index 366c5748..bea7f2a8 100755 --- a/tools/check-formatting.sh +++ b/tools/check-formatting.sh @@ -5,6 +5,7 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm")) +SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt")) ALL_OK=1 diff --git a/tools/run-clang-format.sh b/tools/run-clang-format.sh index 43963d0f..2e69fa67 100755 --- a/tools/run-clang-format.sh +++ b/tools/run-clang-format.sh @@ -6,6 +6,7 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm")) +SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt")) for f in ${SOURCES[@]} do From 1f2901d41a2d8f8ca8afd620316e6053078634b5 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 18:28:46 +0100 Subject: [PATCH 072/407] Add convenience script to replace stdint.h types with Types.h types --- tools/replace-stdint.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100755 tools/replace-stdint.sh diff --git a/tools/replace-stdint.sh b/tools/replace-stdint.sh new file mode 100755 index 00000000..f4bce2fd --- /dev/null +++ b/tools/replace-stdint.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -e +source $(dirname $0)/env.sh + +cd $LUNA_ROOT + +SOURCES=($(find kernel/src -type f | grep -v "\.asm" | grep -v "bootboot.h")) +SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt" | grep -v "Types.h" | grep -v "PlacementNew.h")) + +for f in ${SOURCES[@]} +do + sed -i 's/uint8_t/u8/g' $f + sed -i 's/uint16_t/u16/g' $f + sed -i 's/uint32_t/u32/g' $f + sed -i 's/uint64_t/u64/g' $f + + sed -i 's/int8_t/i8/g' $f + sed -i 's/int16_t/i16/g' $f + sed -i 's/int32_t/i32/g' $f + sed -i 's/int64_t/i64/g' $f + + sed -i 's/size_t/usize/g' $f + sed -i 's/ssize_t/isize/g' $f +done \ No newline at end of file From 459e1ed6533df4674c7c6b611799e6f169725a7c Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 18:29:23 +0100 Subject: [PATCH 073/407] luna/String.h: Convert to Types.h --- luna/String.cpp | 14 +++++++------- luna/String.h | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/luna/String.cpp b/luna/String.cpp index 2b2113b4..abada229 100644 --- a/luna/String.cpp +++ b/luna/String.cpp @@ -2,19 +2,19 @@ extern "C" { - void* memcpy(void* dest, const void* src, size_t n) + void* memcpy(void* dest, const void* src, usize n) { - for (size_t i = 0; i < n; ++i) { *((u8*)dest + i) = *((const u8*)src + i); } + for (usize i = 0; i < n; ++i) { *((u8*)dest + i) = *((const u8*)src + i); } return dest; } - void* memset(void* buf, int c, size_t n) + void* memset(void* buf, int c, usize n) { - for (size_t i = 0; i < n; ++i) { *((u8*)buf + i) = (u8)c; } + for (usize i = 0; i < n; ++i) { *((u8*)buf + i) = (u8)c; } return buf; } - int memcmp(const void* a, const void* b, size_t n) + int memcmp(const void* a, const void* b, usize n) { if (!n) return 0; const u8* ap = (const u8*)a; @@ -27,7 +27,7 @@ extern "C" return *ap - *bp; } - void* memmove(void* dest, const void* src, size_t n) + void* memmove(void* dest, const void* src, usize n) { if (dest == src) return dest; if (dest > src) @@ -37,7 +37,7 @@ extern "C" return dest; } - size_t strlen(const char* str) + usize strlen(const char* str) { const char* i = str; for (; *i; ++i) diff --git a/luna/String.h b/luna/String.h index b11961f6..1e2b9a81 100644 --- a/luna/String.h +++ b/luna/String.h @@ -3,9 +3,9 @@ extern "C" { - void* memcpy(void* dest, const void* src, size_t n); - void* memset(void* buf, int c, size_t n); - int memcmp(const void* a, const void* b, size_t n); - void* memmove(void* dest, const void* src, size_t n); - size_t strlen(const char* str); + void* memcpy(void* dest, const void* src, usize n); + void* memset(void* buf, int c, usize n); + int memcmp(const void* a, const void* b, usize n); + void* memmove(void* dest, const void* src, usize n); + usize strlen(const char* str); } \ No newline at end of file From 43e26e583ca92524fd5993cc20b6d84fb9da5d8d Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 18:30:40 +0100 Subject: [PATCH 074/407] Calculate the boot timestamp in UNIX time for further usage --- kernel/src/arch/Timer.cpp | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index c06b003c..e9694a2c 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -1,8 +1,58 @@ #include "arch/Timer.h" +#include "arch/Serial.h" +#include "boot/bootboot.h" +#include static u64 timer_ticks = 0; static u64 boot_timestamp; +static int isleap(int year) +{ + return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); +} + +static int make_yday(int year, int month) +{ + static const short int upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + int yd; + + yd = upto[month - 1]; + if (month > 2 && isleap(year)) yd++; + return yd; +} + +// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16 +static u64 broken_down_to_unix(u64 year, u64 yday, u64 hour, u64 min, u64 sec) +{ + return sec + min * 60 + hour * 3600 + yday * 86400 + (year - 70) * 31536000 + ((year - 69) / 4) * 86400 - + ((year - 1) / 100) * 86400 + ((year + 299) / 400) * 86400; +} + +// The bootloader encodes the date and time in Binary-Coded Decimal (BCD), which represents decimal digits using +// hexadecimal digits. For example, BCD 0x22 is 22 in decimal. +// https://gitlab.com/bztsrc/bootboot/-/blob/master/bootboot_spec_1st_ed.pdf, page 15. +static int bcd_number_to_decimal(int num) +{ + return ((num >> 4) * 10) + (num & 0xf); +} + +static u64 bootloader_time_to_unix(u8 boottime[8]) +{ + int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); + int month = bcd_number_to_decimal(boottime[2]); + int day = bcd_number_to_decimal(boottime[3]); + int hour = bcd_number_to_decimal(boottime[4]); + int minute = bcd_number_to_decimal(boottime[5]); + int second = bcd_number_to_decimal(boottime[6]); + // "The last byte can store 1/100th second precision, but in lack of support on most platforms, it is 0x00". + // Therefore, let's not rely on it. + Serial::printf("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC\n", day, month, year, hour, minute, second) + .release_value(); + return broken_down_to_unix(year - 1900, make_yday(year, month) + (day - 1), hour, minute, second); +} + +extern BOOTBOOT bootboot; + namespace Timer { void tick() @@ -75,6 +125,7 @@ namespace Timer void init() { + boot_timestamp = bootloader_time_to_unix(bootboot.datetime); arch_init(); } } \ No newline at end of file From 2df0bc4238bce80b25c8724c05a73f97cab646a5 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 18:31:55 +0100 Subject: [PATCH 075/407] Convert one tiny type to Types.h in Format.cpp --- luna/Format.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luna/Format.cpp b/luna/Format.cpp index 6f3a2e56..7d086876 100644 --- a/luna/Format.cpp +++ b/luna/Format.cpp @@ -170,7 +170,7 @@ static void parse_length(const char** format, flags_t& flags) (*format)++; break; case 'z': - flags |= (sizeof(size_t) == sizeof(long)) ? FLAG_LONG : FLAG_LONG_LONG; + flags |= (sizeof(usize) == sizeof(long)) ? FLAG_LONG : FLAG_LONG_LONG; (*format)++; break; default: break; From f982152caa5b11fd292f76f0cb2069e9e3079613 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 18:54:39 +0100 Subject: [PATCH 076/407] Add a script to manually check files with stdint.h types --- tools/check-stdint.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100755 tools/check-stdint.sh diff --git a/tools/check-stdint.sh b/tools/check-stdint.sh new file mode 100755 index 00000000..66dc1f1f --- /dev/null +++ b/tools/check-stdint.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -e +source $(dirname $0)/env.sh + +cd $LUNA_ROOT + +SOURCES=($(find kernel/src -type f | grep -v "\.asm" | grep -v "bootboot.h")) +SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt" | grep -v "Types.h" | grep -v "PlacementNew.h")) + +SUCCESS=1 + +lint-file() +{ + info="$(grep -Hnow $1 $3 | awk -v wrong="$1" -v right="$2" 'BEGIN { FS=":" }{ print $1 ":" $2 ": " wrong " -> " right }')" + if ! [ "$info" = "" ] + then + echo "$info" + SUCCESS=0 + fi +} + +for f in ${SOURCES[@]} +do + lint-file uint8_t u8 $f + lint-file uint16_t u16 $f + lint-file uint32_t u32 $f + lint-file uint64_t u64 $f + + lint-file int8_t i8 $f + lint-file int16_t i16 $f + lint-file int32_t i32 $f + lint-file int64_t i64 $f + + lint-file size_t usize $f + lint-file ssize_t isize $f +done + +if [ "$SUCCESS" = "0" ] +then +exit 1 +fi \ No newline at end of file From 46cad140523b075cbba52d9bf39aa643bcf35cfb Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 20 Nov 2022 18:57:22 +0100 Subject: [PATCH 077/407] Print "All files OK" when all files are using correct types --- tools/check-stdint.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/check-stdint.sh b/tools/check-stdint.sh index 66dc1f1f..47db8013 100755 --- a/tools/check-stdint.sh +++ b/tools/check-stdint.sh @@ -39,4 +39,6 @@ done if [ "$SUCCESS" = "0" ] then exit 1 +else +echo All files OK fi \ No newline at end of file From 3b2dc5db55ef8d1faf11566a847dd7ac6fdc70f6 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 23 Nov 2022 17:22:16 +0100 Subject: [PATCH 078/407] PlacementNew.h: Use Types.h --- luna/PlacementNew.h | 6 +++--- tools/check-stdint.sh | 2 +- tools/replace-stdint.sh | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/luna/PlacementNew.h b/luna/PlacementNew.h index 1e6afcd1..4ecf821c 100644 --- a/luna/PlacementNew.h +++ b/luna/PlacementNew.h @@ -1,11 +1,11 @@ #pragma once -#include +#include -inline void* operator new(size_t, void* p) noexcept +inline void* operator new(usize, void* p) noexcept { return p; } -inline void* operator new[](size_t, void* p) noexcept +inline void* operator new[](usize, void* p) noexcept { return p; } diff --git a/tools/check-stdint.sh b/tools/check-stdint.sh index 47db8013..bf78b6d2 100755 --- a/tools/check-stdint.sh +++ b/tools/check-stdint.sh @@ -6,7 +6,7 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm" | grep -v "bootboot.h")) -SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt" | grep -v "Types.h" | grep -v "PlacementNew.h")) +SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt" | grep -v "Types.h")) SUCCESS=1 diff --git a/tools/replace-stdint.sh b/tools/replace-stdint.sh index f4bce2fd..2fa4d5a2 100755 --- a/tools/replace-stdint.sh +++ b/tools/replace-stdint.sh @@ -6,7 +6,7 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm" | grep -v "bootboot.h")) -SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt" | grep -v "Types.h" | grep -v "PlacementNew.h")) +SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt" | grep -v "Types.h")) for f in ${SOURCES[@]} do From 88f588a0c5d8180be6d11f71856f40da9c941a6f Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 23 Nov 2022 18:00:09 +0100 Subject: [PATCH 079/407] Make ARCH_TIMER_FREQ less frequent so it is more accurate (I hope) --- kernel/src/arch/x86_64/Timer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/arch/x86_64/Timer.cpp b/kernel/src/arch/x86_64/Timer.cpp index c5c693f8..ef6aa72b 100644 --- a/kernel/src/arch/x86_64/Timer.cpp +++ b/kernel/src/arch/x86_64/Timer.cpp @@ -4,7 +4,7 @@ #define PIT_CHANNEL_0 0x40 const u64 base_frequency = 1193182; -const usize ARCH_TIMER_FREQ = 10; +const usize ARCH_TIMER_FREQ = 5; void Timer::arch_init() { From 9934719f6bb9d382cc1e2e18e296a4b6a5f2aa2b Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 23 Nov 2022 18:05:01 +0100 Subject: [PATCH 080/407] Use a more reliable signed 64-bit type than "long" --- luna/Types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luna/Types.h b/luna/Types.h index a872a576..0abcefa7 100644 --- a/luna/Types.h +++ b/luna/Types.h @@ -10,7 +10,7 @@ typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; typedef size_t usize; -typedef long isize; +typedef int64_t isize; static_assert(sizeof(u8) == 1UL); static_assert(sizeof(u16) == 2UL); From 7230eceb4dd4c378306ec5e49824fb1ded378da1 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 23 Nov 2022 18:58:39 +0100 Subject: [PATCH 081/407] x86_64/Timer: Show explanatory message on static assertion fail --- kernel/src/arch/x86_64/Timer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/arch/x86_64/Timer.cpp b/kernel/src/arch/x86_64/Timer.cpp index ef6aa72b..9add861b 100644 --- a/kernel/src/arch/x86_64/Timer.cpp +++ b/kernel/src/arch/x86_64/Timer.cpp @@ -9,7 +9,7 @@ const usize ARCH_TIMER_FREQ = 5; void Timer::arch_init() { constexpr u16 divisor = (u16)(base_frequency / (ARCH_TIMER_FREQ * 1000)); - static_assert(divisor >= 100); + static_assert(divisor >= 100, "ARCH_TIMER_FREQ is too high"); IO::outb(PIT_CHANNEL_0, (u8)(divisor & 0xFF)); IO::outb(0x80, 0); // short delay IO::outb(PIT_CHANNEL_0, (u8)((divisor & 0xFF00) >> 8)); From 88681bdc748bca89a13d27be063f5e7d9a5c0503 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 23 Nov 2022 19:01:28 +0100 Subject: [PATCH 082/407] Default to ninja --- tools/env.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/env.sh b/tools/env.sh index 7b21c968..daf02519 100755 --- a/tools/env.sh +++ b/tools/env.sh @@ -7,13 +7,13 @@ export PATH=$LUNA_ROOT/toolchain/x86-64-luna/bin:$LUNA_ROOT/toolchain/dist:$PATH export ARCH=${ARCH:-x86_64} -if [ "$USE_NINJA" = "1" ] +if [ "$USE_MAKE" = "1" ] then -export BUILD=ninja -export CMAKE_GEN=Ninja -else export BUILD=make export CMAKE_GEN="Unix Makefiles" +else +export BUILD=ninja +export CMAKE_GEN="Ninja" fi export BUILD_DIR=$LUNA_ROOT/build/$BUILD-$ARCH \ No newline at end of file From 82893fa3a44c554fc042d50b3f98ae4cf88a7fdb Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 23 Nov 2022 19:34:04 +0100 Subject: [PATCH 083/407] Introduce a kernel_yield function to use once a scheduler is implemented --- kernel/src/arch/CPU.h | 4 ++- kernel/src/arch/x86_64/CPU.asm | 46 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index daad9bd0..1558551a 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -18,4 +18,6 @@ namespace CPU void enable_interrupts(); void disable_interrupts(); void wait_for_interrupt(); -} \ No newline at end of file +} + +extern "C" void kernel_yield(); \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index c5b37810..2ecc7f73 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -48,6 +48,51 @@ load_tr: ltr ax ret +global switch_task +switch_task: + cli +.loop: + hlt + jmp .loop + +global kernel_yield +kernel_yield: + mov rdi, [rsp] ; return address is now in RDI + mov rcx, rsp ; save current RSP + add rcx, 8 ; skip over the return address + + mov eax, ss + push rax ; SS + push rcx ; RSP + pushfq ; RFLAGS + mov eax, cs + push rax ; CS + push rdi ; RIP + + ; ISR and error code + push 0 + push 0 + + push 0 ; RAX + push rbx ; Preserve RBX + push 0 ; RCX + push 0 ; RDX + push 0 ; RSI + push 0 ; RDI + push rbp ; Preserve RBP + push 0 ; R8 + push 0 ; R9 + push 0 ; R10 + push 0 ; R11 + push r12 ; Preserve R12 + push r13 ; Preserve R13 + push r14 ; Preserve R14 + push r15 ; Preserve R15 + + mov rdi, rsp + call switch_task + jmp _asm_interrupt_exit + %macro ISR 1 global _isr%1 _isr%1: @@ -97,6 +142,7 @@ _asm_interrupt_entry: mov rdi, rsp call arch_interrupt_entry +_asm_interrupt_exit: pop r15 pop r14 pop r13 From 1ed51d11cb22f6eb31163c4d34c335e99299b554 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 23 Nov 2022 19:37:25 +0100 Subject: [PATCH 084/407] Do not push unused values --- kernel/src/arch/x86_64/CPU.asm | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 2ecc7f73..59f4d68a 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -69,21 +69,16 @@ kernel_yield: push rax ; CS push rdi ; RIP - ; ISR and error code - push 0 - push 0 + sub rsp, 24 - push 0 ; RAX push rbx ; Preserve RBX - push 0 ; RCX - push 0 ; RDX - push 0 ; RSI - push 0 ; RDI + + sub rsp, 32 + push rbp ; Preserve RBP - push 0 ; R8 - push 0 ; R9 - push 0 ; R10 - push 0 ; R11 + + sub rsp, 32 + push r12 ; Preserve R12 push r13 ; Preserve R13 push r14 ; Preserve R14 From 552186ad51ef68589b96bb32695775a7b6cc90c2 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 12:36:21 +0100 Subject: [PATCH 085/407] Add string_format and vstring_format --- luna/Format.cpp | 39 +++++++++++++++++++++++++++++++++++++++ luna/Format.h | 4 +++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/luna/Format.cpp b/luna/Format.cpp index 7d086876..f3b1c62a 100644 --- a/luna/Format.cpp +++ b/luna/Format.cpp @@ -467,4 +467,43 @@ Result cstyle_format(const char* format, callback_t callback, void* arg, } return state.count; +} + +struct StringFormatInfo +{ + char* buffer; + size_t remaining; +}; + +Result vstring_format(char* buf, size_t max, const char* format, va_list ap) +{ + StringFormatInfo info = {.buffer = buf, .remaining = max - 1}; + + usize result = TRY(cstyle_format( + format, + [](char c, void* arg) -> Result { + StringFormatInfo* info_arg = (StringFormatInfo*)arg; + if (!info_arg->remaining) return {}; + *(info_arg->buffer) = c; + info_arg->buffer++; + info_arg->remaining--; + return {}; + }, + &info, ap)); + + *(info.buffer) = 0; + + return result; +} + +Result string_format(char* buf, size_t max, const char* format, ...) +{ + va_list ap; + va_start(ap, format); + + usize result = TRY(vstring_format(buf, max, format, ap)); + + va_end(ap); + + return result; } \ No newline at end of file diff --git a/luna/Format.h b/luna/Format.h index 1d06050e..3ad779f2 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -5,4 +5,6 @@ typedef Result (*callback_t)(char, void*); -Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); \ No newline at end of file +Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); +Result vstring_format(char* buf, size_t max, const char* format, va_list ap); +Result string_format(char* buf, size_t max, const char* format, ...); \ No newline at end of file From f1756e6f586e020fba23b32d40f5cab111fcd03f Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 12:42:11 +0100 Subject: [PATCH 086/407] Add unit formatting --- kernel/src/main.cpp | 9 +++++++++ luna/CMakeLists.txt | 1 + luna/Units.cpp | 17 +++++++++++++++++ luna/Units.h | 4 ++++ 4 files changed, 31 insertions(+) create mode 100644 luna/Units.cpp create mode 100644 luna/Units.h diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 4aa3eacd..24b3bcd0 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -6,6 +6,7 @@ #include "memory/Heap.h" #include "memory/MemoryManager.h" #include "video/TextConsole.h" +#include Result init() { @@ -51,6 +52,14 @@ Result init() TRY(destroy(mem)); + char buffer[64]; + to_dynamic_unit(MemoryManager::free(), buffer, sizeof(buffer)); + Serial::printf("Free memory: %s\n", buffer); + to_dynamic_unit(MemoryManager::used(), buffer, sizeof(buffer)); + Serial::printf("Used memory: %s\n", buffer); + to_dynamic_unit(MemoryManager::reserved(), buffer, sizeof(buffer)); + Serial::printf("Reserved memory: %s\n", buffer); + while (1) { while ((Timer::ticks_ms() - start) < 20) { CPU::wait_for_interrupt(); } diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 7481c08b..ee20a2ce 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -2,6 +2,7 @@ set(FREESTANDING_SOURCES Format.cpp NumberParsing.cpp String.cpp + Units.cpp ) set(SOURCES diff --git a/luna/Units.cpp b/luna/Units.cpp new file mode 100644 index 00000000..98eb4e70 --- /dev/null +++ b/luna/Units.cpp @@ -0,0 +1,17 @@ +#include +#include +#include + +Result to_dynamic_unit(usize value, char* buffer, size_t max) +{ + if (value < 1024) { return string_format(buffer, max, "%u bytes", value); } + + const char* unit_prefixes = "KMGTPE"; + for (int i = 40; i >= 0 && value > (0xfffccccccccccccUL >> i); i -= 10) + { + value >>= 10; + unit_prefixes++; + } + + return string_format(buffer, max, "%u.%u %ciB", value / 1024, (value % 1024) / 103, *unit_prefixes); +} \ No newline at end of file diff --git a/luna/Units.h b/luna/Units.h new file mode 100644 index 00000000..c12aac63 --- /dev/null +++ b/luna/Units.h @@ -0,0 +1,4 @@ +#pragma once +#include + +Result to_dynamic_unit(usize value, char* buffer, usize max); \ No newline at end of file From 9f5fb547f7c26a4bc357e876987174b7b2c8384c Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 13:29:28 +0100 Subject: [PATCH 087/407] Add logging system :) --- kernel/CMakeLists.txt | 1 + kernel/src/Log.cpp | 115 +++++++++++++++++++++++++++++++ kernel/src/Log.h | 29 ++++++++ kernel/src/boot/Init.cpp | 6 +- kernel/src/main.cpp | 17 +++-- kernel/src/video/TextConsole.cpp | 10 +++ kernel/src/video/TextConsole.h | 2 + 7 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 kernel/src/Log.cpp create mode 100644 kernel/src/Log.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index f65760a5..e23e42fd 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,5 +1,6 @@ set(SOURCES src/main.cpp + src/Log.cpp src/video/Framebuffer.cpp src/video/TextConsole.cpp src/memory/MemoryManager.cpp diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp new file mode 100644 index 00000000..1a7c34c9 --- /dev/null +++ b/kernel/src/Log.cpp @@ -0,0 +1,115 @@ +#include "Log.h" +#include "arch/Serial.h" +#include "arch/Timer.h" +#include "video/TextConsole.h" +#include + +static bool g_debug_enabled = true; +static bool g_serial_enabled = true; +static bool g_text_console_enabled = false; + +static constexpr u32 BLACK = 0xff000000; +static constexpr u32 WHITE = 0xffffffff; +static constexpr u32 YELLOW = 0xffffff00; +static constexpr u32 RED = 0xffff0000; + +static Result log_serial(LogLevel, const char* format, va_list origin) +{ + va_list ap; + va_copy(ap, origin); + + TRY(Serial::printf("[%6zu.%.6zu] ", Timer::ticks(), Timer::ticks_us() - (Timer::ticks() * 1000000))); + + TRY(cstyle_format( + format, + [](char c, void*) -> Result { + Serial::putchar(c); + return {}; + }, + nullptr, ap)); + + Serial::putchar('\n'); + + va_end(ap); + + return {}; +} + +static Result log_text_console(LogLevel level, const char* format, va_list origin) +{ + va_list ap; + va_copy(ap, origin); + + u32 original_foreground = TextConsole::foreground(); + u32 original_background = TextConsole::background(); + + TextConsole::set_background(BLACK); + + if (level == LogLevel::Warn) TextConsole::set_foreground(YELLOW); + else if (level == LogLevel::Error) + TextConsole::set_foreground(RED); + else + TextConsole::set_foreground(WHITE); + + TRY(cstyle_format( + format, + [](char c, void*) -> Result { + TextConsole::putchar(c); + return {}; + }, + nullptr, ap)); + + TextConsole::putchar('\n'); + + TextConsole::set_background(original_background); + + TextConsole::set_foreground(original_foreground); + + va_end(ap); + + return {}; +} + +Result vlog(LogLevel level, const char* format, va_list ap) +{ + if (!g_debug_enabled && level == LogLevel::Debug) return {}; + + if (g_serial_enabled) TRY(log_serial(level, format, ap)); + if (g_text_console_enabled) TRY(log_text_console(level, format, ap)); + + return {}; +} + +Result log(LogLevel level, const char* format, ...) +{ + va_list ap; + va_start(ap, format); + + TRY(vlog(level, format, ap)); + + va_end(ap); + + return {}; +} + +void setup_log(bool enable_debug, bool enable_serial, bool enable_text_console) +{ + g_debug_enabled = enable_debug; + g_serial_enabled = enable_serial; + g_text_console_enabled = enable_text_console; +} + +bool log_debug_enabled() +{ + return g_debug_enabled; +} + +bool log_serial_enabled() +{ + return g_serial_enabled; +} + +bool log_text_console_enabled() +{ + return g_text_console_enabled; +} \ No newline at end of file diff --git a/kernel/src/Log.h b/kernel/src/Log.h new file mode 100644 index 00000000..6250a758 --- /dev/null +++ b/kernel/src/Log.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include + +enum class LogLevel +{ + Debug, + Info, + Warn, + Error, +}; + +Result vlog(LogLevel level, const char* format, va_list ap); +Result log(LogLevel level, const char* format, ...); + +void setup_log(bool enable_debug, bool enable_serial, bool enable_text_console); +bool log_debug_enabled(); +bool log_serial_enabled(); +bool log_text_console_enabled(); + +#define kdbgln(...) log(LogLevel::Debug, __VA_ARGS__) +#define kinfoln(...) log(LogLevel::Info, __VA_ARGS__) +#define kwarnln(...) log(LogLevel::Warn, __VA_ARGS__) +#define kerrorln(...) log(LogLevel::Error, __VA_ARGS__) + +#define try_kdbgln(...) TRY(log(LogLevel::Debug, __VA_ARGS__)) +#define try_kinfoln(...) TRY(log(LogLevel::Info, __VA_ARGS__)) +#define try_kwarnln(...) TRY(log(LogLevel::Warn, __VA_ARGS__)) +#define try_kerrorln(...) TRY(log(LogLevel::Error, __VA_ARGS__)) \ No newline at end of file diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index ab7a0ee1..291cdc93 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -1,4 +1,5 @@ #include "boot/Init.h" +#include "Log.h" #include "arch/CPU.h" #include "arch/Serial.h" #include "boot/bootboot.h" @@ -23,9 +24,12 @@ void Init::early_init() CPU::disable_interrupts(); Framebuffer::init(); + + setup_log(log_debug_enabled(), log_serial_enabled(), true); + MemoryManager::init(); CPU::platform_init(); - check(MemoryManager::protect_kernel_sections().has_value()); + MemoryManager::protect_kernel_sections().release_value(); } \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 24b3bcd0..25d8c2fc 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,3 +1,4 @@ +#include "Log.h" #include "arch/CPU.h" #include "arch/MMU.h" #include "arch/Serial.h" @@ -36,10 +37,14 @@ Result init() TextConsole::set_foreground(0xff000055); TextConsole::set_background(0xff88ff00); - TextConsole::printf("Hello from Moon for the %s architecture!", CPU::platform_string()); + TextConsole::printf("Hello from Moon for the %s architecture!\n", CPU::platform_string()); Timer::init(); + kinfoln("Hello, world!"); + kwarnln("THIS IS A WARNING"); + kerrorln("ERROR: Please do something."); + CPU::platform_finish_init(); CPU::enable_interrupts(); @@ -54,17 +59,17 @@ Result init() char buffer[64]; to_dynamic_unit(MemoryManager::free(), buffer, sizeof(buffer)); - Serial::printf("Free memory: %s\n", buffer); + kinfoln("Free memory: %s", buffer); to_dynamic_unit(MemoryManager::used(), buffer, sizeof(buffer)); - Serial::printf("Used memory: %s\n", buffer); + kinfoln("Used memory: %s", buffer); to_dynamic_unit(MemoryManager::reserved(), buffer, sizeof(buffer)); - Serial::printf("Reserved memory: %s\n", buffer); + kinfoln("Reserved memory: %s", buffer); while (1) { - while ((Timer::ticks_ms() - start) < 20) { CPU::wait_for_interrupt(); } + while ((Timer::ticks_ms() - start) < 100) { CPU::wait_for_interrupt(); } start = Timer::ticks_ms(); - Serial::printf("%8zu milliseconds have passed!\n", start); + kdbgln("%8zu milliseconds have passed!", start); } return {}; diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index 6d30e557..5e6b46f3 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -122,6 +122,16 @@ namespace TextConsole g_background_color = color; } + u32 foreground() + { + return g_foreground_color; + } + + u32 background() + { + return g_background_color; + } + void move_to(u32 x, u32 y) { g_x_position = x; diff --git a/kernel/src/video/TextConsole.h b/kernel/src/video/TextConsole.h index 21e6de6b..62dfb51f 100644 --- a/kernel/src/video/TextConsole.h +++ b/kernel/src/video/TextConsole.h @@ -9,6 +9,8 @@ namespace TextConsole void putchar(char c); void set_foreground(u32 color); void set_background(u32 color); + u32 foreground(); + u32 background(); void move_to(u32 x, u32 y); void print(const char* str); void println(const char* str); From f8ed74fda5ae944141c5a8828d48269ce753ee0e Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 14:41:35 +0100 Subject: [PATCH 088/407] Improve unit representation code --- luna/Units.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/luna/Units.cpp b/luna/Units.cpp index 98eb4e70..1ce0208c 100644 --- a/luna/Units.cpp +++ b/luna/Units.cpp @@ -1,15 +1,14 @@ #include #include -#include Result to_dynamic_unit(usize value, char* buffer, size_t max) { if (value < 1024) { return string_format(buffer, max, "%u bytes", value); } const char* unit_prefixes = "KMGTPE"; - for (int i = 40; i >= 0 && value > (0xfffccccccccccccUL >> i); i -= 10) + while (value > (1024 * 1024)) { - value >>= 10; + value /= 1024; unit_prefixes++; } From fe47e0d5cb04c0e36df2001430dd6b439504f25a Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 16:30:42 +0100 Subject: [PATCH 089/407] Clean init() up --- kernel/src/main.cpp | 47 +++-------------------------- kernel/src/memory/MemoryManager.cpp | 5 +++ kernel/src/memory/MemoryManager.h | 1 + 3 files changed, 10 insertions(+), 43 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 25d8c2fc..135a0078 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -17,61 +17,22 @@ Result init() Serial::println(TRY(CPU::identify())); - const u64 address = 0xfffffffff8000000; - - Serial::printf("Mapping address 0x%lx\n", address); - - TRY(MemoryManager::alloc_at(address, 1, MMU::ReadWrite)); - - TRY(MMU::remap(address, MMU::ReadWrite | MMU::User)); - - int flags = TRY(MMU::get_flags(address)); - - if (flags & MMU::ReadWrite) Serial::println("Mapping is now writable"); - if (flags & MMU::User) Serial::println("Mapping is now user accessible"); - - u64 old = TRY(MMU::unmap(address)); - - Serial::printf("Unmapped page, was pointing to %#lx\n", old); - - TextConsole::set_foreground(0xff000055); - TextConsole::set_background(0xff88ff00); - - TextConsole::printf("Hello from Moon for the %s architecture!\n", CPU::platform_string()); - Timer::init(); - kinfoln("Hello, world!"); - kwarnln("THIS IS A WARNING"); - kerrorln("ERROR: Please do something."); - CPU::platform_finish_init(); CPU::enable_interrupts(); - usize start = 0; - - int* mem = TRY(make()); - *(volatile int*)mem = 6; - Serial::printf("Read %d from memory\n", *mem); - - TRY(destroy(mem)); - char buffer[64]; + to_dynamic_unit(MemoryManager::total(), buffer, sizeof(buffer)); + kinfoln("Total memory: %s", buffer); to_dynamic_unit(MemoryManager::free(), buffer, sizeof(buffer)); - kinfoln("Free memory: %s", buffer); + kinfoln("Free memory: %s", buffer); to_dynamic_unit(MemoryManager::used(), buffer, sizeof(buffer)); - kinfoln("Used memory: %s", buffer); + kinfoln("Used memory: %s", buffer); to_dynamic_unit(MemoryManager::reserved(), buffer, sizeof(buffer)); kinfoln("Reserved memory: %s", buffer); - while (1) - { - while ((Timer::ticks_ms() - start) < 100) { CPU::wait_for_interrupt(); } - start = Timer::ticks_ms(); - kdbgln("%8zu milliseconds have passed!", start); - } - return {}; } diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index ebfb7b0e..54561743 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -272,4 +272,9 @@ namespace MemoryManager { return reserved_mem; } + + u64 total() + { + return free_mem + used_mem + reserved_mem; + } } \ No newline at end of file diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 17bf0136..f311f412 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -30,4 +30,5 @@ namespace MemoryManager u64 free(); u64 used(); u64 reserved(); + u64 total(); } \ No newline at end of file From fc0779a2f906900160e65d014270b895de34bf70 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 17:10:30 +0100 Subject: [PATCH 090/407] Add a SystemError module for errno values :) --- luna/CMakeLists.txt | 1 + luna/SystemError.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++ luna/SystemError.h | 58 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 luna/SystemError.cpp create mode 100644 luna/SystemError.h diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index ee20a2ce..8360aef4 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -3,6 +3,7 @@ set(FREESTANDING_SOURCES NumberParsing.cpp String.cpp Units.cpp + SystemError.cpp ) set(SOURCES diff --git a/luna/SystemError.cpp b/luna/SystemError.cpp new file mode 100644 index 00000000..00719b56 --- /dev/null +++ b/luna/SystemError.cpp @@ -0,0 +1,60 @@ +#include + +const char* error_string(int error) +{ + switch (error) + { + case 0: return "Success (not an error)"; + case EPERM: return "Operation not permitted"; + case ENOENT: return "No such file or directory"; + case ESRCH: return "No such process"; + case EINTR: return "Interrupted system call"; + case EIO: return "Input/output error"; + case ENXIO: return "No such device or address"; + case E2BIG: return "Argument list too long"; + case ENOEXEC: return "Exec format error"; + case EBADF: return "Bad file descriptor"; + case ECHILD: return "No child processes"; + case EAGAIN: return "Resource temporarily unavailable"; + case ENOMEM: return "Cannot allocate memory"; + case EACCES: return "Permission denied"; + case EFAULT: return "Bad address"; + case EBUSY: return "Device or resource busy"; + case EEXIST: return "File exists"; + case EXDEV: return "Invalid cross-device link"; + case ENODEV: return "No such device"; + case ENOTDIR: return "Not a directory"; + case EISDIR: return "Is a directory"; + case EINVAL: return "Invalid argument"; + case ENFILE: return "Too many open files in system"; + case EMFILE: return "Too many open files"; + case ENOTTY: return "Inappropriate ioctl for device"; + case EFBIG: return "File too large"; + case ENOSPC: return "No space left on device"; + case ESPIPE: return "Illegal seek"; + case EROFS: return "Read-only file system"; + case EMLINK: return "Too many links"; + case EPIPE: return "Broken pipe"; + case EDOM: return "Numerical argument out of domain"; + case ERANGE: return "Numerical result out of range"; + case EDEADLK: return "Resource deadlock avoided"; + case ENAMETOOLONG: return "File name too long"; + case ENOLCK: return "No locks available"; + case ENOSYS: return "Function not implemented"; + case ENOTEMPTY: return "Directory not empty"; + case ELOOP: return "Too many levels of symbolic links"; + case ENOMSG: return "No message of desired type"; + case EOVERFLOW: return "Value too large for defined data type"; + case EILSEQ: return "Invalid or incomplete multibyte or wide character"; + case ENOTSOCK: return "Socket operation on non-socket"; + case ENOTSUP: return "Operation not supported"; + case EADDRINUSE: return "Address already in use"; + case ENETRESET: return "Network dropped connection on reset"; + case ECONNRESET: return "Connection reset by peer"; + case EISCONN: return "Transport endpoint is already connected"; + case ETIMEDOUT: return "Connection timed out"; + case EALREADY: return "Operation already in progress"; + case EFIXME: return "Functionality not yet implemented"; + default: return "Unknown error"; + } +} \ No newline at end of file diff --git a/luna/SystemError.h b/luna/SystemError.h new file mode 100644 index 00000000..0c952b57 --- /dev/null +++ b/luna/SystemError.h @@ -0,0 +1,58 @@ +#pragma once + +#define EPERM 1 // Operation not permitted +#define ENOENT 2 // No such file or directory +#define ESRCH 3 // No such process +#define EINTR 4 // Interrupted system call +#define EIO 5 // Input/output error +#define ENXIO 6 // No such device or address +#define E2BIG 7 // Argument list too long +#define ENOEXEC 8 // Exec format error +#define EBADF 9 // Bad file descriptor +#define ECHILD 10 // No child processes +#define EAGAIN 11 // Resource temporarily unavailable +#define EWOULDBLOCK 11 // Resource temporarily unavailable +#define ENOMEM 12 // Cannot allocate memory +#define EACCES 13 // Permission denied +#define EFAULT 14 // Bad address +#define EBUSY 16 // Device or resource busy +#define EEXIST 17 // File exists +#define EXDEV 18 // Invalid cross-device link +#define ENODEV 19 // No such device +#define ENOTDIR 20 // Not a directory +#define EISDIR 21 // Is a directory +#define EINVAL 22 // Invalid argument +#define ENFILE 23 // Too many open files in system +#define EMFILE 24 // Too many open files +#define ENOTTY 25 // Inappropriate ioctl for device +#define EFBIG 27 // File too large +#define ENOSPC 28 // No space left on device +#define ESPIPE 29 // Illegal seek +#define EROFS 30 // Read-only file system +#define EMLINK 31 // Too many links +#define EPIPE 32 // Broken pipe +#define EDOM 33 // Numerical argument out of domain +#define ERANGE 34 // Numerical result out of range +#define EDEADLK 35 // Resource deadlock avoided +#define ENAMETOOLONG 36 // File name too long +#define ENOLCK 37 // No locks available +#define ENOSYS 38 // Function not implemented +#define ENOTEMPTY 39 // Directory not empty +#define ELOOP 40 // Too many levels of symbolic links +#define ENOMSG 42 // No message of desired type +#define EOVERFLOW 75 // Value too large for defined data type +#define EILSEQ 84 // Invalid or incomplete multibyte or wide character +#define ENOTSOCK 88 // Socket operation on non-socket +#define ENOTSUP 95 // Operation not supported +#define EOPNOTSUPP 95 // Operation not supported +#define EADDRINUSE 98 // Address already in use +#define ENETRESET 102 // Network dropped connection on reset +#define ECONNRESET 104 // Connection reset by peer +#define EISCONN 106 // Transport endpoint is already connected +#define ETIMEDOUT 110 // Connection timed out +#define EALREADY 114 // Operation already in progress + +// This one is Luna-specific. +#define EFIXME 342 // Functionality not yet implemented + +const char* error_string(int error); \ No newline at end of file From 1d51935d4349f153819e274631bd98fd82be1b3e Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 17:10:43 +0100 Subject: [PATCH 091/407] Make Result able to return an error string --- luna/Result.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/luna/Result.h b/luna/Result.h index 1aec130f..13dfd58a 100644 --- a/luna/Result.h +++ b/luna/Result.h @@ -2,6 +2,7 @@ #include #include #include +#include #include struct Error @@ -92,6 +93,12 @@ template class Result return {m_error}; } + const char* error_string() + { + check(has_error()); + return ::error_string(m_error); + } + T value() { check(has_value()); @@ -224,6 +231,12 @@ template <> class Result return {m_error}; } + const char* error_string() + { + check(has_error()); + return ::error_string(m_error); + } + void value() { check(has_value()); @@ -242,7 +255,7 @@ template <> class Result }; // clang-format off -#define err Error{0} +#define err(x) Error{x} // clang-format on #define TRY(expr) \ From 29dad5651d7f3fd85346d72d680d7c0e78181e06 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 17:12:06 +0100 Subject: [PATCH 092/407] Move __check_failed to Log.cpp so it can be logged across all backends --- kernel/src/Log.cpp | 13 +++++++++++++ kernel/src/arch/Serial.cpp | 12 ------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 1a7c34c9..63519d43 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -1,4 +1,5 @@ #include "Log.h" +#include "arch/CPU.h" #include "arch/Serial.h" #include "arch/Timer.h" #include "video/TextConsole.h" @@ -112,4 +113,16 @@ bool log_serial_enabled() bool log_text_console_enabled() { return g_text_console_enabled; +} + +static bool g_check_already_failed = false; + +_noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr) +{ + if (!g_check_already_failed) + { // Avoid endlessly failing when trying to report a failed check. + g_check_already_failed = true; + kerrorln("ERROR: Check failed at %s:%s, in %s: %s", file, line, func, expr); + } + CPU::efficient_halt(); } \ No newline at end of file diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index 9a00a751..2dc834ac 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -34,16 +34,4 @@ namespace Serial va_end(ap); return rc; } -} - -static bool g_check_already_failed = false; - -_noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr) -{ - if (!g_check_already_failed) - { // Avoid endlessly failing when trying to report a failed check. - g_check_already_failed = true; - Serial::printf("ERROR: Check failed at %s:%s, in %s: %s\n", file, line, func, expr); - } - CPU::efficient_halt(); } \ No newline at end of file From d2856d8812f761482e748daf9620465e431a2c2e Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 17:13:59 +0100 Subject: [PATCH 093/407] Provide meaningful error numbers --- kernel/src/arch/x86_64/CPU.cpp | 7 ++++--- kernel/src/arch/x86_64/MMU.cpp | 27 ++++++++++++++------------- kernel/src/memory/Heap.cpp | 11 ++++++----- kernel/src/memory/MemoryManager.cpp | 7 ++++--- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 968ba063..83a65206 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -3,6 +3,7 @@ #include "arch/Timer.h" #include "arch/x86_64/IO.h" #include +#include #include #include @@ -347,11 +348,11 @@ namespace CPU static char brand_string[49]; u32 buf[4]; - if (!__get_cpuid(0x80000002, &buf[0], &buf[1], &buf[2], &buf[3])) return err; + if (!__get_cpuid(0x80000002, &buf[0], &buf[1], &buf[2], &buf[3])) return err(ENOTSUP); memcpy(brand_string, buf, 16); - if (!__get_cpuid(0x80000003, &buf[0], &buf[1], &buf[2], &buf[3])) return err; + if (!__get_cpuid(0x80000003, &buf[0], &buf[1], &buf[2], &buf[3])) return err(ENOTSUP); memcpy(&brand_string[16], buf, 16); - if (!__get_cpuid(0x80000004, &buf[0], &buf[1], &buf[2], &buf[3])) return err; + if (!__get_cpuid(0x80000004, &buf[0], &buf[1], &buf[2], &buf[3])) return err(ENOTSUP); memcpy(&brand_string[32], buf, 16); brand_string[48] = 0; // null-terminate it :) diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 613fcacb..a36a038e 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -1,6 +1,7 @@ #include "arch/MMU.h" #include "memory/MemoryManager.h" #include +#include #define PAGE_SIZE 4096 @@ -161,12 +162,12 @@ namespace MMU Result find_entry(u64 virt) { auto& l4 = l4_entry(virt); - if (!l4.present) return err; + if (!l4.present) return err(EFAULT); auto& l3 = l3_entry(virt); - if (!l3.present) return err; + if (!l3.present) return err(EFAULT); if (l3.larger_pages) return &l3; auto& l2 = l2_entry(virt); - if (!l2.present) return err; + if (!l2.present) return err(EFAULT); if (l2.larger_pages) return &l2; return &l1_entry(virt); } @@ -174,16 +175,16 @@ namespace MMU Result apply_cascading_flags(u64 virt, int flags) { auto& l4 = l4_entry(virt); - if (!l4.present) return err; + if (!l4.present) return err(EFAULT); if (flags & Flags::ReadWrite) l4.read_write = true; if (flags & Flags::User) l4.user = true; auto& l3 = l3_entry(virt); - if (!l3.present) return err; + if (!l3.present) return err(EFAULT); if (l3.larger_pages) return &l3; if (flags & Flags::ReadWrite) l3.read_write = true; if (flags & Flags::User) l3.user = true; auto& l2 = l2_entry(virt); - if (!l2.present) return err; + if (!l2.present) return err(EFAULT); if (l2.larger_pages) return &l2; if (flags & Flags::ReadWrite) l2.read_write = true; if (flags & Flags::User) l2.user = true; @@ -217,7 +218,7 @@ namespace MMU if (flags & Flags::ReadWrite) l3.read_write = true; if (flags & Flags::User) l3.user = true; - if (l3.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM + if (l3.larger_pages) return err(EFIXME); // FIXME: Replacing larger pages is not supported ATM auto& l2 = l2_entry(virt); if (!l2.present) @@ -231,10 +232,10 @@ namespace MMU if (flags & Flags::ReadWrite) l2.read_write = true; if (flags & Flags::User) l2.user = true; - if (l2.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM + if (l2.larger_pages) return err(EFIXME); // FIXME: Replacing larger pages is not supported ATM auto& l1 = l1_entry(virt); - if (l1.present) return err; // Please explicitly unmap the page before mapping it again. + if (l1.present) return err(EEXIST); // Please explicitly unmap the page before mapping it again. l1.ignore0 = l1.ignore1 = false; l1.present = true; l1.read_write = (flags & Flags::ReadWrite); @@ -249,7 +250,7 @@ namespace MMU Result remap(u64 virt, int flags) { auto& l1 = *TRY(apply_cascading_flags(virt, flags)); - if (!l1.present) return err; + if (!l1.present) return err(EFAULT); l1.read_write = (flags & Flags::ReadWrite); l1.user = (flags & Flags::User); l1.write_through = (flags & Flags::WriteThrough); @@ -261,7 +262,7 @@ namespace MMU Result unmap(u64 virt) { auto& l1 = *TRY(find_entry(virt)); - if (!l1.present) return err; + if (!l1.present) return err(EFAULT); u64 address = l1.get_address(); memset(&l1, 0, sizeof(l1)); flush_page(virt); @@ -271,14 +272,14 @@ namespace MMU Result get_physical(u64 virt) { auto& l1 = *TRY(find_entry(virt)); - if (!l1.present) return err; + if (!l1.present) return err(EFAULT); return l1.get_address(); } Result get_flags(u64 virt) { auto& l1 = *TRY(find_entry(virt)); - if (!l1.present) return err; + if (!l1.present) return err(EFAULT); return arch_flags_to_mmu(l1); } diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 74866481..1b18516f 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -4,6 +4,7 @@ #include "memory/MemoryManager.h" #include #include +#include static constexpr int BLOCK_USED = 1 << 0; static constexpr int BLOCK_START_MEM = 1 << 1; @@ -97,7 +98,7 @@ static Result split(HeapBlock* block, usize size) usize old_size = block->full_size; // Save the old value of this variable since we are going to use it after modifying it - if (available < (size + sizeof(HeapBlock))) return err; + if (available < (size + sizeof(HeapBlock))) return err(0); // This error is not propagated. usize offset = get_fair_offset_to_split_at(block, size + sizeof(HeapBlock)); block->full_size = offset; // shrink the old block to fit this offset @@ -244,13 +245,13 @@ Result kfree(void* ptr) else Serial::printf("ERROR: Attempt to free memory at %p, which wasn't allocated with kmalloc\n", ptr); - return err; + return err(EFAULT); } if (is_block_free(block)) { Serial::printf("ERROR: Attempt to free memory at %p, which was already freed\n", ptr); - return err; + return err(EFAULT); } else block->status &= ~BLOCK_USED; @@ -300,7 +301,7 @@ Result krealloc(void* ptr, usize size) else Serial::printf("ERROR: Attempt to realloc memory at %p, which wasn't allocated with kmalloc\n", ptr); - return err; + return err(EFAULT); } size = align_up(size, 16UL); @@ -308,7 +309,7 @@ Result krealloc(void* ptr, usize size) if (is_block_free(block)) { Serial::printf("ERROR: Attempt to realloc memory at %p, which was already freed\n", ptr); - return err; + return err(EFAULT); } if (block->full_size >= size) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 54561743..906efaae 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -4,6 +4,7 @@ #include "boot/bootboot.h" #include #include +#include #include extern BOOTBOOT bootboot; @@ -143,14 +144,14 @@ namespace MemoryManager return index * ARCH_PAGE_SIZE; } - return err; // FIXME: ENOMEM. + return err(ENOMEM); } Result free_frame(u64 frame) { const u64 index = frame / ARCH_PAGE_SIZE; - if (index > (page_bitmap_size * 8)) return err; - if (!page_bitmap_read(index)) return err; + if (index > (page_bitmap_size * 8)) return err(EFAULT); + if (!page_bitmap_read(index)) return err(EFAULT); page_bitmap_set(index, false); used_mem -= ARCH_PAGE_SIZE; free_mem += ARCH_PAGE_SIZE; From 985d45ddfb8c89121e5998d4776c3aa2bae94635 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 17:16:36 +0100 Subject: [PATCH 094/407] Switch to logging functions everywhere --- kernel/src/arch/Timer.cpp | 4 ++-- kernel/src/arch/x86_64/CPU.cpp | 9 +++++---- kernel/src/boot/Init.cpp | 2 +- kernel/src/main.cpp | 8 ++++---- kernel/src/memory/Heap.cpp | 26 +++++++++++++------------- kernel/src/memory/MemoryManager.cpp | 4 ++-- 6 files changed, 27 insertions(+), 26 deletions(-) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index e9694a2c..d2ac041e 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -1,4 +1,5 @@ #include "arch/Timer.h" +#include "Log.h" #include "arch/Serial.h" #include "boot/bootboot.h" #include @@ -46,8 +47,7 @@ static u64 bootloader_time_to_unix(u8 boottime[8]) int second = bcd_number_to_decimal(boottime[6]); // "The last byte can store 1/100th second precision, but in lack of support on most platforms, it is 0x00". // Therefore, let's not rely on it. - Serial::printf("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC\n", day, month, year, hour, minute, second) - .release_value(); + kinfoln("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC", day, month, year, hour, minute, second).release_value(); return broken_down_to_unix(year - 1900, make_yday(year, month) + (day - 1), hour, minute, second); } diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 83a65206..a4cbb6c2 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -1,4 +1,5 @@ #include "arch/x86_64/CPU.h" +#include "Log.h" #include "arch/Serial.h" #include "arch/Timer.h" #include "arch/x86_64/IO.h" @@ -275,7 +276,7 @@ static void setup_idt() // Interrupt handling #define FIXME_UNHANDLED_INTERRUPT(name) \ - Serial::println("FIXME(interrupt): " name); \ + kerrorln("FIXME(interrupt): %s", name); \ CPU::efficient_halt(); extern "C" void handle_x86_exception([[maybe_unused]] Registers* regs) @@ -315,20 +316,20 @@ extern "C" void arch_interrupt_entry(Registers* regs) } else { - Serial::println("IRQ catched! Halting."); + kwarnln("IRQ catched! Halting."); CPU::efficient_halt(); } } extern "C" [[noreturn]] void arch_double_fault() { - Serial::println("ERROR: Catched double fault"); + kerrorln("ERROR: Catched double fault"); CPU::efficient_halt(); } extern "C" [[noreturn]] void arch_machine_check() { - Serial::println("ERROR: Machine check failed"); + kerrorln("ERROR: Machine check failed"); CPU::efficient_halt(); } diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 291cdc93..0654f8a9 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -13,7 +13,7 @@ void Init::check_magic() { if (memcmp(bootboot.magic, BOOTBOOT_MAGIC, 4)) { - Serial::println("ERROR: Invalid magic value from bootloader"); + kerrorln("ERROR: Invalid magic value from bootloader"); for (;;) ; } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 135a0078..bf0cf636 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -11,11 +11,11 @@ Result init() { - Serial::println("Hello, world!"); + kinfoln("Hello, world!"); - Serial::printf("Current platform: %s\n", CPU::platform_string()); + kinfoln("Current platform: %s", CPU::platform_string()); - Serial::println(TRY(CPU::identify())); + kinfoln("Current processor: %s", TRY(CPU::identify())); Timer::init(); @@ -41,6 +41,6 @@ extern "C" [[noreturn]] void _start() Init::check_magic(); Init::early_init(); auto rc = init(); - rc.release_value(); + if (rc.has_error()) kerrorln("Runtime error: %s", rc.error_string()); CPU::efficient_halt(); } \ No newline at end of file diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 1b18516f..54dbb9f0 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -1,4 +1,5 @@ #include "memory/Heap.h" +#include "Log.h" #include "arch/MMU.h" #include "arch/Serial.h" #include "memory/MemoryManager.h" @@ -240,17 +241,17 @@ Result kfree(void* ptr) { if (block->magic == BLOCK_DEAD) { - Serial::printf("ERROR: Attempt to free memory at %p, which was already freed\n", ptr); + kerrorln("ERROR: Attempt to free memory at %p, which was already freed", ptr); } else - Serial::printf("ERROR: Attempt to free memory at %p, which wasn't allocated with kmalloc\n", ptr); + kerrorln("ERROR: Attempt to free memory at %p, which wasn't allocated with kmalloc", ptr); return err(EFAULT); } if (is_block_free(block)) { - Serial::printf("ERROR: Attempt to free memory at %p, which was already freed\n", ptr); + kerrorln("ERROR: Attempt to free memory at %p, which was already freed", ptr); return err(EFAULT); } else @@ -296,10 +297,10 @@ Result krealloc(void* ptr, usize size) { if (block->magic == BLOCK_DEAD) { - Serial::printf("ERROR: Attempt to realloc memory at %p, which was already freed\n", ptr); + kerrorln("ERROR: Attempt to realloc memory at %p, which was already freed", ptr); } else - Serial::printf("ERROR: Attempt to realloc memory at %p, which wasn't allocated with kmalloc\n", ptr); + kerrorln("ERROR: Attempt to realloc memory at %p, which wasn't allocated with kmalloc", ptr); return err(EFAULT); } @@ -308,7 +309,7 @@ Result krealloc(void* ptr, usize size) if (is_block_free(block)) { - Serial::printf("ERROR: Attempt to realloc memory at %p, which was already freed\n", ptr); + kerrorln("ERROR: Attempt to realloc memory at %p, which was already freed", ptr); return err(EFAULT); } @@ -336,10 +337,10 @@ Result kcalloc(usize nmemb, usize size) void dump_heap_usage() { - Serial::println("-- Dumping usage stats for kernel heap:"); + kdbgln("-- Dumping usage stats for kernel heap:"); if (!heap_start) { - Serial::println("- Heap is not currently being used"); + kdbgln("- Heap is not currently being used"); return; } usize alloc_total = 0; @@ -349,19 +350,18 @@ void dump_heap_usage() { if (is_block_free(block)) { - Serial::printf("- Available block, of size %zu\n", block->full_size); + kdbgln("- Available block, of size %zu", block->full_size); alloc_total += block->full_size + sizeof(HeapBlock); } else { - Serial::printf("- Used block, of size %zu, of which %zu bytes are being used\n", block->full_size, - block->req_size); + kdbgln("- Used block, of size %zu, of which %zu bytes are being used", block->full_size, block->req_size); alloc_total += block->full_size + sizeof(HeapBlock); alloc_used += block->req_size; } block = block->next; } - Serial::printf("-- Total memory allocated for heap: %zu bytes\n", alloc_total); - Serial::printf("-- Heap memory in use by the kernel: %zu bytes\n", alloc_used); + kdbgln("-- Total memory allocated for heap: %zu bytes", alloc_total); + kdbgln("-- Heap memory in use by the kernel: %zu bytes", alloc_used); } \ No newline at end of file diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 906efaae..65d9006d 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -1,6 +1,6 @@ #include "memory/MemoryManager.h" +#include "Log.h" #include "arch/MMU.h" -#include "arch/Serial.h" #include "boot/bootboot.h" #include #include @@ -88,7 +88,7 @@ namespace MemoryManager page_virtual_bitmap_addr = page_bitmap_addr; // we'll map this to virtual memory as soon as the MMU is ready if ((total_mem / ARCH_PAGE_SIZE / 8) >= biggest_memory_block_size) { - Serial::println("ERROR: No single memory block is enough to hold the page bitmap"); + kerrorln("ERROR: No single memory block is enough to hold the page bitmap"); for (;;) ; } From 3f40ccd7037bca1611af8a59027c2239058c5f23 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 17:26:33 +0100 Subject: [PATCH 095/407] Indicate the log level in the serial console --- kernel/src/Log.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 63519d43..67704922 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -14,11 +14,17 @@ static constexpr u32 WHITE = 0xffffffff; static constexpr u32 YELLOW = 0xffffff00; static constexpr u32 RED = 0xffff0000; -static Result log_serial(LogLevel, const char* format, va_list origin) +static char log_level_letters[] = {'D', 'I', 'W', 'E'}; // D for debug, I for info, W for warning, E for error +static const char* ansi_color_codes_per_log_level[] = {"37", "37", "33", "31"}; // 37 is white, 33 yellow, 31 red + +static Result log_serial(LogLevel level, const char* format, va_list origin) { va_list ap; va_copy(ap, origin); + TRY(Serial::printf("\x1b[%sm%c\x1b[0m ", ansi_color_codes_per_log_level[(int)level], + log_level_letters[(int)level])); + TRY(Serial::printf("[%6zu.%.6zu] ", Timer::ticks(), Timer::ticks_us() - (Timer::ticks() * 1000000))); TRY(cstyle_format( From 2bc99f2e6e3bd947d796dece73c825dd0b2922b1 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 17:28:46 +0100 Subject: [PATCH 096/407] Make log __attribute__(format), so the compiler can warn us of bad format strings --- kernel/src/Log.h | 3 ++- kernel/src/main.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/src/Log.h b/kernel/src/Log.h index 6250a758..0c0b9ab8 100644 --- a/kernel/src/Log.h +++ b/kernel/src/Log.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include @@ -11,7 +12,7 @@ enum class LogLevel }; Result vlog(LogLevel level, const char* format, va_list ap); -Result log(LogLevel level, const char* format, ...); +Result log(LogLevel level, const char* format, ...) _format(2, 3); void setup_log(bool enable_debug, bool enable_serial, bool enable_text_console); bool log_debug_enabled(); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index bf0cf636..10e76567 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -33,6 +33,10 @@ Result init() to_dynamic_unit(MemoryManager::reserved(), buffer, sizeof(buffer)); kinfoln("Reserved memory: %s", buffer); + volatile char* p = (volatile char*)0xefe0f3445692d; + + *p = 7; + return {}; } From 9c9cb6a05a20eb71919f6322d294c7a474ead95d Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 30 Nov 2022 17:29:18 +0100 Subject: [PATCH 097/407] oopsie --- kernel/src/main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 10e76567..bf0cf636 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -33,10 +33,6 @@ Result init() to_dynamic_unit(MemoryManager::reserved(), buffer, sizeof(buffer)); kinfoln("Reserved memory: %s", buffer); - volatile char* p = (volatile char*)0xefe0f3445692d; - - *p = 7; - return {}; } From 374030942743421058b9e36a2a1a6e0fefd19072 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:18:16 +0100 Subject: [PATCH 098/407] Check for STRINGIZE_VALUE_OF before defining it --- luna/Check.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/luna/Check.h b/luna/Check.h index 1e24fb66..4327a2be 100644 --- a/luna/Check.h +++ b/luna/Check.h @@ -3,7 +3,9 @@ extern _noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr); +#ifndef STRINGIZE_VALUE_OF #define STRINGIZE(x) #x #define STRINGIZE_VALUE_OF(x) STRINGIZE(x) +#endif #define check(expr) (expr) || __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, #expr) From bdc9747f9edf885d4bb6a79e043d0aa63fe190e2 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:18:25 +0100 Subject: [PATCH 099/407] Set a project version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23c53e13..397b925c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CROSSCOMPILING true) -project(Luna LANGUAGES C CXX ASM_NASM) +project(Luna LANGUAGES C CXX ASM_NASM VERSION 0.1.0) set(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR}) From 1d7b9260c315f25a1cc960447b70515e8d18df41 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:25:25 +0100 Subject: [PATCH 100/407] Add config.h for version information --- kernel/CMakeLists.txt | 4 ++++ kernel/src/config.h.in | 6 ++++++ kernel/src/main.cpp | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 kernel/src/config.h.in diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index e23e42fd..a1c5155d 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -58,6 +58,10 @@ set_target_properties(moon PROPERTIES CXX_STANDARD 20) target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) +configure_file(src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/gen/config.h @ONLY) + +target_include_directories(moon PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/gen) + target_link_options(moon PRIVATE LINKER:-T ${CMAKE_CURRENT_LIST_DIR}/moon.ld -nostdlib -nodefaultlibs) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/moon" DESTINATION ${LUNA_ROOT}/initrd/boot) \ No newline at end of file diff --git a/kernel/src/config.h.in b/kernel/src/config.h.in new file mode 100644 index 00000000..6cbc30ec --- /dev/null +++ b/kernel/src/config.h.in @@ -0,0 +1,6 @@ +#pragma once + +#define MOON_VERSION "@CMAKE_PROJECT_VERSION@" +#define MOON_VERSION_MAJOR "@CMAKE_PROJECT_VERSION_MAJOR@" +#define MOON_VERSION_MINOR "@CMAKE_PROJECT_VERSION_MINOR@" +#define MOON_VERSION_PATCH "@CMAKE_PROJECT_VERSION_PATCH@" \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index bf0cf636..3e5cba2c 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,6 +4,7 @@ #include "arch/Serial.h" #include "arch/Timer.h" #include "boot/Init.h" +#include "config.h" #include "memory/Heap.h" #include "memory/MemoryManager.h" #include "video/TextConsole.h" @@ -11,7 +12,7 @@ Result init() { - kinfoln("Hello, world!"); + kinfoln("Starting Moon %s", MOON_VERSION); kinfoln("Current platform: %s", CPU::platform_string()); From dcd5a82073928372a6c52cbc8974f3506ca67713 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:34:14 +0100 Subject: [PATCH 101/407] Make GDB use the correct kernel file --- .gdbconf | 2 +- tools/gdb.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gdbconf b/.gdbconf index d03031b8..81fc76d9 100644 --- a/.gdbconf +++ b/.gdbconf @@ -1,4 +1,4 @@ -file kernel/bin/moon.elf +file kernel/moon break _start target remote :1234 continue \ No newline at end of file diff --git a/tools/gdb.sh b/tools/gdb.sh index f0363a98..394192d9 100755 --- a/tools/gdb.sh +++ b/tools/gdb.sh @@ -3,4 +3,6 @@ set -e source $(dirname $0)/env.sh +cd $BUILD_DIR + gdb -x .gdbconf \ No newline at end of file From 505dde35acdab399d4f535c0ef062553ec6a084a Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:34:36 +0100 Subject: [PATCH 102/407] Make GDB source .gdbconf relative to the root directory --- tools/gdb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gdb.sh b/tools/gdb.sh index 394192d9..bae0b3ab 100755 --- a/tools/gdb.sh +++ b/tools/gdb.sh @@ -5,4 +5,4 @@ source $(dirname $0)/env.sh cd $BUILD_DIR -gdb -x .gdbconf \ No newline at end of file +gdb -x $LUNA_ROOT/.gdbconf \ No newline at end of file From e440df58c91c41daad76f1b8d41bc806c99f6068 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:37:12 +0100 Subject: [PATCH 103/407] cleanup: remove unused scripts --- tools/binutils.patch | 117 -------------------------------- tools/build-debug.sh | 6 -- tools/build-stable-iso.sh | 9 +-- tools/gcc.patch | 137 -------------------------------------- 4 files changed, 1 insertion(+), 268 deletions(-) delete mode 100644 tools/binutils.patch delete mode 100755 tools/build-debug.sh mode change 100755 => 120000 tools/build-stable-iso.sh delete mode 100644 tools/gcc.patch diff --git a/tools/binutils.patch b/tools/binutils.patch deleted file mode 100644 index d375e06f..00000000 --- a/tools/binutils.patch +++ /dev/null @@ -1,117 +0,0 @@ -diff --color -rN -u binutils-2.38/bfd/config.bfd build/binutils-2.38/bfd/config.bfd ---- a/binutils-2.38/bfd/config.bfd 2022-01-22 13:14:07.000000000 +0100 -+++ b/binutils-2.38/bfd/config.bfd 2022-10-01 22:12:16.914033792 +0200 -@@ -651,6 +651,11 @@ - targ_selvecs="iamcu_elf32_vec i386_pei_vec" - targ64_selvecs="x86_64_elf64_vec x86_64_elf32_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec" - ;; -+ i[3-7]86-*-luna*) -+ targ_defvec=i386_elf32_vec -+ targ_selvecs= -+ targ64_selvecs=x86_64_elf64_vec -+ ;; - i[3-7]86-*-redox*) - targ_defvec=i386_elf32_vec - targ_selvecs= -@@ -706,6 +711,11 @@ - targ_selvecs="i386_elf32_vec iamcu_elf32_vec x86_64_elf32_vec i386_pei_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec" - want64=true - ;; -+ x86_64-*-luna*) -+ targ_defvec=x86_64_elf64_vec -+ targ_selvecs=i386_elf32_vec -+ want64=true -+ ;; - x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin) - targ_defvec=x86_64_pe_vec - targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_big_vec x86_64_elf64_vec l1om_elf64_vec k1om_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec" -diff --color -rN -u binutils-2.38/gas/configure.tgt build/binutils-2.38/gas/configure.tgt ---- a/binutils-2.38/gas/configure.tgt 2022-01-22 13:14:08.000000000 +0100 -+++ b/binutils-2.38/gas/configure.tgt 2022-10-01 22:12:38.115093972 +0200 -@@ -238,6 +238,7 @@ - x86_64*-linux-gnux32) arch=x86_64:32 ;; - esac ;; - i386-*-lynxos*) fmt=elf em=lynx ;; -+ i386-*-luna*) fmt=elf em=gnu ;; - i386-*-redox*) fmt=elf ;; - i386-*-solaris*) fmt=elf em=solaris ;; - i386-*-freebsd* \ -diff --color -rN -u binutils-2.38/ld/configure.tgt build/binutils-2.38/ld/configure.tgt ---- a/binutils-2.38/ld/configure.tgt 2022-01-22 15:19:36.000000000 +0100 -+++ b/binutils-2.38/ld/configure.tgt 2022-10-01 22:15:04.853571062 +0200 -@@ -329,6 +329,11 @@ - targ64_extra_emuls="elf_x86_64 elf32_x86_64 elf_l1om elf_k1om" - targ64_extra_libpath="elf_x86_64 elf32_x86_64" - ;; -+i[3-7]86-*-luna*) -+ targ_emul=elf_i386_luna -+ targ_extra_emuls=elf_i386 -+ targ64_extra_emuls="elf_x86_64_luna elf_x86_64" -+ ;; - i[3-7]86-*-redox*) targ_emul=elf_i386 - targ_extra_emuls=elf_x86_64 - ;; -@@ -967,6 +972,10 @@ - targ_extra_libpath="elf_i386 elf32_x86_64 elf_l1om elf_k1om" - tdir_elf_i386=`echo ${targ_alias} | sed -e 's/x86_64/i386/'` - ;; -+x86_64-*-luna*) -+ targ_emul=elf_x86_64_luna -+ targ_extra_emuls="elf_i386_luna elf_x86_64 elf_i386" -+ ;; - x86_64-*-redox*) targ_emul=elf_x86_64 - targ_extra_emuls=elf_i386 - ;; -diff --color -rN -u binutils-2.38/ld/emulparams/elf_i386_luna.sh build/binutils-2.38/ld/emulparams/elf_i386_luna.sh ---- a/dev/null 1970-01-01 01:00:00.000000000 +0100 -+++ b/binutils-2.38/ld/emulparams/elf_i386_luna.sh 2022-10-01 21:52:12.394068335 +0200 -@@ -0,0 +1,3 @@ -+source_sh ${srcdir}/emulparams/elf_i386.sh -+TEXT_START_ADDR=0x08000000 -+MAXPAGESIZE=0x1000 -\ No newline at end of file -diff --color -rN -u binutils-2.38/ld/emulparams/elf_x86_64_luna.sh build/binutils-2.38/ld/emulparams/elf_x86_64_luna.sh ---- a/dev/null 1970-01-01 01:00:00.000000000 +0100 -+++ b/binutils-2.38/ld/emulparams/elf_x86_64_luna.sh 2022-10-01 21:53:00.411200592 +0200 -@@ -0,0 +1,2 @@ -+source_sh ${srcdir}/emulparams/elf_x86_64.sh -+MAXPAGESIZE=0x1000 -\ No newline at end of file -diff --color -rN -u binutils-2.38/ld/Makefile.am build/binutils-2.38/ld/Makefile.am ---- a/binutils-2.38/ld/Makefile.am 2022-01-22 13:14:09.000000000 +0100 -+++ b/binutils-2.38/ld/Makefile.am 2022-10-01 22:18:02.660263017 +0200 -@@ -278,6 +278,7 @@ - eelf32xtensa.c \ - eelf32z80.c \ - eelf_i386.c \ -+ eelf_i386_luna.c \ - eelf_i386_be.c \ - eelf_i386_fbsd.c \ - eelf_i386_haiku.c \ -@@ -464,6 +465,7 @@ - eelf_x86_64_fbsd.c \ - eelf_x86_64_haiku.c \ - eelf_x86_64_sol2.c \ -+ eelf_x86_64_luna.c \ - ehppa64linux.c \ - ei386pep.c \ - emmo.c -diff --color -rN -u binutils-2.38/ld/Makefile.in build/binutils-2.38/ld/Makefile.in ---- a/binutils-2.38/ld/Makefile.in 2022-02-09 12:49:03.000000000 +0100 -+++ b/binutils-2.38/ld/Makefile.in 2022-10-01 22:17:46.740196925 +0200 -@@ -769,6 +769,7 @@ - eelf32xtensa.c \ - eelf32z80.c \ - eelf_i386.c \ -+ eelf_i386_luna.c \ - eelf_i386_be.c \ - eelf_i386_fbsd.c \ - eelf_i386_haiku.c \ -@@ -954,6 +955,7 @@ - eelf_x86_64_fbsd.c \ - eelf_x86_64_haiku.c \ - eelf_x86_64_sol2.c \ -+ eelf_x86_64_luna.c \ - ehppa64linux.c \ - ei386pep.c \ - emmo.c diff --git a/tools/build-debug.sh b/tools/build-debug.sh deleted file mode 100755 index 877def35..00000000 --- a/tools/build-debug.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e -source $(dirname $0)/env.sh - -MOON_BUILD_DEBUG=1 tools/rebuild-iso.sh \ No newline at end of file diff --git a/tools/build-stable-iso.sh b/tools/build-stable-iso.sh deleted file mode 100755 index 270c97b1..00000000 --- a/tools/build-stable-iso.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -set -e - -source $(dirname $0)/env.sh - -cd $LUNA_ROOT - -MOON_BUILD_STABLE=1 tools/rebuild-iso.sh \ No newline at end of file diff --git a/tools/build-stable-iso.sh b/tools/build-stable-iso.sh new file mode 120000 index 00000000..cab78962 --- /dev/null +++ b/tools/build-stable-iso.sh @@ -0,0 +1 @@ +/home/apio/Dev/Luna/tools/rebuild-iso.sh \ No newline at end of file diff --git a/tools/gcc.patch b/tools/gcc.patch deleted file mode 100644 index 04500e4d..00000000 --- a/tools/gcc.patch +++ /dev/null @@ -1,137 +0,0 @@ -diff --color -rN -u gcc-12.2.0/config.sub build/gcc-12.2.0/config.sub ---- a/gcc-12.2.0/config.sub 2022-08-19 10:09:52.128656687 +0200 -+++ b/gcc-12.2.0/config.sub 2022-10-02 11:27:45.660055384 +0200 -@@ -1723,7 +1723,7 @@ - | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ - | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ - | hiux* | abug | nacl* | netware* | windows* \ -- | os9* | macos* | osx* | ios* \ -+ | os9* | macos* | osx* | ios* | luna* \ - | mpw* | magic* | mmixware* | mon960* | lnews* \ - | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ - | aos* | aros* | cloudabi* | sortix* | twizzler* \ -diff --color -rN -u gcc-12.2.0/fixincludes/mkfixinc.sh build/gcc-12.2.0/fixincludes/mkfixinc.sh ---- a/gcc-12.2.0/fixincludes/mkfixinc.sh 2022-08-19 10:09:52.160657095 +0200 -+++ b/gcc-12.2.0/fixincludes/mkfixinc.sh 2022-10-02 11:27:45.662055397 +0200 -@@ -12,6 +12,8 @@ - # Check for special fix rules for particular targets - case $machine in - i?86-*-cygwin* | \ -+ *-luna* | \ -+ *-*-luna* | \ - i?86-*-mingw32* | \ - x86_64-*-mingw32* | \ - powerpc-*-eabisim* | \ -diff --color -rN -u gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel build/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel ---- a/dev/null 1970-01-01 01:00:00.000000000 +0100 -+++ b/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel 2022-10-02 11:45:30.955856133 +0200 -@@ -0,0 +1,4 @@ -+#Add libgcc multilib variant without red-zone requirement, for use in the kernel -+ -+MULTILIB_OPTIONS += mno-red-zone -+MULTILIB_DIRNAMES += no-red-zone -\ No newline at end of file -diff --color -rN -u gcc-12.2.0/gcc/config/luna.h build/gcc-12.2.0/gcc/config/luna.h ---- a/dev/null 1970-01-01 01:00:00.000000000 +0100 -+++ b/gcc-12.2.0/gcc/config/luna.h 2022-10-02 11:27:45.663055404 +0200 -@@ -0,0 +1,40 @@ -+#undef TARGET_LUNA -+#define TARGET_LUNA 1 -+ -+/* Default arguments you want when running your -+ i686-luna-gcc/x86_64-luna-gcc toolchain */ -+#undef LIB_SPEC -+#define LIB_SPEC "-lc" /* link against C standard library */ -+ -+/* Files that are linked before user code. -+ The %s tells GCC to look for these files in the library directory. */ -+#undef STARTFILE_SPEC -+#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s" -+ -+/* Files that are linked after user code. */ -+#undef ENDFILE_SPEC -+#define ENDFILE_SPEC "crtend.o%s crtn.o%s" -+ -+#undef PID_TYPE -+#define PID_TYPE "long int" -+ -+#undef SIZE_TYPE -+#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int") -+ -+/* Ensure that ptrdiff_t matches the actual pointer size */ -+#undef PTRDIFF_TYPE -+#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int") -+ -+/* Additional predefined macros. */ -+#undef TARGET_OS_CPP_BUILTINS -+#define TARGET_OS_CPP_BUILTINS() \ -+ do { \ -+ builtin_define("__luna__"); \ -+ builtin_define("__unix__"); \ -+ builtin_assert("system=luna"); \ -+ builtin_assert("system=unix"); \ -+ builtin_assert("system=posix"); \ -+ } while (0); -+ -+#undef LINK_SPEC -+#define LINK_SPEC "-z max-page-size=4096" -\ No newline at end of file -diff --color -rN -u gcc-12.2.0/gcc/config.gcc build/gcc-12.2.0/gcc/config.gcc ---- a/gcc-12.2.0/gcc/config.gcc 2022-08-19 10:09:52.552662114 +0200 -+++ b/gcc-12.2.0/gcc/config.gcc 2022-10-02 11:45:18.311797546 +0200 -@@ -895,6 +895,12 @@ - ;; - esac - ;; -+*-*-luna*) -+ gas=yes -+ gnu_ld=yes -+ default_use_cxa_atexit=yes -+ use_gcc_stdint=provide -+ ;; - *-*-netbsd*) - tm_p_file="${tm_p_file} netbsd-protos.h" - tmake_file="t-netbsd t-slibgcc" -@@ -1901,6 +1907,13 @@ - x86_64-*-elf*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h" - ;; -+i[34567]86-*-luna*) -+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h luna.h" -+ ;; -+x86_64-*-luna*) -+ tmake_file="${tmake_file} i386/x86_64-luna-kernel" -+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h luna.h" -+ ;; - x86_64-*-rtems*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rtemself.h rtems.h" - ;; -diff --color -rN -u gcc-12.2.0/libgcc/config.host build/gcc-12.2.0/libgcc/config.host ---- a/gcc-12.2.0/libgcc/config.host 2022-08-19 10:09:54.664689148 +0200 -+++ b/gcc-12.2.0/libgcc/config.host 2022-10-02 11:27:45.671055461 +0200 -@@ -783,6 +783,14 @@ - ;; - i[34567]86-*-lynxos*) - ;; -+i[34567]86-*-luna*) -+ extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o" -+ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic" -+ ;; -+x86_64-*-luna*) -+ extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o" -+ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic" -+ ;; - i[34567]86-*-nto-qnx*) - tmake_file="$tmake_file i386/t-nto t-libgcc-pic" - extra_parts=crtbegin.o -diff --color -rN -u gcc-12.2.0/libgcc/libgcov.h build/gcc-12.2.0/libgcc/libgcov.h ---- a/gcc-12.2.0/libgcc/libgcov.h 2022-08-19 10:09:54.728689966 +0200 -+++ b/gcc-12.2.0/libgcc/libgcov.h 2022-10-02 11:41:48.571807335 +0200 -@@ -194,6 +194,7 @@ - #endif - - #include "gcov-io.h" -+#include - - /* Structures embedded in coveraged program. The structures generated - by write_profile must match these. */ From bbc5470ae492e55a9c13a96123d47ee2c199df28 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:39:22 +0100 Subject: [PATCH 104/407] Update symlink location --- tools/build-stable-iso.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build-stable-iso.sh b/tools/build-stable-iso.sh index cab78962..0b6e6f17 120000 --- a/tools/build-stable-iso.sh +++ b/tools/build-stable-iso.sh @@ -1 +1 @@ -/home/apio/Dev/Luna/tools/rebuild-iso.sh \ No newline at end of file +./rebuild-iso.sh \ No newline at end of file From d72478de29181624b4929c8a0ba4ac50a87154e4 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:51:39 +0100 Subject: [PATCH 105/407] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ace6537..b1fe9778 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Luna -A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C. +A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C. (rewrite, listed features are currently mostly from the old version) ## Features - x86_64-compatible [kernel](kernel/). From 37a41f3d2c043cea3a4092f7e76c4375cf322f28 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Dec 2022 17:53:47 +0100 Subject: [PATCH 106/407] Add warning message --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1fe9778..e8c68281 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ A simple kernel and userspace for the x86_64 platform, written mostly in C++ and ## Notes - The default user is named 'selene' and you can log into it with the password 'moon'. -## Setup +## Setup (probably broken) To build and run Luna, you will need to build a [GCC Cross-Compiler](https://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler%3F) and cross-binutils for `x86_64-luna`. (Yes, Luna is advanced enough that it can use its own [OS-Specific Toolchain](https://wiki.osdev.org/OS_Specific_Toolchain), instead of a bare metal target like `x86_64-elf`. It is the first of my OS projects to be able to do so. The patches for Binutils and GCC are [binutils.patch](tools/binutils.patch) and [gcc.patch](tools/gcc.patch)). You should start by installing the [required dependencies](https://wiki.osdev.org/GCC_Cross_Compiler#Installing_Dependencies). From 9a6d0d1bae3eaa83041678329a1c5a8a10d74cfd Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 10:07:56 +0100 Subject: [PATCH 107/407] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e8c68281..17bbbb78 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,10 @@ A simple kernel and userspace for the x86_64 platform, written mostly in C++ and ## Notes - The default user is named 'selene' and you can log into it with the password 'moon'. -## Setup (probably broken) -To build and run Luna, you will need to build a [GCC Cross-Compiler](https://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler%3F) and cross-binutils for `x86_64-luna`. (Yes, Luna is advanced enough that it can use its own [OS-Specific Toolchain](https://wiki.osdev.org/OS_Specific_Toolchain), instead of a bare metal target like `x86_64-elf`. It is the first of my OS projects to be able to do so. The patches for Binutils and GCC are [binutils.patch](tools/binutils.patch) and [gcc.patch](tools/gcc.patch)). +## Setup (broken) +**WARNING**: Setup will fail on this branch, since we do not have the required libc headers yet, and I removed the patches for now. Your best bet to build the toolchain is to switch to the `main` branch, where it will build successfully, and run `tools/setup.sh`. Then switch back to this branch, remove some files created by the `main` branch, and continue development :) + +To build and run Luna, you will need to build a [GCC Cross-Compiler](https://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler) and cross-binutils for `x86_64-luna`. (Yes, Luna is advanced enough that it can use its own [OS-Specific Toolchain](https://wiki.osdev.org/OS_Specific_Toolchain), instead of a bare metal target like `x86_64-elf`. It is the first of my OS projects to be able to do so. The patches for Binutils and GCC are [binutils.patch](tools/binutils.patch) and [gcc.patch](tools/gcc.patch)). You should start by installing the [required dependencies](https://wiki.osdev.org/GCC_Cross_Compiler#Installing_Dependencies). @@ -42,8 +44,6 @@ There are a variety of scripts for building Luna. `tools/build-iso.sh` will build, install, and make an ISO disk image named Luna.iso. -`tools/build-debug.sh` will rebuild the kernel with debug symbols and optimizations disabled, install, and make an ISO image. This script should only be used when you are going to be running the system with a debugger (such as GDB). - `tools/build-stable-iso.sh` does the same thing as build-iso.sh, but configures the kernel so that the version does not show the commit hash (used for stable versions). `tools/rebuild-iso.sh` will do a clean rebuild, install, and make an ISO disk image. From 5d9c50eb12e556e539a7cb42ce783d55fbc162cd Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 10:27:25 +0100 Subject: [PATCH 108/407] Make build-debug.sh work --- kernel/CMakeLists.txt | 5 +++++ tools/build-debug.sh | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100755 tools/build-debug.sh diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index a1c5155d..28007d7f 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -52,6 +52,11 @@ if("${ARCH}" MATCHES "x86_64") target_link_options(moon PRIVATE -mno-red-zone) endif() +if(MOON_DEBUG_SYMBOLS) + message(STATUS "Building Moon with debug symbols") + target_compile_options(moon PRIVATE -ggdb) +endif() + target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mcmodel=kernel) set_target_properties(moon PROPERTIES CXX_STANDARD 20) diff --git a/tools/build-debug.sh b/tools/build-debug.sh new file mode 100755 index 00000000..ea36b439 --- /dev/null +++ b/tools/build-debug.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -e + +source $(dirname $0)/env.sh + +cd $LUNA_ROOT + +tools/setup.sh + +rm -rf $BUILD_DIR +mkdir $BUILD_DIR + +cmake -S . -B $BUILD_DIR -DMOON_DEBUG_SYMBOLS=ON -G "$CMAKE_GEN" +cmake --build $BUILD_DIR +cmake --install $BUILD_DIR + +mkbootimg luna.json Luna.iso \ No newline at end of file From a0c4bbe6f3cec7ee7b2e8571da3a086abfaf898b Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 11:55:47 +0100 Subject: [PATCH 109/407] Make sure to clean CMake cache when rebuilding --- tools/build-debug.sh | 3 +-- tools/full-clean.sh | 7 +++++++ tools/rebuild-iso.sh | 4 +--- tools/rebuild.sh | 4 +--- 4 files changed, 10 insertions(+), 8 deletions(-) create mode 100755 tools/full-clean.sh diff --git a/tools/build-debug.sh b/tools/build-debug.sh index ea36b439..85d83455 100755 --- a/tools/build-debug.sh +++ b/tools/build-debug.sh @@ -7,8 +7,7 @@ cd $LUNA_ROOT tools/setup.sh -rm -rf $BUILD_DIR -mkdir $BUILD_DIR +tools/full-clean.sh cmake -S . -B $BUILD_DIR -DMOON_DEBUG_SYMBOLS=ON -G "$CMAKE_GEN" cmake --build $BUILD_DIR diff --git a/tools/full-clean.sh b/tools/full-clean.sh new file mode 100755 index 00000000..e4e03188 --- /dev/null +++ b/tools/full-clean.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -e + +source $(dirname $0)/env.sh + +rm -rf $BUILD_DIR +mkdir -p $BUILD_DIR \ No newline at end of file diff --git a/tools/rebuild-iso.sh b/tools/rebuild-iso.sh index 8537e980..a10085cb 100755 --- a/tools/rebuild-iso.sh +++ b/tools/rebuild-iso.sh @@ -7,9 +7,7 @@ cd $LUNA_ROOT tools/setup.sh -cd $BUILD_DIR -$BUILD clean -cd - +tools/full-clean.sh cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" cmake --build $BUILD_DIR diff --git a/tools/rebuild.sh b/tools/rebuild.sh index cff4de9a..1c3e0316 100755 --- a/tools/rebuild.sh +++ b/tools/rebuild.sh @@ -7,9 +7,7 @@ cd $LUNA_ROOT tools/setup.sh -cd $BUILD_DIR -$BUILD clean -cd - +tools/full-clean.sh cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" cmake --build $BUILD_DIR \ No newline at end of file From bb92480aa348a0aab591ca699c4b1dcb0d4ef550 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:19:17 +0100 Subject: [PATCH 110/407] Add a variant of check() that accepts an error message --- luna/Check.h | 2 ++ luna/Result.h | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/luna/Check.h b/luna/Check.h index 4327a2be..429e65af 100644 --- a/luna/Check.h +++ b/luna/Check.h @@ -9,3 +9,5 @@ extern _noreturn bool __check_failed(const char* file, const char* line, const c #endif #define check(expr) (expr) || __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, #expr) +#define expect(expr, message) \ + (expr) || __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, message) diff --git a/luna/Result.h b/luna/Result.h index 13dfd58a..ed99a04b 100644 --- a/luna/Result.h +++ b/luna/Result.h @@ -83,25 +83,25 @@ template class Result int error() { - check(has_error()); + expect(has_error(), "Result::error() called on a Result that holds a value"); return m_error; } Error release_error() { - check(has_error()); + expect(has_error(), "Result::release_error() called on a Result that holds a value"); return {m_error}; } const char* error_string() { - check(has_error()); + expect(has_error(), "Result::error_string() called on a Result that holds a value"); return ::error_string(m_error); } T value() { - check(has_value()); + expect(has_value(), "Result::value() called on a Result that holds an error"); return m_storage.fetch_reference(); } @@ -120,7 +120,7 @@ template class Result T release_value() { - check(has_value()); + expect(has_value(), "Result::release_value() called on a Result that holds an error"); T item = m_storage.fetch_reference(); m_has_value = false; m_storage.destroy(); @@ -221,31 +221,31 @@ template <> class Result int error() { - check(has_error()); + expect(has_error(), "Result::error() called on a Result that holds a value"); return m_error; } Error release_error() { - check(has_error()); + expect(has_error(), "Result::release_error() called on a Result that holds a value"); return {m_error}; } const char* error_string() { - check(has_error()); + expect(has_error(), "Result::error_string() called on a Result that holds a value"); return ::error_string(m_error); } void value() { - check(has_value()); + expect(has_value(), "Result::value() called on a Result that holds an error"); return; } void release_value() { - check(has_value()); + expect(has_value(), "Result::release_value() called on a Result that holds an error"); return; } From bed29e71af0464f12c641bbc16ba7b83c4aa536d Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:25:16 +0100 Subject: [PATCH 111/407] Replace some uses of check() with expect() --- kernel/src/arch/x86_64/CPU.cpp | 4 ++-- kernel/src/memory/Heap.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index a4cbb6c2..d5a7ee3d 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -80,7 +80,7 @@ static void set_base(GDTEntry* entry, u32 base) static void set_limit(GDTEntry* entry, u32 limit) { - check(limit <= 0xFFFFF); + expect(limit <= 0xFFFFF, "Limit too big for a GDT entry"); entry->limit0 = limit & 0xFFFF; entry->limit1_flags = (entry->limit1_flags & 0xF0) | ((limit >> 16) & 0xF); } @@ -208,7 +208,7 @@ struct IDTR static void idt_add_handler(short num, void* handler, u8 type_attr) { check(handler != nullptr); - check(num < 256); + expect(num < 256, "IDT can only hold up to 256 entries"); IDTEntry* entry_for_handler = &idt[num]; entry_for_handler->selector = 0x08; entry_for_handler->type_attr = type_attr; diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 54dbb9f0..d98a205d 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -64,7 +64,7 @@ static bool is_block_free(HeapBlock* block) static usize space_available(HeapBlock* block) { - check(!is_block_free(block)); + expect(!is_block_free(block), "Attempting to split a free block"); return block->full_size - block->req_size; } From cdbed6970a08670b601187a4dc824da9ab74aa24 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:32:34 +0100 Subject: [PATCH 112/407] Result: Add expect_ variants of value() and release_value() --- luna/Result.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/luna/Result.h b/luna/Result.h index ed99a04b..297fdec1 100644 --- a/luna/Result.h +++ b/luna/Result.h @@ -105,6 +105,12 @@ template class Result return m_storage.fetch_reference(); } + T expect_value(const char* reason) + { + expect(has_value(), reason); + return m_storage.fetch_reference(); + } + T value_or(T other) { if (has_value()) return m_storage.fetch_reference(); @@ -127,6 +133,15 @@ template class Result return move(item); } + T expect_release_value(const char* reason) + { + expect(has_value(), reason); + T item = m_storage.fetch_reference(); + m_has_value = false; + m_storage.destroy(); + return move(item); + } + ~Result() { if (has_value()) m_storage.destroy(); @@ -177,6 +192,7 @@ template class Result fetch_reference().~T(); } }; + Storage m_storage; int m_error; bool m_has_error; @@ -243,12 +259,24 @@ template <> class Result return; } + void expect_value(const char* reason) + { + expect(has_value(), reason); + return; + } + void release_value() { expect(has_value(), "Result::release_value() called on a Result that holds an error"); return; } + void expect_release_value(const char* reason) + { + expect(has_value(), reason); + return; + } + private: int m_error; bool m_has_error; @@ -262,5 +290,5 @@ template <> class Result ({ \ auto _expr_rc = (expr); \ if (_expr_rc.has_error()) return _expr_rc.release_error(); \ - _expr_rc.release_value(); \ + _expr_rc.expect_release_value("sanity check failed: has_error() returned false, yet result has no value"); \ }) From c7ab6bc2d3942035be500f2a9a80c8ce625c80d2 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:42:43 +0100 Subject: [PATCH 113/407] Reorganize the luna/ directory so that headers aren't in the top level include path --- kernel/src/Log.cpp | 2 +- kernel/src/Log.h | 4 ++-- kernel/src/arch/CPU.h | 2 +- kernel/src/arch/MMU.h | 2 +- kernel/src/arch/Serial.cpp | 2 +- kernel/src/arch/Serial.h | 4 ++-- kernel/src/arch/Timer.cpp | 2 +- kernel/src/arch/Timer.h | 2 +- kernel/src/arch/x86_64/CPU.cpp | 6 +++--- kernel/src/arch/x86_64/CPU.h | 2 +- kernel/src/arch/x86_64/IO.h | 2 +- kernel/src/arch/x86_64/MMU.cpp | 4 ++-- kernel/src/boot/Init.cpp | 2 +- kernel/src/main.cpp | 2 +- kernel/src/memory/Heap.cpp | 6 +++--- kernel/src/memory/Heap.h | 4 ++-- kernel/src/memory/MemoryManager.cpp | 8 ++++---- kernel/src/memory/MemoryManager.h | 4 ++-- kernel/src/video/BuiltinFont.h | 2 +- kernel/src/video/Framebuffer.h | 2 +- kernel/src/video/TextConsole.cpp | 4 ++-- kernel/src/video/TextConsole.h | 6 +++--- luna/CMakeLists.txt | 16 ++++++++-------- luna/{ => include/luna}/Alignment.h | 0 luna/{ => include/luna}/Attributes.h | 0 luna/{ => include/luna}/CType.h | 0 luna/{ => include/luna}/Check.h | 2 +- luna/{ => include/luna}/Format.h | 4 ++-- luna/{ => include/luna}/Move.h | 0 luna/{ => include/luna}/NumberParsing.h | 3 +-- luna/{ => include/luna}/PlacementNew.h | 2 +- luna/{ => include/luna}/Result.h | 10 +++++----- luna/{ => include/luna}/String.h | 2 +- luna/{ => include/luna}/SystemError.h | 0 luna/{ => include/luna}/Types.h | 0 luna/{ => include/luna}/Units.h | 2 +- luna/{ => src}/Check.cpp | 2 +- luna/{ => src}/Format.cpp | 6 +++--- luna/{ => src}/NumberParsing.cpp | 3 ++- luna/{ => src}/String.cpp | 2 +- luna/{ => src}/SystemError.cpp | 2 +- luna/{ => src}/Units.cpp | 4 ++-- tools/check-formatting.sh | 3 ++- tools/check-stdint.sh | 3 ++- tools/replace-stdint.sh | 3 ++- tools/run-clang-format.sh | 3 ++- 46 files changed, 75 insertions(+), 71 deletions(-) rename luna/{ => include/luna}/Alignment.h (100%) rename luna/{ => include/luna}/Attributes.h (100%) rename luna/{ => include/luna}/CType.h (100%) rename luna/{ => include/luna}/Check.h (95%) rename luna/{ => include/luna}/Format.h (83%) rename luna/{ => include/luna}/Move.h (100%) rename luna/{ => include/luna}/NumberParsing.h (84%) rename luna/{ => include/luna}/PlacementNew.h (72%) rename luna/{ => include/luna}/Result.h (97%) rename luna/{ => include/luna}/String.h (91%) rename luna/{ => include/luna}/SystemError.h (100%) rename luna/{ => include/luna}/Types.h (100%) rename luna/{ => include/luna}/Units.h (72%) rename luna/{ => src}/Check.cpp (79%) rename luna/{ => src}/Format.cpp (99%) rename luna/{ => src}/NumberParsing.cpp (96%) rename luna/{ => src}/String.cpp (97%) rename luna/{ => src}/SystemError.cpp (98%) rename luna/{ => src}/Units.cpp (88%) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 67704922..b4f14cc7 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -3,7 +3,7 @@ #include "arch/Serial.h" #include "arch/Timer.h" #include "video/TextConsole.h" -#include +#include static bool g_debug_enabled = true; static bool g_serial_enabled = true; diff --git a/kernel/src/Log.h b/kernel/src/Log.h index 0c0b9ab8..10eaed9f 100644 --- a/kernel/src/Log.h +++ b/kernel/src/Log.h @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include #include enum class LogLevel diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index 1558551a..abf826e3 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -1,5 +1,5 @@ #pragma once -#include +#include struct Registers; diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index d15c7b87..f18e0302 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -1,5 +1,5 @@ #pragma once -#include +#include struct PageDirectory; diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index 2dc834ac..2282d157 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -1,6 +1,6 @@ #include "arch/Serial.h" #include "arch/CPU.h" -#include +#include namespace Serial { diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h index 097a7408..0efc6e47 100644 --- a/kernel/src/arch/Serial.h +++ b/kernel/src/arch/Serial.h @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include template class Result; diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index d2ac041e..9c0606db 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -2,7 +2,7 @@ #include "Log.h" #include "arch/Serial.h" #include "boot/bootboot.h" -#include +#include static u64 timer_ticks = 0; static u64 boot_timestamp; diff --git a/kernel/src/arch/Timer.h b/kernel/src/arch/Timer.h index d2895de3..21c389d7 100644 --- a/kernel/src/arch/Timer.h +++ b/kernel/src/arch/Timer.h @@ -1,5 +1,5 @@ #pragma once -#include +#include extern const usize ARCH_TIMER_FREQ; // How many timer ticks in one millisecond? diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index d5a7ee3d..306117d5 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -3,10 +3,10 @@ #include "arch/Serial.h" #include "arch/Timer.h" #include "arch/x86_64/IO.h" -#include -#include -#include #include +#include +#include +#include extern "C" void enable_sse(); extern "C" void enable_write_protect(); diff --git a/kernel/src/arch/x86_64/CPU.h b/kernel/src/arch/x86_64/CPU.h index f156e80d..a4e8d52f 100644 --- a/kernel/src/arch/x86_64/CPU.h +++ b/kernel/src/arch/x86_64/CPU.h @@ -1,5 +1,5 @@ #include "arch/CPU.h" -#include +#include struct Registers // Saved CPU registers for x86-64 { diff --git a/kernel/src/arch/x86_64/IO.h b/kernel/src/arch/x86_64/IO.h index 05c6acf9..5f5a6fc2 100644 --- a/kernel/src/arch/x86_64/IO.h +++ b/kernel/src/arch/x86_64/IO.h @@ -1,5 +1,5 @@ #pragma once -#include +#include namespace IO { diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index a36a038e..12cbd372 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -1,7 +1,7 @@ #include "arch/MMU.h" #include "memory/MemoryManager.h" -#include -#include +#include +#include #define PAGE_SIZE 4096 diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 0654f8a9..18a3e8d0 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -5,7 +5,7 @@ #include "boot/bootboot.h" #include "memory/MemoryManager.h" #include "video/Framebuffer.h" -#include +#include extern BOOTBOOT bootboot; diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 3e5cba2c..9c804132 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -8,7 +8,7 @@ #include "memory/Heap.h" #include "memory/MemoryManager.h" #include "video/TextConsole.h" -#include +#include Result init() { diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index d98a205d..6c7a4bad 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -3,9 +3,9 @@ #include "arch/MMU.h" #include "arch/Serial.h" #include "memory/MemoryManager.h" -#include -#include -#include +#include +#include +#include static constexpr int BLOCK_USED = 1 << 0; static constexpr int BLOCK_START_MEM = 1 << 1; diff --git a/kernel/src/memory/Heap.h b/kernel/src/memory/Heap.h index 251e039c..80d4b410 100644 --- a/kernel/src/memory/Heap.h +++ b/kernel/src/memory/Heap.h @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include Result kmalloc(usize size); Result kcalloc(usize nmemb, usize size); diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 65d9006d..9bbd204c 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -2,10 +2,10 @@ #include "Log.h" #include "arch/MMU.h" #include "boot/bootboot.h" -#include -#include -#include -#include +#include +#include +#include +#include extern BOOTBOOT bootboot; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index f311f412..8179e12e 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include namespace MemoryManager { diff --git a/kernel/src/video/BuiltinFont.h b/kernel/src/video/BuiltinFont.h index a2a2e478..cadd6908 100644 --- a/kernel/src/video/BuiltinFont.h +++ b/kernel/src/video/BuiltinFont.h @@ -1,5 +1,5 @@ #pragma once -#include +#include // FIXME: Load a font from disk/initrd. diff --git a/kernel/src/video/Framebuffer.h b/kernel/src/video/Framebuffer.h index 9105f315..033ac127 100644 --- a/kernel/src/video/Framebuffer.h +++ b/kernel/src/video/Framebuffer.h @@ -1,5 +1,5 @@ #pragma once -#include +#include namespace Framebuffer { diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index 5e6b46f3..8384eec5 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -1,8 +1,8 @@ #include "video/TextConsole.h" #include "boot/bootboot.h" #include "video/Framebuffer.h" -#include -#include +#include +#include extern BOOTBOOT bootboot; diff --git a/kernel/src/video/TextConsole.h b/kernel/src/video/TextConsole.h index 62dfb51f..d502e485 100644 --- a/kernel/src/video/TextConsole.h +++ b/kernel/src/video/TextConsole.h @@ -1,7 +1,7 @@ #pragma once -#include -#include -#include +#include +#include +#include namespace TextConsole { diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 8360aef4..0bb23007 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -1,14 +1,14 @@ set(FREESTANDING_SOURCES - Format.cpp - NumberParsing.cpp - String.cpp - Units.cpp - SystemError.cpp + src/Format.cpp + src/NumberParsing.cpp + src/String.cpp + src/Units.cpp + src/SystemError.cpp ) set(SOURCES ${FREESTANDING_SOURCES} - Check.cpp + src/Check.cpp ) add_library(luna-freestanding ${FREESTANDING_SOURCES}) @@ -26,7 +26,7 @@ target_compile_options(luna-freestanding PRIVATE -mno-red-zone) target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) endif() -target_include_directories(luna-freestanding PUBLIC ${LUNA_ROOT}/luna) +target_include_directories(luna-freestanding PUBLIC include/) set_target_properties(luna-freestanding PROPERTIES CXX_STANDARD 20) add_library(luna ${SOURCES}) @@ -35,5 +35,5 @@ target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-se target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) -target_include_directories(luna PUBLIC ${LUNA_ROOT}/luna) +target_include_directories(luna PUBLIC include/) set_target_properties(luna PROPERTIES CXX_STANDARD 20) \ No newline at end of file diff --git a/luna/Alignment.h b/luna/include/luna/Alignment.h similarity index 100% rename from luna/Alignment.h rename to luna/include/luna/Alignment.h diff --git a/luna/Attributes.h b/luna/include/luna/Attributes.h similarity index 100% rename from luna/Attributes.h rename to luna/include/luna/Attributes.h diff --git a/luna/CType.h b/luna/include/luna/CType.h similarity index 100% rename from luna/CType.h rename to luna/include/luna/CType.h diff --git a/luna/Check.h b/luna/include/luna/Check.h similarity index 95% rename from luna/Check.h rename to luna/include/luna/Check.h index 429e65af..fce54b96 100644 --- a/luna/Check.h +++ b/luna/include/luna/Check.h @@ -1,5 +1,5 @@ #pragma once -#include +#include extern _noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr); diff --git a/luna/Format.h b/luna/include/luna/Format.h similarity index 83% rename from luna/Format.h rename to luna/include/luna/Format.h index 3ad779f2..245979a7 100644 --- a/luna/Format.h +++ b/luna/include/luna/Format.h @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include #include typedef Result (*callback_t)(char, void*); diff --git a/luna/Move.h b/luna/include/luna/Move.h similarity index 100% rename from luna/Move.h rename to luna/include/luna/Move.h diff --git a/luna/NumberParsing.h b/luna/include/luna/NumberParsing.h similarity index 84% rename from luna/NumberParsing.h rename to luna/include/luna/NumberParsing.h index c3c83fce..774250a1 100644 --- a/luna/NumberParsing.h +++ b/luna/include/luna/NumberParsing.h @@ -1,6 +1,5 @@ #pragma once -#include -#include +#include usize _atou(const char** str); isize _atos(const char** str); diff --git a/luna/PlacementNew.h b/luna/include/luna/PlacementNew.h similarity index 72% rename from luna/PlacementNew.h rename to luna/include/luna/PlacementNew.h index 4ecf821c..91a20f39 100644 --- a/luna/PlacementNew.h +++ b/luna/include/luna/PlacementNew.h @@ -1,5 +1,5 @@ #pragma once -#include +#include inline void* operator new(usize, void* p) noexcept { diff --git a/luna/Result.h b/luna/include/luna/Result.h similarity index 97% rename from luna/Result.h rename to luna/include/luna/Result.h index 297fdec1..a923bff4 100644 --- a/luna/Result.h +++ b/luna/include/luna/Result.h @@ -1,9 +1,9 @@ #pragma once -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include struct Error { diff --git a/luna/String.h b/luna/include/luna/String.h similarity index 91% rename from luna/String.h rename to luna/include/luna/String.h index 1e2b9a81..0dddc00b 100644 --- a/luna/String.h +++ b/luna/include/luna/String.h @@ -1,5 +1,5 @@ #pragma once -#include +#include extern "C" { diff --git a/luna/SystemError.h b/luna/include/luna/SystemError.h similarity index 100% rename from luna/SystemError.h rename to luna/include/luna/SystemError.h diff --git a/luna/Types.h b/luna/include/luna/Types.h similarity index 100% rename from luna/Types.h rename to luna/include/luna/Types.h diff --git a/luna/Units.h b/luna/include/luna/Units.h similarity index 72% rename from luna/Units.h rename to luna/include/luna/Units.h index c12aac63..854c18b8 100644 --- a/luna/Units.h +++ b/luna/include/luna/Units.h @@ -1,4 +1,4 @@ #pragma once -#include +#include Result to_dynamic_unit(usize value, char* buffer, usize max); \ No newline at end of file diff --git a/luna/Check.cpp b/luna/src/Check.cpp similarity index 79% rename from luna/Check.cpp rename to luna/src/Check.cpp index e464ca86..4f522f79 100644 --- a/luna/Check.cpp +++ b/luna/src/Check.cpp @@ -1,4 +1,4 @@ -#include +#include _weak _noreturn bool __check_failed(const char*, const char*, const char*, const char*) { diff --git a/luna/Format.cpp b/luna/src/Format.cpp similarity index 99% rename from luna/Format.cpp rename to luna/src/Format.cpp index f3b1c62a..0231b3a2 100644 --- a/luna/Format.cpp +++ b/luna/src/Format.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include +#include +#include extern "C" usize strlen(const char*); diff --git a/luna/NumberParsing.cpp b/luna/src/NumberParsing.cpp similarity index 96% rename from luna/NumberParsing.cpp rename to luna/src/NumberParsing.cpp index 0e46b314..0790ad9f 100644 --- a/luna/NumberParsing.cpp +++ b/luna/src/NumberParsing.cpp @@ -1,4 +1,5 @@ -#include +#include +#include // This function assumes you have called is_valid_digit_for_base() to validate the digit first. static isize parse_digit_unchecked(char c) diff --git a/luna/String.cpp b/luna/src/String.cpp similarity index 97% rename from luna/String.cpp rename to luna/src/String.cpp index abada229..bd174d93 100644 --- a/luna/String.cpp +++ b/luna/src/String.cpp @@ -1,4 +1,4 @@ -#include +#include extern "C" { diff --git a/luna/SystemError.cpp b/luna/src/SystemError.cpp similarity index 98% rename from luna/SystemError.cpp rename to luna/src/SystemError.cpp index 00719b56..2e1f63ad 100644 --- a/luna/SystemError.cpp +++ b/luna/src/SystemError.cpp @@ -1,4 +1,4 @@ -#include +#include const char* error_string(int error) { diff --git a/luna/Units.cpp b/luna/src/Units.cpp similarity index 88% rename from luna/Units.cpp rename to luna/src/Units.cpp index 1ce0208c..fa2a0e1b 100644 --- a/luna/Units.cpp +++ b/luna/src/Units.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include Result to_dynamic_unit(usize value, char* buffer, size_t max) { diff --git a/tools/check-formatting.sh b/tools/check-formatting.sh index bea7f2a8..029a3a05 100755 --- a/tools/check-formatting.sh +++ b/tools/check-formatting.sh @@ -5,7 +5,8 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm")) -SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt")) +SOURCES+=($(find luna/src -type f)) +SOURCES+=($(find luna/include/luna -type f)) ALL_OK=1 diff --git a/tools/check-stdint.sh b/tools/check-stdint.sh index bf78b6d2..8bd9cfb4 100755 --- a/tools/check-stdint.sh +++ b/tools/check-stdint.sh @@ -6,7 +6,8 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm" | grep -v "bootboot.h")) -SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt" | grep -v "Types.h")) +SOURCES+=($(find luna/src -type f)) +SOURCES+=($(find luna/include/luna -type f | grep -v "Types.h")) SUCCESS=1 diff --git a/tools/replace-stdint.sh b/tools/replace-stdint.sh index 2fa4d5a2..2b42c24a 100755 --- a/tools/replace-stdint.sh +++ b/tools/replace-stdint.sh @@ -6,7 +6,8 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm" | grep -v "bootboot.h")) -SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt" | grep -v "Types.h")) +SOURCES+=($(find luna/src -type f)) +SOURCES+=($(find luna/include/luna -type f | grep -v "Types.h")) for f in ${SOURCES[@]} do diff --git a/tools/run-clang-format.sh b/tools/run-clang-format.sh index 2e69fa67..eed14fac 100755 --- a/tools/run-clang-format.sh +++ b/tools/run-clang-format.sh @@ -6,7 +6,8 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm")) -SOURCES+=($(find luna -type f | grep -v "CMakeLists.txt")) +SOURCES+=($(find luna/src -type f)) +SOURCES+=($(find luna/include/luna -type f)) for f in ${SOURCES[@]} do From b8239698db740a3125dc91c611051560d965be39 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:47:08 +0100 Subject: [PATCH 114/407] Add descriptions in CMakeLists --- kernel/CMakeLists.txt | 2 ++ luna/CMakeLists.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 28007d7f..feedd900 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,3 +1,5 @@ +# The Moon kernel for Luna. + set(SOURCES src/main.cpp src/Log.cpp diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 0bb23007..73c64b07 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -1,3 +1,5 @@ +# The miscellaneous library shared between the Luna kernel and userspace, with stuff such as custom types, common routines and data structures. + set(FREESTANDING_SOURCES src/Format.cpp src/NumberParsing.cpp From adb2c2ab41c0f23fb1c794335ff5ef23ffa92cf9 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:52:49 +0100 Subject: [PATCH 115/407] Add kernel-side new and delete --- kernel/src/memory/Heap.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 6c7a4bad..1189b8dc 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -364,4 +364,34 @@ void dump_heap_usage() kdbgln("-- Total memory allocated for heap: %zu bytes", alloc_total); kdbgln("-- Heap memory in use by the kernel: %zu bytes", alloc_used); +} + +void* operator new(usize size) +{ + return kmalloc(size).expect_release_value("FIXME: Kernel new panics on OOM, since there are no exceptions"); +} + +void* operator new[](usize size) +{ + return kmalloc(size).expect_release_value("FIXME: Kernel new[] panics on OOM, since there are no exceptions"); +} + +void operator delete(void* p) +{ + kfree(p); +} + +void operator delete[](void* p) +{ + kfree(p); +} + +void operator delete(void* p, usize) +{ + kfree(p); +} + +void operator delete[](void* p, usize) +{ + kfree(p); } \ No newline at end of file From 96b32f5a939237db167c6f2138fc819c15b8ff7c Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:55:32 +0100 Subject: [PATCH 116/407] Please use make and destroy instead of new and delete Those are there only for common stuff (in the Luna library) that needs an environment-agnostic way of allocating memory. new and delete are standard, thus we should use those. --- kernel/src/memory/Heap.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 1189b8dc..ceb96406 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -368,12 +368,14 @@ void dump_heap_usage() void* operator new(usize size) { - return kmalloc(size).expect_release_value("FIXME: Kernel new panics on OOM, since there are no exceptions"); + return kmalloc(size).expect_release_value("FIXME: Kernel new panics on OOM, since there are no exceptions. If " + "possible, use make for error propagation."); } void* operator new[](usize size) { - return kmalloc(size).expect_release_value("FIXME: Kernel new[] panics on OOM, since there are no exceptions"); + return kmalloc(size).expect_release_value("FIXME: Kernel new[] panics on OOM, since there are no exceptions. If " + "possible, use make for error propagation."); } void operator delete(void* p) From 22019ac6b23f45e4423c58ca28fe2e450b57cbf4 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:57:43 +0100 Subject: [PATCH 117/407] Print the error instead --- kernel/src/memory/Heap.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index ceb96406..f8fd6210 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -368,14 +368,16 @@ void dump_heap_usage() void* operator new(usize size) { - return kmalloc(size).expect_release_value("FIXME: Kernel new panics on OOM, since there are no exceptions. If " - "possible, use make for error propagation."); + auto rc = kmalloc(size); + if (rc.has_error()) { expect(false, rc.error_string()); } + return rc.release_value(); } void* operator new[](usize size) { - return kmalloc(size).expect_release_value("FIXME: Kernel new[] panics on OOM, since there are no exceptions. If " - "possible, use make for error propagation."); + auto rc = kmalloc(size); + if (rc.has_error()) { expect(false, rc.error_string()); } + return rc.release_value(); } void operator delete(void* p) From f8120e01c00ce4dedfaf35393c787dfb8c2aabe4 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 12:58:37 +0100 Subject: [PATCH 118/407] Panic in delete as well --- kernel/src/memory/Heap.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index f8fd6210..4259e61b 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -382,20 +382,28 @@ void* operator new[](usize size) void operator delete(void* p) { - kfree(p); + auto rc = kfree(p); + if (rc.has_error()) { expect(false, rc.error_string()); } + return rc.release_value(); } void operator delete[](void* p) { - kfree(p); + auto rc = kfree(p); + if (rc.has_error()) { expect(false, rc.error_string()); } + return rc.release_value(); } void operator delete(void* p, usize) { - kfree(p); + auto rc = kfree(p); + if (rc.has_error()) { expect(false, rc.error_string()); } + return rc.release_value(); } void operator delete[](void* p, usize) { - kfree(p); + auto rc = kfree(p); + if (rc.has_error()) { expect(false, rc.error_string()); } + return rc.release_value(); } \ No newline at end of file From bde3d55eb2b15b822602a8b41783ecf363e2b872 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 13:38:48 +0100 Subject: [PATCH 119/407] Remove escape from comment --- kernel/src/memory/Heap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 4259e61b..41ddf176 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -11,7 +11,7 @@ static constexpr int BLOCK_USED = 1 << 0; static constexpr int BLOCK_START_MEM = 1 << 1; static constexpr int BLOCK_END_MEM = 1 << 2; -static constexpr usize BLOCK_MAGIC = 0x6d616c6c6f63210a; // echo "malloc\!" | hexdump -C +static constexpr usize BLOCK_MAGIC = 0x6d616c6c6f63210a; // echo 'malloc!' | hexdump -C (includes a newline) static constexpr usize BLOCK_DEAD = 0xdeaddeaddeaddead; static constexpr usize MINIMUM_PAGES_PER_ALLOCATION = 4; From ee76bdf84d0f8da4cdc3cb18629d149eb820a624 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 13:41:14 +0100 Subject: [PATCH 120/407] Add sanity check --- kernel/src/memory/Heap.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 41ddf176..dfd0ae5f 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -185,7 +185,9 @@ Result kmalloc(usize size) block->next = block->last = nullptr; heap_start = block; - if (!heap_end) heap_end = heap_start; + check(!heap_end); + + heap_end = heap_start; } HeapBlock* block = heap_start; From 5aa2d1fa1801156f7f4fd5ef3586806b77fba897 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 15:14:07 +0100 Subject: [PATCH 121/407] Add a Bitmap class to provide common functionality and use that in the MemoryManager --- kernel/src/boot/Init.cpp | 2 +- kernel/src/memory/MemoryManager.cpp | 103 ++++++++++++++++------------ luna/CMakeLists.txt | 1 + luna/include/luna/Bitmap.h | 43 ++++++++++++ luna/src/Bitmap.cpp | 88 ++++++++++++++++++++++++ 5 files changed, 192 insertions(+), 45 deletions(-) create mode 100644 luna/include/luna/Bitmap.h create mode 100644 luna/src/Bitmap.cpp diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 18a3e8d0..c72f8aa4 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -31,5 +31,5 @@ void Init::early_init() CPU::platform_init(); - MemoryManager::protect_kernel_sections().release_value(); + MemoryManager::protect_kernel_sections().expect_release_value("We should succeed to protect sections"); } \ No newline at end of file diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 9bbd204c..d788befe 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -1,11 +1,14 @@ #include "memory/MemoryManager.h" #include "Log.h" +#include "arch/CPU.h" #include "arch/MMU.h" #include "boot/bootboot.h" #include +#include #include #include #include +#include extern BOOTBOOT bootboot; @@ -14,34 +17,37 @@ extern u8 end_of_kernel_rodata[1]; extern u8 start_of_kernel_data[1]; extern u8 end_of_kernel_data[1]; -static bool page_bitmap_read(u64 index); -static void page_bitmap_set(u64 index, bool value); - static u64 free_mem = 0; static u64 used_mem = 0; static u64 reserved_mem = 0; -static char* page_bitmap_addr = nullptr; -static char* page_virtual_bitmap_addr = nullptr; -static u64 page_bitmap_size; - static u64 start_index = 0; -static bool page_bitmap_read(u64 index) -{ - return (page_virtual_bitmap_addr[index / 8] & (0b10000000 >> (index % 8))) > 0; -} - -static void page_bitmap_set(u64 index, bool value) -{ - u64 byte_index = index / 8; - u8 mask = 0b10000000 >> (index % 8); - page_virtual_bitmap_addr[byte_index] &= (u8)(~mask); - if (value) { page_virtual_bitmap_addr[byte_index] |= mask; } -} +static Bitmap g_frame_bitmap; #define CHECK_PAGE_ALIGNED(address) check(is_aligned(address, ARCH_PAGE_SIZE)) +static usize get_physical_address_space_size() +{ + MMapEnt* ptr = &bootboot.mmap; + u64 biggest_ptr = 0; + u64 biggest_ptr_size = 0; + u64 mmap_entries = (bootboot.size - 128) / 16; + for (u64 i = 0; i < mmap_entries; i++) + { + if (MMapEnt_Ptr(ptr) > biggest_ptr) + { + biggest_ptr = MMapEnt_Ptr(ptr); + biggest_ptr_size = MMapEnt_Size(ptr); + } + + ptr++; + } + + return biggest_ptr + biggest_ptr_size; // This would be the address at the end of the last entry, thus the whole + // address space that was passed to us. +} + namespace MemoryManager { Result protect_kernel_sections() @@ -57,12 +63,12 @@ namespace MemoryManager return {}; } - void init_physical_allocator() + void init_physical_frame_allocator() { u64 total_mem = 0; - void* biggest_memory_block = nullptr; - u64 biggest_memory_block_size = 0; + void* biggest_usable_memory_block = nullptr; + u64 biggest_usable_memory_block_size = 0; // walk the memory map MMapEnt* ptr = &bootboot.mmap; @@ -76,53 +82,62 @@ namespace MemoryManager ptr++; continue; } - if (size > biggest_memory_block_size) + if (size > biggest_usable_memory_block_size) { - biggest_memory_block = (void*)MMapEnt_Ptr(ptr); - biggest_memory_block_size = MMapEnt_Size(ptr); + biggest_usable_memory_block = (void*)MMapEnt_Ptr(ptr); + biggest_usable_memory_block_size = MMapEnt_Size(ptr); } ptr++; } - page_bitmap_addr = (char*)biggest_memory_block; - page_virtual_bitmap_addr = page_bitmap_addr; // we'll map this to virtual memory as soon as the MMU is ready - if ((total_mem / ARCH_PAGE_SIZE / 8) >= biggest_memory_block_size) + // The entire physical address space. May contain inexistent memory holes, thus differs from total_mem which + // only counts existent memory. Our bitmap needs to have space for all of the physical address space, since + // usable addresses will be scattered across it. + usize physical_address_space_size = get_physical_address_space_size(); + + char* frame_bitmap_addr = (char*)biggest_usable_memory_block; + usize frame_bitmap_size = physical_address_space_size / ARCH_PAGE_SIZE / 8 + 1; + + // This should never happen, unless memory is very fragmented. Usually there is always a very big block of + // usable memory and then some tiny blocks around it. + if (frame_bitmap_size >= biggest_usable_memory_block_size) [[unlikely]] { - kerrorln("ERROR: No single memory block is enough to hold the page bitmap"); - for (;;) - ; + kerrorln("ERROR: No single memory block is enough to hold the frame bitmap"); + CPU::efficient_halt(); } - page_bitmap_size = total_mem / ARCH_PAGE_SIZE / 8 + 1; - memset(page_bitmap_addr, 0xFF, page_bitmap_size); + g_frame_bitmap.initialize(frame_bitmap_addr, frame_bitmap_size); + + g_frame_bitmap.clear(true); // Set all pages to used/reserved by default, then clear out the free ones ptr = &bootboot.mmap; for (u64 i = 0; i < mmap_entries; i++) { u64 index = MMapEnt_Ptr(ptr) / ARCH_PAGE_SIZE; + u64 pages = MMapEnt_Size(ptr) / ARCH_PAGE_SIZE; if (!MMapEnt_IsFree(ptr)) { reserved_mem += MMapEnt_Size(ptr); } else { free_mem += MMapEnt_Size(ptr); - for (u64 j = 0; j < (MMapEnt_Size(ptr) / ARCH_PAGE_SIZE); j++) { page_bitmap_set(index + j, false); } + g_frame_bitmap.clear_region(index, pages, false); } ptr++; } - lock_frames((u64)page_bitmap_addr, page_bitmap_size / ARCH_PAGE_SIZE + 1); + lock_frames((u64)frame_bitmap_addr, frame_bitmap_size / ARCH_PAGE_SIZE + 1); } void init() { - init_physical_allocator(); + init_physical_frame_allocator(); MMU::setup_initial_page_directory(); } void lock_frame(u64 frame) { const u64 index = ((u64)frame) / ARCH_PAGE_SIZE; - if (page_bitmap_read(index)) return; - page_bitmap_set(index, true); + if (g_frame_bitmap.get(index)) return; + g_frame_bitmap.set(index, true); used_mem += ARCH_PAGE_SIZE; free_mem -= ARCH_PAGE_SIZE; } @@ -134,10 +149,10 @@ namespace MemoryManager Result alloc_frame() { - for (u64 index = start_index; index < (page_bitmap_size * 8); index++) + for (u64 index = start_index; index < g_frame_bitmap.size(); index++) { - if (page_bitmap_read(index)) continue; - page_bitmap_set(index, true); + if (g_frame_bitmap.get(index)) continue; + g_frame_bitmap.set(index, true); start_index = index + 1; free_mem -= ARCH_PAGE_SIZE; used_mem += ARCH_PAGE_SIZE; @@ -150,9 +165,9 @@ namespace MemoryManager Result free_frame(u64 frame) { const u64 index = frame / ARCH_PAGE_SIZE; - if (index > (page_bitmap_size * 8)) return err(EFAULT); - if (!page_bitmap_read(index)) return err(EFAULT); - page_bitmap_set(index, false); + if (index > g_frame_bitmap.size()) return err(EFAULT); + if (!g_frame_bitmap.get(index)) return err(EFAULT); + g_frame_bitmap.set(index, false); used_mem -= ARCH_PAGE_SIZE; free_mem += ARCH_PAGE_SIZE; if (start_index > index) start_index = index; diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 73c64b07..1ac0c37f 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -6,6 +6,7 @@ set(FREESTANDING_SOURCES src/String.cpp src/Units.cpp src/SystemError.cpp + src/Bitmap.cpp ) set(SOURCES diff --git a/luna/include/luna/Bitmap.h b/luna/include/luna/Bitmap.h new file mode 100644 index 00000000..3260853d --- /dev/null +++ b/luna/include/luna/Bitmap.h @@ -0,0 +1,43 @@ +#pragma once +#include + +class Bitmap +{ + public: + Bitmap(); + Bitmap(void* location, usize size_in_bytes); + + void initialize(void* location, usize size_in_bytes); + void* move(void* new_location, usize new_location_size_in_bytes); + + void set(usize index, bool value); + bool get(usize index); + + // size() returns size in bits! If you want the size in bytes, call size_in_bytes(). + usize size() + { + return m_size_in_bytes * 8; + } + + usize size_in_bytes() + { + return m_size_in_bytes; + } + + void* location() + { + return (void*)m_location; + } + + bool initialized() + { + return m_location; + } + + void clear(bool value); + void clear_region(usize start, usize bits, bool value); + + private: + char* m_location = nullptr; + usize m_size_in_bytes = 0; +}; \ No newline at end of file diff --git a/luna/src/Bitmap.cpp b/luna/src/Bitmap.cpp new file mode 100644 index 00000000..e130d191 --- /dev/null +++ b/luna/src/Bitmap.cpp @@ -0,0 +1,88 @@ +#include +#include +#include + +Bitmap::Bitmap() +{ +} + +Bitmap::Bitmap(void* location, usize size_in_bytes) : m_location((char*)location), m_size_in_bytes(size_in_bytes) +{ +} + +void Bitmap::initialize(void* location, usize size_in_bytes) +{ + m_location = (char*)location; + m_size_in_bytes = size_in_bytes; +} + +void* Bitmap::move(void* new_location, usize new_location_size_in_bytes) +{ + expect(initialized(), "Bitmap was never initialized"); + + if (new_location_size_in_bytes > m_size_in_bytes) memcpy(new_location, m_location, m_size_in_bytes); + else + memcpy(new_location, m_location, new_location_size_in_bytes); + + void* old_location = (void*)m_location; + + m_location = (char*)new_location; + m_size_in_bytes = new_location_size_in_bytes; + + return old_location; +} + +void Bitmap::set(usize index, bool value) +{ + expect(initialized(), "Bitmap was never initialized"); + expect(index < size(), "Bitmap access out of range"); + u64 byte_index = index / 8; + u8 bit_mask = 0b10000000 >> (index % 8); + m_location[byte_index] &= (u8)(~bit_mask); + if (value) { m_location[byte_index] |= bit_mask; } +} + +bool Bitmap::get(usize index) +{ + expect(initialized(), "Bitmap was never initialized"); + expect(index < size(), "Bitmap access out of range"); + usize byte_index = index / 8; + usize bit_mask = 0b10000000 >> (index % 8); + return (m_location[byte_index] & bit_mask) > 0; +} + +void Bitmap::clear(bool value) +{ + expect(initialized(), "Bitmap was never initialized"); + u8 value_byte = value ? 0xff : 0; + memset(m_location, value_byte, m_size_in_bytes); +} + +void Bitmap::clear_region(usize start, usize bits, bool value) +{ + expect(initialized(), "Bitmap was never initialized"); + expect((start + bits) <= size(), "Bitmap clear out of range"); + + u8 value_byte = value ? 0xff : 0; + + // Set individual bits while not on a byte boundary. + while ((start % 8) && bits--) + { + set(start, value); + start++; + } + + // Clear out the rest in bytes. + usize bytes = bits / 8; + + memset(&m_location[start / 8], value_byte, bytes); + start += bytes * 8; + bits -= bytes * 8; + + // Set the remaining individual bits. + while (bits--) + { + set(start, value); + start++; + } +} \ No newline at end of file From 5f6c48bd123be3c2ae8d9d041beef78404a4200c Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 15:45:13 +0100 Subject: [PATCH 122/407] Use a friendlier way of iterating over the memory map --- kernel/CMakeLists.txt | 1 + kernel/src/memory/MemoryManager.cpp | 63 ++++++++---------------- kernel/src/memory/MemoryMap.cpp | 75 +++++++++++++++++++++++++++++ kernel/src/memory/MemoryMap.h | 37 ++++++++++++++ 4 files changed, 132 insertions(+), 44 deletions(-) create mode 100644 kernel/src/memory/MemoryMap.cpp create mode 100644 kernel/src/memory/MemoryMap.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index feedd900..687a9c56 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES src/video/TextConsole.cpp src/memory/MemoryManager.cpp src/memory/Heap.cpp + src/memory/MemoryMap.cpp src/boot/Init.cpp src/arch/Serial.cpp src/arch/Timer.cpp diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index d788befe..fcae5467 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -3,6 +3,7 @@ #include "arch/CPU.h" #include "arch/MMU.h" #include "boot/bootboot.h" +#include "memory/MemoryMap.h" #include #include #include @@ -29,23 +30,11 @@ static Bitmap g_frame_bitmap; static usize get_physical_address_space_size() { - MMapEnt* ptr = &bootboot.mmap; - u64 biggest_ptr = 0; - u64 biggest_ptr_size = 0; - u64 mmap_entries = (bootboot.size - 128) / 16; - for (u64 i = 0; i < mmap_entries; i++) - { - if (MMapEnt_Ptr(ptr) > biggest_ptr) - { - biggest_ptr = MMapEnt_Ptr(ptr); - biggest_ptr_size = MMapEnt_Size(ptr); - } + MemoryMapIterator iter; + MemoryMapEntry entry = iter.highest(); - ptr++; - } - - return biggest_ptr + biggest_ptr_size; // This would be the address at the end of the last entry, thus the whole - // address space that was passed to us. + return entry.ptr + entry.size; // This is the address at the end of the last (highest) entry, thus the whole + // address space that was passed to us. } namespace MemoryManager @@ -67,28 +56,15 @@ namespace MemoryManager { u64 total_mem = 0; - void* biggest_usable_memory_block = nullptr; - u64 biggest_usable_memory_block_size = 0; + MemoryMapIterator iter; - // walk the memory map - MMapEnt* ptr = &bootboot.mmap; - u64 mmap_entries = (bootboot.size - 128) / 16; - for (u64 i = 0; i < mmap_entries; i++) - { - u64 size = MMapEnt_Size(ptr); - total_mem += size; - if (!MMapEnt_IsFree(ptr)) - { - ptr++; - continue; - } - if (size > biggest_usable_memory_block_size) - { - biggest_usable_memory_block = (void*)MMapEnt_Ptr(ptr); - biggest_usable_memory_block_size = MMapEnt_Size(ptr); - } - ptr++; - } + MemoryMapEntry entry; + while (iter.next().try_set_value(entry)) { total_mem += entry.size; } + + auto largest_free = iter.largest_free(); + + void* biggest_usable_memory_block = (void*)largest_free.ptr; + u64 biggest_usable_memory_block_size = largest_free.size; // The entire physical address space. May contain inexistent memory holes, thus differs from total_mem which // only counts existent memory. Our bitmap needs to have space for all of the physical address space, since @@ -110,18 +86,17 @@ namespace MemoryManager g_frame_bitmap.clear(true); // Set all pages to used/reserved by default, then clear out the free ones - ptr = &bootboot.mmap; - for (u64 i = 0; i < mmap_entries; i++) + iter.rewind(); + while (iter.next().try_set_value(entry)) { - u64 index = MMapEnt_Ptr(ptr) / ARCH_PAGE_SIZE; - u64 pages = MMapEnt_Size(ptr) / ARCH_PAGE_SIZE; - if (!MMapEnt_IsFree(ptr)) { reserved_mem += MMapEnt_Size(ptr); } + u64 index = entry.ptr / ARCH_PAGE_SIZE; + u64 pages = entry.size / ARCH_PAGE_SIZE; + if (!entry.free) { reserved_mem += entry.size; } else { - free_mem += MMapEnt_Size(ptr); + free_mem += entry.size; g_frame_bitmap.clear_region(index, pages, false); } - ptr++; } lock_frames((u64)frame_bitmap_addr, frame_bitmap_size / ARCH_PAGE_SIZE + 1); diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp new file mode 100644 index 00000000..7c1fcb80 --- /dev/null +++ b/kernel/src/memory/MemoryMap.cpp @@ -0,0 +1,75 @@ +#include "memory/MemoryMap.h" + +extern BOOTBOOT bootboot; + +static MemoryMapEntry memory_map_entry_from_mmapent(MMapEnt* ent) +{ + MemoryMapEntry result; + result.ptr = MMapEnt_Ptr(ent); + result.size = MMapEnt_Size(ent); + result.free = MMapEnt_IsFree(ent); + return result; +} + +MemoryMapIterator::MemoryMapIterator() +{ + m_mmap_entries = (bootboot.size - 128) / 16; + m_base_ent = &bootboot.mmap; + rewind(); +} + +void MemoryMapIterator::rewind() +{ + m_cur_ent = 0; +} + +Result MemoryMapIterator::at(usize index) +{ + if (index >= m_mmap_entries) return err(ERANGE); + return memory_map_entry_from_mmapent(m_base_ent + index); +} + +Result MemoryMapIterator::next() +{ + return at(m_cur_ent++); +} + +MemoryMapEntry MemoryMapIterator::largest_free() +{ + usize largest_size = 0; + usize largest_index = 0; + + rewind(); + + MemoryMapEntry entry; + while (next().try_set_value(entry)) + { + if (entry.free && entry.size > largest_size) + { + largest_size = entry.size; + largest_index = m_cur_ent - 1; + } + } + + return at(largest_index).release_value(); +} + +MemoryMapEntry MemoryMapIterator::highest() +{ + usize highest_ptr = 0; + usize highest_index = 0; + + rewind(); + + MemoryMapEntry entry; + while (next().try_set_value(entry)) + { + if (entry.ptr > highest_ptr) + { + highest_ptr = entry.ptr; + highest_index = m_cur_ent - 1; + } + } + + return at(highest_index).release_value(); +} \ No newline at end of file diff --git a/kernel/src/memory/MemoryMap.h b/kernel/src/memory/MemoryMap.h new file mode 100644 index 00000000..096bd2a7 --- /dev/null +++ b/kernel/src/memory/MemoryMap.h @@ -0,0 +1,37 @@ +#pragma once +#include "boot/bootboot.h" +#include +#include + +struct MemoryMapEntry +{ + u64 ptr; + u64 size; + bool free; +}; + +class MemoryMapIterator +{ + public: + MemoryMapIterator(); + + void rewind(); + + Result next(); + + MemoryMapEntry largest_free(); + + MemoryMapEntry highest(); + + Result at(usize index); + + usize entries() + { + return m_mmap_entries; + } + + private: + usize m_mmap_entries; + MMapEnt* m_base_ent; + usize m_cur_ent; +}; \ No newline at end of file From 0d10c98477422880f6909f07bfdec7f6258b976a Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 15:50:21 +0100 Subject: [PATCH 123/407] SImplify init_physical_frame_allocator() even more --- kernel/src/memory/MemoryManager.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index fcae5467..a2a03927 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -54,29 +54,26 @@ namespace MemoryManager void init_physical_frame_allocator() { - u64 total_mem = 0; - MemoryMapIterator iter; - MemoryMapEntry entry; - while (iter.next().try_set_value(entry)) { total_mem += entry.size; } auto largest_free = iter.largest_free(); - void* biggest_usable_memory_block = (void*)largest_free.ptr; - u64 biggest_usable_memory_block_size = largest_free.size; + expect(largest_free.free, "We were given a largest free block that isn't even free!"); // The entire physical address space. May contain inexistent memory holes, thus differs from total_mem which // only counts existent memory. Our bitmap needs to have space for all of the physical address space, since // usable addresses will be scattered across it. usize physical_address_space_size = get_physical_address_space_size(); - char* frame_bitmap_addr = (char*)biggest_usable_memory_block; + // We store our frame bitmap at the beginning of the largest free memory block. + char* frame_bitmap_addr = (char*)largest_free.ptr; + usize frame_bitmap_size = physical_address_space_size / ARCH_PAGE_SIZE / 8 + 1; // This should never happen, unless memory is very fragmented. Usually there is always a very big block of // usable memory and then some tiny blocks around it. - if (frame_bitmap_size >= biggest_usable_memory_block_size) [[unlikely]] + if (frame_bitmap_size >= largest_free.size) [[unlikely]] { kerrorln("ERROR: No single memory block is enough to hold the frame bitmap"); CPU::efficient_halt(); From 766804b3a03275e828acbb6d5d96509174e48bb7 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 15:52:56 +0100 Subject: [PATCH 124/407] Use get_blocks_from_size instead of +1 --- kernel/src/memory/MemoryManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index a2a03927..a6add72c 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -69,7 +69,7 @@ namespace MemoryManager // We store our frame bitmap at the beginning of the largest free memory block. char* frame_bitmap_addr = (char*)largest_free.ptr; - usize frame_bitmap_size = physical_address_space_size / ARCH_PAGE_SIZE / 8 + 1; + usize frame_bitmap_size = get_blocks_from_size(physical_address_space_size / ARCH_PAGE_SIZE, 8UL); // This should never happen, unless memory is very fragmented. Usually there is always a very big block of // usable memory and then some tiny blocks around it. @@ -96,7 +96,8 @@ namespace MemoryManager } } - lock_frames((u64)frame_bitmap_addr, frame_bitmap_size / ARCH_PAGE_SIZE + 1); + // Make sure that the physical frames used by the bitmap aren't handed out to anyone else. + lock_frames(largest_free.ptr, get_blocks_from_size(frame_bitmap_size, ARCH_PAGE_SIZE)); } void init() From 0a296413e6be850a13045fc6f07efdc5459aa792 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 15:55:12 +0100 Subject: [PATCH 125/407] It's not worth it aborting when failing to determine CPU name --- kernel/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9c804132..2056716f 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -16,7 +16,7 @@ Result init() kinfoln("Current platform: %s", CPU::platform_string()); - kinfoln("Current processor: %s", TRY(CPU::identify())); + kinfoln("Current processor: %s", CPU::identify().value_or("(unknown)")); Timer::init(); From 77e64d74a05d7d6a0f841601046480bc41ef2f02 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 15:55:52 +0100 Subject: [PATCH 126/407] Remove unused header --- kernel/src/memory/MemoryManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index a6add72c..4128447f 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -9,7 +9,6 @@ #include #include #include -#include extern BOOTBOOT bootboot; From af96db3641a21c51ea020f4238a6a84d2f033dbd Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 4 Dec 2022 15:56:25 +0100 Subject: [PATCH 127/407] Remove bootboot declaration from MemoryManager now that it's MemoryMapIterator's job to walk the mmap --- kernel/src/memory/MemoryManager.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 4128447f..2a91c5d4 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -2,7 +2,6 @@ #include "Log.h" #include "arch/CPU.h" #include "arch/MMU.h" -#include "boot/bootboot.h" #include "memory/MemoryMap.h" #include #include @@ -10,8 +9,6 @@ #include #include -extern BOOTBOOT bootboot; - extern u8 start_of_kernel_rodata[1]; extern u8 end_of_kernel_rodata[1]; extern u8 start_of_kernel_data[1]; From 3b77ba6b04b4fb30343581b8b89170c46a3060b9 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 12:49:01 +0100 Subject: [PATCH 128/407] EVERYTHING IS CONSTANT IN THIS UNIVERSE Here's one advantage of Rust over C++: Immutability by default. In Rust, you have to mark a variable as mutable, whereas in C++ you have to mark it as immutable. What's the problem here? Usually, most variables don't need mutability. Thus we end up with const all over the place. --- kernel/src/memory/MemoryManager.cpp | 32 +++++++++++++---------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 2a91c5d4..768997f4 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -9,10 +9,10 @@ #include #include -extern u8 start_of_kernel_rodata[1]; -extern u8 end_of_kernel_rodata[1]; -extern u8 start_of_kernel_data[1]; -extern u8 end_of_kernel_data[1]; +extern const u8 start_of_kernel_rodata[1]; +extern const u8 end_of_kernel_rodata[1]; +extern const u8 start_of_kernel_data[1]; +extern const u8 end_of_kernel_data[1]; static u64 free_mem = 0; static u64 used_mem = 0; @@ -27,7 +27,7 @@ static Bitmap g_frame_bitmap; static usize get_physical_address_space_size() { MemoryMapIterator iter; - MemoryMapEntry entry = iter.highest(); + const MemoryMapEntry entry = iter.highest(); return entry.ptr + entry.size; // This is the address at the end of the last (highest) entry, thus the whole // address space that was passed to us. @@ -53,27 +53,23 @@ namespace MemoryManager MemoryMapIterator iter; MemoryMapEntry entry; - auto largest_free = iter.largest_free(); + const auto largest_free = iter.largest_free(); - expect(largest_free.free, "We were given a largest free block that isn't even free!"); + expect(largest_free.free, "We were given a largest free memory region that isn't even free!"); // The entire physical address space. May contain inexistent memory holes, thus differs from total_mem which // only counts existent memory. Our bitmap needs to have space for all of the physical address space, since // usable addresses will be scattered across it. - usize physical_address_space_size = get_physical_address_space_size(); + const usize physical_address_space_size = get_physical_address_space_size(); // We store our frame bitmap at the beginning of the largest free memory block. - char* frame_bitmap_addr = (char*)largest_free.ptr; + char* const frame_bitmap_addr = (char*)largest_free.ptr; - usize frame_bitmap_size = get_blocks_from_size(physical_address_space_size / ARCH_PAGE_SIZE, 8UL); + const usize frame_bitmap_size = get_blocks_from_size(physical_address_space_size / ARCH_PAGE_SIZE, 8UL); // This should never happen, unless memory is very fragmented. Usually there is always a very big block of // usable memory and then some tiny blocks around it. - if (frame_bitmap_size >= largest_free.size) [[unlikely]] - { - kerrorln("ERROR: No single memory block is enough to hold the frame bitmap"); - CPU::efficient_halt(); - } + expect(frame_bitmap_size < largest_free.size, "No single memory region is enough to hold the frame bitmap"); g_frame_bitmap.initialize(frame_bitmap_addr, frame_bitmap_size); @@ -82,8 +78,8 @@ namespace MemoryManager iter.rewind(); while (iter.next().try_set_value(entry)) { - u64 index = entry.ptr / ARCH_PAGE_SIZE; - u64 pages = entry.size / ARCH_PAGE_SIZE; + const u64 index = entry.ptr / ARCH_PAGE_SIZE; + const u64 pages = entry.size / ARCH_PAGE_SIZE; if (!entry.free) { reserved_mem += entry.size; } else { @@ -104,7 +100,7 @@ namespace MemoryManager void lock_frame(u64 frame) { - const u64 index = ((u64)frame) / ARCH_PAGE_SIZE; + const u64 index = frame / ARCH_PAGE_SIZE; if (g_frame_bitmap.get(index)) return; g_frame_bitmap.set(index, true); used_mem += ARCH_PAGE_SIZE; From 004e13a5f309c5f9ba23382ba84d28b7638ac516 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 12:50:30 +0100 Subject: [PATCH 129/407] Make bitmap methods const if not modifying the bitmap --- luna/include/luna/Bitmap.h | 10 +++++----- luna/src/Bitmap.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/luna/include/luna/Bitmap.h b/luna/include/luna/Bitmap.h index 3260853d..463c88e5 100644 --- a/luna/include/luna/Bitmap.h +++ b/luna/include/luna/Bitmap.h @@ -11,25 +11,25 @@ class Bitmap void* move(void* new_location, usize new_location_size_in_bytes); void set(usize index, bool value); - bool get(usize index); + bool get(usize index) const; // size() returns size in bits! If you want the size in bytes, call size_in_bytes(). - usize size() + usize size() const { return m_size_in_bytes * 8; } - usize size_in_bytes() + usize size_in_bytes() const { return m_size_in_bytes; } - void* location() + void* location() const { return (void*)m_location; } - bool initialized() + bool initialized() const { return m_location; } diff --git a/luna/src/Bitmap.cpp b/luna/src/Bitmap.cpp index e130d191..f7b91156 100644 --- a/luna/src/Bitmap.cpp +++ b/luna/src/Bitmap.cpp @@ -42,7 +42,7 @@ void Bitmap::set(usize index, bool value) if (value) { m_location[byte_index] |= bit_mask; } } -bool Bitmap::get(usize index) +bool Bitmap::get(usize index) const { expect(initialized(), "Bitmap was never initialized"); expect(index < size(), "Bitmap access out of range"); From 86a12f301e0cd708d33950bc6a5ad03c318409c1 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 12:53:16 +0100 Subject: [PATCH 130/407] Make value_byte a helper --- luna/include/luna/Bitmap.h | 5 +++++ luna/src/Bitmap.cpp | 7 ++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/luna/include/luna/Bitmap.h b/luna/include/luna/Bitmap.h index 463c88e5..b7464e14 100644 --- a/luna/include/luna/Bitmap.h +++ b/luna/include/luna/Bitmap.h @@ -38,6 +38,11 @@ class Bitmap void clear_region(usize start, usize bits, bool value); private: + u8 value_byte(bool b) + { + return b ? 0xff : 0; + } + char* m_location = nullptr; usize m_size_in_bytes = 0; }; \ No newline at end of file diff --git a/luna/src/Bitmap.cpp b/luna/src/Bitmap.cpp index f7b91156..05566e3b 100644 --- a/luna/src/Bitmap.cpp +++ b/luna/src/Bitmap.cpp @@ -54,8 +54,7 @@ bool Bitmap::get(usize index) const void Bitmap::clear(bool value) { expect(initialized(), "Bitmap was never initialized"); - u8 value_byte = value ? 0xff : 0; - memset(m_location, value_byte, m_size_in_bytes); + memset(m_location, value_byte(value), m_size_in_bytes); } void Bitmap::clear_region(usize start, usize bits, bool value) @@ -63,8 +62,6 @@ void Bitmap::clear_region(usize start, usize bits, bool value) expect(initialized(), "Bitmap was never initialized"); expect((start + bits) <= size(), "Bitmap clear out of range"); - u8 value_byte = value ? 0xff : 0; - // Set individual bits while not on a byte boundary. while ((start % 8) && bits--) { @@ -75,7 +72,7 @@ void Bitmap::clear_region(usize start, usize bits, bool value) // Clear out the rest in bytes. usize bytes = bits / 8; - memset(&m_location[start / 8], value_byte, bytes); + memset(&m_location[start / 8], value_byte(value), bytes); start += bytes * 8; bits -= bytes * 8; From 792642dd6fdb0f8442ae1b1e1f7394c9bbeedbf2 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 12:58:59 +0100 Subject: [PATCH 131/407] MORE CONST --- luna/src/Format.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index 0231b3a2..0080475c 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -192,8 +192,8 @@ static usize to_string(usize value, usize base, char* buf, usize max, bool upper return 1; } do { - int digit = (int)(value % base); - char c = (char)(digit < 10 ? '0' + digit : ((uppercase ? 'A' : 'a') + (digit - 10))); + const int digit = (int)(value % base); + const char c = (char)(digit < 10 ? '0' + digit : ((uppercase ? 'A' : 'a') + (digit - 10))); buf[i++] = c; value /= base; } while (value && i < max); @@ -224,7 +224,7 @@ static Result output_integer(char specifier, conv_state& vstate, format_st if (!(vstate.flags & FLAG_LEFT_ALIGN) && (vstate.flags & FLAG_ZERO_PAD)) // we're padding with zeroes from the beginning { - bool extra_char = + const bool extra_char = negative || ((vstate.flags & FLAG_SIGN) || (vstate.flags & FLAG_BLANK_SIGNED)); // are we adding an extra character after the buffer? if (vstate.width && extra_char) vstate.width--; @@ -291,7 +291,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format } else { - unsigned char v = (unsigned char)va_arg(ap, unsigned int); + const unsigned char v = (unsigned char)va_arg(ap, unsigned int); return output_integer(specifier, vstate, state, v, false); } } @@ -309,7 +309,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format } else { - unsigned short v = (unsigned short)va_arg(ap, unsigned int); + const unsigned short v = (unsigned short)va_arg(ap, unsigned int); return output_integer(specifier, vstate, state, v, false); } } @@ -327,7 +327,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format } else { - unsigned long long v = va_arg(ap, unsigned long long); + const unsigned long long v = va_arg(ap, unsigned long long); return output_integer(specifier, vstate, state, v, false); } } @@ -345,7 +345,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format } else { - unsigned long v = va_arg(ap, unsigned long); + const unsigned long v = va_arg(ap, unsigned long); return output_integer(specifier, vstate, state, v, false); } } @@ -363,7 +363,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format } else { - unsigned int v = va_arg(ap, unsigned int); + const unsigned int v = va_arg(ap, unsigned int); return output_integer(specifier, vstate, state, v, false); } } @@ -396,13 +396,13 @@ Result cstyle_format(const char* format, callback_t callback, void* arg, // %[flags][width][.precision][length]conversion flags_t flags = parse_flags(&format); - usize width = parse_width(&format, flags, ap); + const usize width = parse_width(&format, flags, ap); usize precision = parse_precision(&format, flags, ap); parse_length(&format, flags); conv_state vstate = {flags, width, precision}; - char specifier = *format; + const char specifier = *format; format++; if (is_integer_format_specifier(specifier)) @@ -412,7 +412,7 @@ Result cstyle_format(const char* format, callback_t callback, void* arg, } else if (specifier == 'p') { - void* ptr = va_arg(ap, void*); + const void* ptr = va_arg(ap, void*); if (ptr == nullptr) { TRY(start_pad(vstate, state, 5)); From 54ce511f1dbf16938fdb6dbdb42c843c73698436 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:00:41 +0100 Subject: [PATCH 132/407] More const --- kernel/src/Log.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index b4f14cc7..0b008e58 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -47,8 +47,8 @@ static Result log_text_console(LogLevel level, const char* format, va_list va_list ap; va_copy(ap, origin); - u32 original_foreground = TextConsole::foreground(); - u32 original_background = TextConsole::background(); + const u32 original_foreground = TextConsole::foreground(); + const u32 original_background = TextConsole::background(); TextConsole::set_background(BLACK); From 58ecf1142405f040455be2412d64fc55df90b86d Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:04:01 +0100 Subject: [PATCH 133/407] Make all refs to the bootboot structure const --- kernel/src/arch/Timer.cpp | 4 ++-- kernel/src/boot/Init.cpp | 2 +- kernel/src/memory/MemoryMap.cpp | 6 +++--- kernel/src/memory/MemoryMap.h | 6 +++--- kernel/src/video/Framebuffer.cpp | 2 +- kernel/src/video/TextConsole.cpp | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 9c0606db..75792e93 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -37,7 +37,7 @@ static int bcd_number_to_decimal(int num) return ((num >> 4) * 10) + (num & 0xf); } -static u64 bootloader_time_to_unix(u8 boottime[8]) +static u64 bootloader_time_to_unix(const u8 boottime[8]) { int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); int month = bcd_number_to_decimal(boottime[2]); @@ -51,7 +51,7 @@ static u64 bootloader_time_to_unix(u8 boottime[8]) return broken_down_to_unix(year - 1900, make_yday(year, month) + (day - 1), hour, minute, second); } -extern BOOTBOOT bootboot; +extern const BOOTBOOT bootboot; namespace Timer { diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index c72f8aa4..11537b84 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -7,7 +7,7 @@ #include "video/Framebuffer.h" #include -extern BOOTBOOT bootboot; +extern const BOOTBOOT bootboot; void Init::check_magic() { diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index 7c1fcb80..5a97443a 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -1,8 +1,8 @@ #include "memory/MemoryMap.h" -extern BOOTBOOT bootboot; +extern const BOOTBOOT bootboot; -static MemoryMapEntry memory_map_entry_from_mmapent(MMapEnt* ent) +static MemoryMapEntry memory_map_entry_from_mmapent(const MMapEnt* ent) { MemoryMapEntry result; result.ptr = MMapEnt_Ptr(ent); @@ -23,7 +23,7 @@ void MemoryMapIterator::rewind() m_cur_ent = 0; } -Result MemoryMapIterator::at(usize index) +Result MemoryMapIterator::at(usize index) const { if (index >= m_mmap_entries) return err(ERANGE); return memory_map_entry_from_mmapent(m_base_ent + index); diff --git a/kernel/src/memory/MemoryMap.h b/kernel/src/memory/MemoryMap.h index 096bd2a7..26f86518 100644 --- a/kernel/src/memory/MemoryMap.h +++ b/kernel/src/memory/MemoryMap.h @@ -23,15 +23,15 @@ class MemoryMapIterator MemoryMapEntry highest(); - Result at(usize index); + Result at(usize index) const; - usize entries() + usize entries() const { return m_mmap_entries; } private: usize m_mmap_entries; - MMapEnt* m_base_ent; + const MMapEnt* m_base_ent; usize m_cur_ent; }; \ No newline at end of file diff --git a/kernel/src/video/Framebuffer.cpp b/kernel/src/video/Framebuffer.cpp index 8de99d62..8b28dbba 100644 --- a/kernel/src/video/Framebuffer.cpp +++ b/kernel/src/video/Framebuffer.cpp @@ -7,7 +7,7 @@ static u32 g_fb_width; static u32 g_fb_height; static u32 g_fb_scanline; -extern BOOTBOOT bootboot; +extern const BOOTBOOT bootboot; extern u8 fb[1]; namespace Framebuffer diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index 8384eec5..f6a55fa6 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -4,7 +4,7 @@ #include #include -extern BOOTBOOT bootboot; +extern const BOOTBOOT bootboot; #include "video/BuiltinFont.h" From ec1354fc8da7f04c2298416faa669adec705596a Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:06:12 +0100 Subject: [PATCH 134/407] const in TextConsole --- kernel/src/video/TextConsole.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index f6a55fa6..b49588bf 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -22,7 +22,7 @@ static u32 g_y_position = 0; static void putchar_at(char c, u32 x, u32 y) { - u8* glyph = &font[c * 16]; + const u8* glyph = &font[c * 16]; for (u32 i = 0; i < FONT_HEIGHT; i++) { for (u32 j = 0; j < FONT_WIDTH; j++) From d9fc50f1ea18c571a83625249a5b31723a3fe2f3 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:23:01 +0100 Subject: [PATCH 135/407] Make MemoryMapEntry have private fields with public getters --- kernel/src/memory/MemoryManager.cpp | 20 +++++++-------- kernel/src/memory/MemoryMap.cpp | 38 ++++++++++++++++++----------- kernel/src/memory/MemoryMap.h | 35 +++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 768997f4..34cc8f91 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -29,8 +29,8 @@ static usize get_physical_address_space_size() MemoryMapIterator iter; const MemoryMapEntry entry = iter.highest(); - return entry.ptr + entry.size; // This is the address at the end of the last (highest) entry, thus the whole - // address space that was passed to us. + return entry.address() + entry.size(); // This is the address at the end of the last (highest) entry, thus the whole + // address space that was passed to us. } namespace MemoryManager @@ -55,7 +55,7 @@ namespace MemoryManager const auto largest_free = iter.largest_free(); - expect(largest_free.free, "We were given a largest free memory region that isn't even free!"); + expect(largest_free.is_free(), "We were given a largest free memory region that isn't even free!"); // The entire physical address space. May contain inexistent memory holes, thus differs from total_mem which // only counts existent memory. Our bitmap needs to have space for all of the physical address space, since @@ -63,13 +63,13 @@ namespace MemoryManager const usize physical_address_space_size = get_physical_address_space_size(); // We store our frame bitmap at the beginning of the largest free memory block. - char* const frame_bitmap_addr = (char*)largest_free.ptr; + char* const frame_bitmap_addr = (char*)largest_free.ptr(); const usize frame_bitmap_size = get_blocks_from_size(physical_address_space_size / ARCH_PAGE_SIZE, 8UL); // This should never happen, unless memory is very fragmented. Usually there is always a very big block of // usable memory and then some tiny blocks around it. - expect(frame_bitmap_size < largest_free.size, "No single memory region is enough to hold the frame bitmap"); + expect(frame_bitmap_size < largest_free.size(), "No single memory region is enough to hold the frame bitmap"); g_frame_bitmap.initialize(frame_bitmap_addr, frame_bitmap_size); @@ -78,18 +78,18 @@ namespace MemoryManager iter.rewind(); while (iter.next().try_set_value(entry)) { - const u64 index = entry.ptr / ARCH_PAGE_SIZE; - const u64 pages = entry.size / ARCH_PAGE_SIZE; - if (!entry.free) { reserved_mem += entry.size; } + const u64 index = entry.address() / ARCH_PAGE_SIZE; + const u64 pages = entry.size() / ARCH_PAGE_SIZE; + if (!entry.is_free()) { reserved_mem += entry.size(); } else { - free_mem += entry.size; + free_mem += entry.size(); g_frame_bitmap.clear_region(index, pages, false); } } // Make sure that the physical frames used by the bitmap aren't handed out to anyone else. - lock_frames(largest_free.ptr, get_blocks_from_size(frame_bitmap_size, ARCH_PAGE_SIZE)); + lock_frames(largest_free.address(), get_blocks_from_size(frame_bitmap_size, ARCH_PAGE_SIZE)); } void init() diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index 5a97443a..9573a7d7 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -2,19 +2,29 @@ extern const BOOTBOOT bootboot; -static MemoryMapEntry memory_map_entry_from_mmapent(const MMapEnt* ent) +MemoryMapEntry::MemoryMapEntry(u64 address, u64 size, bool is_free) + : m_address(address), m_size(size), m_is_free(is_free) { - MemoryMapEntry result; - result.ptr = MMapEnt_Ptr(ent); - result.size = MMapEnt_Size(ent); - result.free = MMapEnt_IsFree(ent); - return result; } -MemoryMapIterator::MemoryMapIterator() +MemoryMapEntry& MemoryMapEntry::operator=(const MemoryMapEntry& other) +{ + if (&other == this) return *this; + + m_address = other.address(); + m_size = other.size(); + m_is_free = other.is_free(); + + return *this; +} + +static MemoryMapEntry memory_map_entry_from_mmapent(const MMapEnt* ent) +{ + return {MMapEnt_Ptr(ent), MMapEnt_Size(ent), MMapEnt_IsFree(ent)}; +} + +MemoryMapIterator::MemoryMapIterator() : m_mmap_entries((bootboot.size - 128) / 16), m_base_ent(&bootboot.mmap) { - m_mmap_entries = (bootboot.size - 128) / 16; - m_base_ent = &bootboot.mmap; rewind(); } @@ -44,9 +54,9 @@ MemoryMapEntry MemoryMapIterator::largest_free() MemoryMapEntry entry; while (next().try_set_value(entry)) { - if (entry.free && entry.size > largest_size) + if (entry.is_free() && entry.size() > largest_size) { - largest_size = entry.size; + largest_size = entry.size(); largest_index = m_cur_ent - 1; } } @@ -56,7 +66,7 @@ MemoryMapEntry MemoryMapIterator::largest_free() MemoryMapEntry MemoryMapIterator::highest() { - usize highest_ptr = 0; + usize highest_address = 0; usize highest_index = 0; rewind(); @@ -64,9 +74,9 @@ MemoryMapEntry MemoryMapIterator::highest() MemoryMapEntry entry; while (next().try_set_value(entry)) { - if (entry.ptr > highest_ptr) + if (entry.address() > highest_address) { - highest_ptr = entry.ptr; + highest_address = entry.address(); highest_index = m_cur_ent - 1; } } diff --git a/kernel/src/memory/MemoryMap.h b/kernel/src/memory/MemoryMap.h index 26f86518..05b30b8d 100644 --- a/kernel/src/memory/MemoryMap.h +++ b/kernel/src/memory/MemoryMap.h @@ -5,9 +5,36 @@ struct MemoryMapEntry { - u64 ptr; - u64 size; - bool free; + MemoryMapEntry() = default; + MemoryMapEntry(const MemoryMapEntry& other) = default; + MemoryMapEntry(u64 address, u64 size, bool is_free); + + u64 address() const + { + return m_address; + } + + void* ptr() const + { + return (void*)m_address; + } + + u64 size() const + { + return m_size; + } + + bool is_free() const + { + return m_is_free; + } + + MemoryMapEntry& operator=(const MemoryMapEntry& other); + + private: + u64 m_address; + u64 m_size; + bool m_is_free; }; class MemoryMapIterator @@ -31,7 +58,7 @@ class MemoryMapIterator } private: - usize m_mmap_entries; + const usize m_mmap_entries; const MMapEnt* m_base_ent; usize m_cur_ent; }; \ No newline at end of file From bfd4647467ddd6e846b7f951148a24db0bbe13fb Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:26:09 +0100 Subject: [PATCH 136/407] Rename largest_free -> largest_free_entry --- kernel/src/memory/MemoryManager.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 34cc8f91..1a03cfca 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -53,9 +53,9 @@ namespace MemoryManager MemoryMapIterator iter; MemoryMapEntry entry; - const auto largest_free = iter.largest_free(); + const auto largest_free_entry = iter.largest_free(); - expect(largest_free.is_free(), "We were given a largest free memory region that isn't even free!"); + expect(largest_free_entry.is_free(), "We were given a largest free memory region that isn't even free!"); // The entire physical address space. May contain inexistent memory holes, thus differs from total_mem which // only counts existent memory. Our bitmap needs to have space for all of the physical address space, since @@ -63,13 +63,14 @@ namespace MemoryManager const usize physical_address_space_size = get_physical_address_space_size(); // We store our frame bitmap at the beginning of the largest free memory block. - char* const frame_bitmap_addr = (char*)largest_free.ptr(); + char* const frame_bitmap_addr = (char*)largest_free_entry.ptr(); const usize frame_bitmap_size = get_blocks_from_size(physical_address_space_size / ARCH_PAGE_SIZE, 8UL); // This should never happen, unless memory is very fragmented. Usually there is always a very big block of // usable memory and then some tiny blocks around it. - expect(frame_bitmap_size < largest_free.size(), "No single memory region is enough to hold the frame bitmap"); + expect(frame_bitmap_size < largest_free_entry.size(), + "No single memory region is enough to hold the frame bitmap"); g_frame_bitmap.initialize(frame_bitmap_addr, frame_bitmap_size); @@ -89,7 +90,7 @@ namespace MemoryManager } // Make sure that the physical frames used by the bitmap aren't handed out to anyone else. - lock_frames(largest_free.address(), get_blocks_from_size(frame_bitmap_size, ARCH_PAGE_SIZE)); + lock_frames(largest_free_entry.address(), get_blocks_from_size(frame_bitmap_size, ARCH_PAGE_SIZE)); } void init() From 55a30ac487e32df742e964a2d8bfe268e0d69c1f Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:26:50 +0100 Subject: [PATCH 137/407] Make CHECK_PAGE_ALIGNED use expect() instead of check() --- kernel/src/memory/MemoryManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 1a03cfca..6e3f17b3 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -22,7 +22,7 @@ static u64 start_index = 0; static Bitmap g_frame_bitmap; -#define CHECK_PAGE_ALIGNED(address) check(is_aligned(address, ARCH_PAGE_SIZE)) +#define CHECK_PAGE_ALIGNED(address) expect(is_aligned(address, ARCH_PAGE_SIZE), "Address is not page-aligned"); static usize get_physical_address_space_size() { From ea7893ba7138415e0a0d3089092c94170c67e233 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:26:50 +0100 Subject: [PATCH 138/407] Make CHECK_PAGE_ALIGNED use expect() instead of check() --- kernel/src/memory/MemoryManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 6e3f17b3..0122b9e8 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -22,7 +22,7 @@ static u64 start_index = 0; static Bitmap g_frame_bitmap; -#define CHECK_PAGE_ALIGNED(address) expect(is_aligned(address, ARCH_PAGE_SIZE), "Address is not page-aligned"); +#define CHECK_PAGE_ALIGNED(address) expect(is_aligned(address, ARCH_PAGE_SIZE), "Address is not page-aligned") static usize get_physical_address_space_size() { From 7cc139c3f7ea83f07a065369616ff0e56d0e0614 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:35:33 +0100 Subject: [PATCH 139/407] Make expect and check use unlikely --- luna/include/luna/Check.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/luna/include/luna/Check.h b/luna/include/luna/Check.h index fce54b96..fe1c7f50 100644 --- a/luna/include/luna/Check.h +++ b/luna/include/luna/Check.h @@ -8,6 +8,18 @@ extern _noreturn bool __check_failed(const char* file, const char* line, const c #define STRINGIZE_VALUE_OF(x) STRINGIZE(x) #endif -#define check(expr) (expr) || __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, #expr) #define expect(expr, message) \ - (expr) || __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, message) + do { \ + if (!(expr)) [[unlikely]] \ + { \ + __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, message); \ + } \ + } while (0) + +#define check(expr) \ + do { \ + if (!(expr)) [[unlikely]] \ + { \ + __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, #expr); \ + } \ + } while (0) From 891320f7d3a297578f943a018e91beae308ae993 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:41:58 +0100 Subject: [PATCH 140/407] Heap: Make const --- kernel/src/memory/Heap.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index dfd0ae5f..edc689f8 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -38,7 +38,7 @@ static Result allocate_pages( // space is so huge, we can just start at a fairly large address and assume // we'll never run into anything, but this will probably bite us in the future. { - void* ptr = (void*)TRY(MemoryManager::alloc_at(start_addr, count, MMU::ReadWrite | MMU::NoExecute)); + void* const ptr = (void*)TRY(MemoryManager::alloc_at(start_addr, count, MMU::ReadWrite | MMU::NoExecute)); if (ptr) start_addr += (count * ARCH_PAGE_SIZE); return (HeapBlock*)ptr; } @@ -95,13 +95,13 @@ static usize get_fair_offset_to_split_at(HeapBlock* block, usize min) static Result split(HeapBlock* block, usize size) { - usize available = space_available(block); // How much space can we steal from this block? - usize old_size = + const usize available = space_available(block); // How much space can we steal from this block? + const usize old_size = block->full_size; // Save the old value of this variable since we are going to use it after modifying it if (available < (size + sizeof(HeapBlock))) return err(0); // This error is not propagated. - usize offset = get_fair_offset_to_split_at(block, size + sizeof(HeapBlock)); + const usize offset = get_fair_offset_to_split_at(block, size + sizeof(HeapBlock)); block->full_size = offset; // shrink the old block to fit this offset HeapBlock* new_block = offset_ptr(block, offset + sizeof(HeapBlock)); @@ -120,7 +120,7 @@ static Result split(HeapBlock* block, usize size) static Result combine_forward(HeapBlock* block) { - HeapBlock* next = block->next; + HeapBlock* const next = block->next; if (next == heap_end) heap_end = block; next->magic = BLOCK_DEAD; @@ -145,7 +145,7 @@ static Result combine_forward(HeapBlock* block) static Result combine_backward(HeapBlock* block) { - HeapBlock* last = block->last; + HeapBlock* const last = block->last; if (block == heap_end) heap_end = last; block->magic = BLOCK_DEAD; @@ -176,8 +176,8 @@ Result kmalloc(usize size) if (!heap_start) { - usize pages = get_pages_for_allocation(size); - auto* block = TRY(allocate_pages(pages)); + const usize pages = get_pages_for_allocation(size); + HeapBlock* const block = TRY(allocate_pages(pages)); block->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); block->magic = BLOCK_MAGIC; @@ -293,7 +293,7 @@ Result krealloc(void* ptr, usize size) return (void*)BLOCK_MAGIC; } - HeapBlock* block = get_heap_block_for_pointer(ptr); + HeapBlock* const block = get_heap_block_for_pointer(ptr); if (block->magic != BLOCK_MAGIC) { @@ -322,7 +322,7 @@ Result krealloc(void* ptr, usize size) return ptr; } - void* new_ptr = TRY(kmalloc(size)); + void* const new_ptr = TRY(kmalloc(size)); memcpy(new_ptr, ptr, block->req_size > size ? size : block->req_size); TRY(kfree(ptr)); @@ -332,8 +332,8 @@ Result krealloc(void* ptr, usize size) Result kcalloc(usize nmemb, usize size) { // FIXME: Check for overflows. - usize realsize = nmemb * size; - void* ptr = TRY(kmalloc(realsize)); + const usize realsize = nmemb * size; + void* const ptr = TRY(kmalloc(realsize)); return memset(ptr, 0, realsize); } From a63a8b32b58c3ca744336683933a185207ba0309 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 13:45:32 +0100 Subject: [PATCH 141/407] Make new and delete noexcept and return nullptr on failure --- kernel/src/memory/Heap.cpp | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index edc689f8..a95244be 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -368,44 +368,32 @@ void dump_heap_usage() kdbgln("-- Heap memory in use by the kernel: %zu bytes", alloc_used); } -void* operator new(usize size) +void* operator new(usize size) noexcept { - auto rc = kmalloc(size); - if (rc.has_error()) { expect(false, rc.error_string()); } - return rc.release_value(); + return kmalloc(size).value_or(nullptr); } -void* operator new[](usize size) +void* operator new[](usize size) noexcept { - auto rc = kmalloc(size); - if (rc.has_error()) { expect(false, rc.error_string()); } - return rc.release_value(); + return kmalloc(size).value_or(nullptr); } -void operator delete(void* p) +void operator delete(void* p) noexcept { - auto rc = kfree(p); - if (rc.has_error()) { expect(false, rc.error_string()); } - return rc.release_value(); + kfree(p); } -void operator delete[](void* p) +void operator delete[](void* p) noexcept { - auto rc = kfree(p); - if (rc.has_error()) { expect(false, rc.error_string()); } - return rc.release_value(); + kfree(p); } -void operator delete(void* p, usize) +void operator delete(void* p, usize) noexcept { - auto rc = kfree(p); - if (rc.has_error()) { expect(false, rc.error_string()); } - return rc.release_value(); + kfree(p); } -void operator delete[](void* p, usize) +void operator delete[](void* p, usize) noexcept { - auto rc = kfree(p); - if (rc.has_error()) { expect(false, rc.error_string()); } - return rc.release_value(); + kfree(p); } \ No newline at end of file From 4f183958e390d9fb992a2518219e1dda41bd36f3 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 16:13:38 +0100 Subject: [PATCH 142/407] General constness + [[gnu::packed]] everywhere --- kernel/src/arch/Timer.cpp | 14 ++--- kernel/src/arch/x86_64/CPU.cpp | 44 ++++++++++------ kernel/src/arch/x86_64/MMU.cpp | 95 +++++++++++++++++++--------------- 3 files changed, 90 insertions(+), 63 deletions(-) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 75792e93..26515c99 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -32,19 +32,19 @@ static u64 broken_down_to_unix(u64 year, u64 yday, u64 hour, u64 min, u64 sec) // The bootloader encodes the date and time in Binary-Coded Decimal (BCD), which represents decimal digits using // hexadecimal digits. For example, BCD 0x22 is 22 in decimal. // https://gitlab.com/bztsrc/bootboot/-/blob/master/bootboot_spec_1st_ed.pdf, page 15. -static int bcd_number_to_decimal(int num) +static inline constexpr int bcd_number_to_decimal(int num) { return ((num >> 4) * 10) + (num & 0xf); } static u64 bootloader_time_to_unix(const u8 boottime[8]) { - int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); - int month = bcd_number_to_decimal(boottime[2]); - int day = bcd_number_to_decimal(boottime[3]); - int hour = bcd_number_to_decimal(boottime[4]); - int minute = bcd_number_to_decimal(boottime[5]); - int second = bcd_number_to_decimal(boottime[6]); + const int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); + const int month = bcd_number_to_decimal(boottime[2]); + const int day = bcd_number_to_decimal(boottime[3]); + const int hour = bcd_number_to_decimal(boottime[4]); + const int minute = bcd_number_to_decimal(boottime[5]); + const int second = bcd_number_to_decimal(boottime[6]); // "The last byte can store 1/100th second precision, but in lack of support on most platforms, it is 0x00". // Therefore, let's not rely on it. kinfoln("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC", day, month, year, hour, minute, second).release_value(); diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 306117d5..73ffbafd 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -12,15 +12,19 @@ extern "C" void enable_sse(); extern "C" void enable_write_protect(); extern "C" void enable_nx(); +// FIXME: Split this into separate files? + // GDT code and definitions -struct GDTR +struct [[gnu::packed]] GDTR { u16 size; u64 offset; -} __attribute__((packed)); +}; -struct GDTEntry +static_assert(sizeof(GDTR) == 10UL); + +struct [[gnu::packed]] GDTEntry { u16 limit0; u16 base0; @@ -28,15 +32,19 @@ struct GDTEntry u8 access; u8 limit1_flags; u8 base2; -} __attribute__((packed)); +}; -struct HighGDTEntry +static_assert(sizeof(GDTEntry) == 8UL); + +struct [[gnu::packed]] HighGDTEntry { u32 base_high; u32 reserved; -} __attribute__((packed)); +}; -struct TSS +static_assert(sizeof(HighGDTEntry) == 8UL); + +struct [[gnu::packed]] TSS { u32 reserved0; u64 rsp[3]; @@ -45,9 +53,11 @@ struct TSS u64 reserved2; u16 reserved3; u16 iomap_base; -} __attribute__((packed)); +}; -struct GlobalDescriptorTable +static_assert(sizeof(TSS) == 104UL); + +struct [[gnu::packed]] alignas(4096) GlobalDescriptorTable { GDTEntry null; GDTEntry kernel_code; @@ -56,7 +66,7 @@ struct GlobalDescriptorTable GDTEntry user_data; GDTEntry tss; HighGDTEntry tss2; -} __attribute__((packed)) __attribute((aligned(4096))); +}; static TSS task_state_segment; @@ -174,9 +184,11 @@ struct IDTEntry u32 offset2; u32 ignore; void set_offset(u64 offset); - u64 get_offset(); + u64 get_offset() const; }; +static_assert(sizeof(IDTEntry) == 16UL); + void IDTEntry::set_offset(u64 offset) { offset0 = (u16)(offset & 0x000000000000ffff); @@ -184,7 +196,7 @@ void IDTEntry::set_offset(u64 offset) offset2 = (u32)((offset & 0xffffffff00000000) >> 32); } -u64 IDTEntry::get_offset() +u64 IDTEntry::get_offset() const { u64 offset = 0; offset |= (u64)offset0; @@ -199,17 +211,19 @@ static IDTEntry idt[256]; #define IDT_TA_UserInterruptGate 0b11101110 #define IDT_TA_TrapGate 0b10001111 -struct IDTR +struct [[gnu::packed]] IDTR { u16 limit; u64 offset; -} __attribute__((packed)); +}; + +static_assert(sizeof(IDTR) == 10UL); static void idt_add_handler(short num, void* handler, u8 type_attr) { check(handler != nullptr); expect(num < 256, "IDT can only hold up to 256 entries"); - IDTEntry* entry_for_handler = &idt[num]; + IDTEntry* const entry_for_handler = &idt[num]; entry_for_handler->selector = 0x08; entry_for_handler->type_attr = type_attr; entry_for_handler->set_offset((u64)handler); diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 12cbd372..fa09ff14 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -12,22 +12,30 @@ const u64 sign = 0177777UL << 48; // sign extension struct [[gnu::packed]] PageTableEntry { - bool present : 1; - bool read_write : 1; - bool user : 1; - bool write_through : 1; - bool cache_disabled : 1; - bool accessed : 1; - bool ignore0 : 1; - bool larger_pages : 1; - bool ignore1 : 1; - u8 available : 3; - u64 address : 48; - u8 available2 : 3; - bool no_execute : 1; + union { + struct [[gnu::packed]] + { + bool present : 1; + bool read_write : 1; + bool user : 1; + bool write_through : 1; + bool cache_disabled : 1; + bool accessed : 1; + bool ignore0 : 1; + bool larger_pages : 1; + bool ignore1 : 1; + u8 available : 3; + u64 address : 48; + u8 available2 : 3; + bool no_execute : 1; + }; + u64 raw; + }; void set_address(u64 addr); - u64 get_address(); + u64 get_address() const; + + void clear(); }; #pragma GCC push_options @@ -38,13 +46,18 @@ void PageTableEntry::set_address(u64 addr) this->address = (addr >> 12); } -u64 PageTableEntry::get_address() +u64 PageTableEntry::get_address() const { return (u64)this->address << 12; } #pragma GCC pop_options +void PageTableEntry::clear() +{ + raw = 0; +} + struct alignas(PAGE_SIZE) PageDirectory { PageTableEntry entries[512]; @@ -56,13 +69,13 @@ static_assert(sizeof(PageDirectory) == PAGE_SIZE); namespace MMU { - PageDirectory* l4_table() + constexpr PageDirectory* l4_table() { - u64 l4 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (rindex << 12); + constexpr u64 l4 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (rindex << 12); return (PageDirectory*)l4; } - u64 l4_index(u64 addr) + constexpr u64 l4_index(u64 addr) { return (addr >> 39) & 0777; } @@ -72,14 +85,14 @@ namespace MMU return l4_table()->entries[l4_index(addr)]; } - PageDirectory* l3_table(u64 addr) + constexpr PageDirectory* l3_table(u64 addr) { - u64 l4 = l4_index(addr); - u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12); + const u64 l4 = l4_index(addr); + const u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12); return (PageDirectory*)l3; } - u64 l3_index(u64 addr) + constexpr u64 l3_index(u64 addr) { return (addr >> 30) & 0777; } @@ -89,15 +102,15 @@ namespace MMU return l3_table(addr)->entries[l3_index(addr)]; } - PageDirectory* l2_table(u64 addr) + constexpr PageDirectory* l2_table(u64 addr) { - u64 l4 = l4_index(addr); - u64 l3 = l3_index(addr); - u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12); + const u64 l4 = l4_index(addr); + const u64 l3 = l3_index(addr); + const u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12); return (PageDirectory*)l2; } - u64 l2_index(u64 addr) + constexpr u64 l2_index(u64 addr) { return (addr >> 21) & 0777; } @@ -107,16 +120,16 @@ namespace MMU return l2_table(addr)->entries[l2_index(addr)]; } - PageDirectory* l1_table(u64 addr) + constexpr PageDirectory* l1_table(u64 addr) { - u64 l4 = l4_index(addr); - u64 l3 = l3_index(addr); - u64 l2 = l2_index(addr); - u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12); + const u64 l4 = l4_index(addr); + const u64 l3 = l3_index(addr); + const u64 l2 = l2_index(addr); + const u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12); return (PageDirectory*)l1; } - u64 l1_index(u64 addr) + constexpr u64 l1_index(u64 addr) { return (addr >> 12) & 0777; } @@ -148,7 +161,7 @@ namespace MMU asm volatile("invlpg (%0)" : : "r"(page) : "memory"); } - int arch_flags_to_mmu(PageTableEntry& entry) + int arch_flags_to_mmu(const PageTableEntry& entry) { int result = Flags::None; if (entry.read_write) result |= Flags::ReadWrite; @@ -161,7 +174,7 @@ namespace MMU Result find_entry(u64 virt) { - auto& l4 = l4_entry(virt); + const auto& l4 = l4_entry(virt); if (!l4.present) return err(EFAULT); auto& l3 = l3_entry(virt); if (!l3.present) return err(EFAULT); @@ -263,30 +276,30 @@ namespace MMU { auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err(EFAULT); - u64 address = l1.get_address(); - memset(&l1, 0, sizeof(l1)); + const u64 address = l1.get_address(); + l1.clear(); flush_page(virt); return address; } Result get_physical(u64 virt) { - auto& l1 = *TRY(find_entry(virt)); + const auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err(EFAULT); return l1.get_address(); } Result get_flags(u64 virt) { - auto& l1 = *TRY(find_entry(virt)); + const auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err(EFAULT); return arch_flags_to_mmu(l1); } void setup_initial_page_directory() { - PageDirectory* dir = get_page_directory(); - u64 paddr = (u64)dir; + PageDirectory* const dir = get_page_directory(); + const u64 paddr = (u64)dir; PageTableEntry& recursive_entry = dir->entries[rindex]; recursive_entry.read_write = true; recursive_entry.present = true; From 1e3706ac015bd20032cb50922998a6e33dbeedc7 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 16:36:41 +0100 Subject: [PATCH 143/407] Make ARCH_PAGE_SIZE and ARCH_TIMER_FREQ known at compile-time --- CMakeLists.txt | 4 +++ kernel/src/arch/MMU.h | 8 ++++-- kernel/src/arch/Timer.cpp | 6 ++-- kernel/src/arch/Timer.h | 6 +++- kernel/src/arch/x86_64/MMU.cpp | 49 ++------------------------------ kernel/src/arch/x86_64/MMU.h | 43 ++++++++++++++++++++++++++++ kernel/src/arch/x86_64/Timer.cpp | 1 - kernel/src/arch/x86_64/Timer.h | 4 +++ luna/CMakeLists.txt | 14 +++++---- 9 files changed, 75 insertions(+), 60 deletions(-) create mode 100644 kernel/src/arch/x86_64/MMU.h create mode 100644 kernel/src/arch/x86_64/Timer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 397b925c..8f522402 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,10 @@ set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) set(ARCH $ENV{ARCH}) +if(NOT DEFINED $ENV{ARCH}) +set(ARCH "x86_64") +endif() + message(STATUS "Configuring Luna for ${ARCH}") add_subdirectory(luna) diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index f18e0302..095ed40a 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -1,9 +1,11 @@ #pragma once #include -struct PageDirectory; - -extern const usize ARCH_PAGE_SIZE; +#ifdef ARCH_X86_64 +#include "arch/x86_64/MMU.h" +#else +#error "Unknown architecture." +#endif namespace MMU { diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 26515c99..7f29500b 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -73,9 +73,9 @@ namespace Timer usize ticks_us() // We want a bit of precision; if there are 10 ticks/ms, do not return the truncated ms value * // 1000, but ticks * 100 (1000/10), which is more precise { - if (ARCH_TIMER_FREQ > 1000) [[unlikely]] - return timer_ticks / (ARCH_TIMER_FREQ / 1000); - return timer_ticks * (1000 / ARCH_TIMER_FREQ); + if constexpr (ARCH_TIMER_FREQ > 1000) return timer_ticks / (ARCH_TIMER_FREQ / 1000); + else + return timer_ticks * (1000 / ARCH_TIMER_FREQ); } usize ticks_ns() diff --git a/kernel/src/arch/Timer.h b/kernel/src/arch/Timer.h index 21c389d7..c540631b 100644 --- a/kernel/src/arch/Timer.h +++ b/kernel/src/arch/Timer.h @@ -1,7 +1,11 @@ #pragma once #include -extern const usize ARCH_TIMER_FREQ; // How many timer ticks in one millisecond? +#ifdef ARCH_X86_64 +#include "arch/x86_64/Timer.h" +#else +#error "Unknown architecture." +#endif static const usize MS_PER_SECOND = 1000; static const usize US_PER_SECOND = MS_PER_SECOND * 1000; diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index fa09ff14..d4088c1f 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -3,41 +3,6 @@ #include #include -#define PAGE_SIZE 4096 - -const usize ARCH_PAGE_SIZE = PAGE_SIZE; - -const u64 rindex = 0776; // recursive index -const u64 sign = 0177777UL << 48; // sign extension - -struct [[gnu::packed]] PageTableEntry -{ - union { - struct [[gnu::packed]] - { - bool present : 1; - bool read_write : 1; - bool user : 1; - bool write_through : 1; - bool cache_disabled : 1; - bool accessed : 1; - bool ignore0 : 1; - bool larger_pages : 1; - bool ignore1 : 1; - u8 available : 3; - u64 address : 48; - u8 available2 : 3; - bool no_execute : 1; - }; - u64 raw; - }; - - void set_address(u64 addr); - u64 get_address() const; - - void clear(); -}; - #pragma GCC push_options #pragma GCC diagnostic ignored "-Wconversion" @@ -58,14 +23,6 @@ void PageTableEntry::clear() raw = 0; } -struct alignas(PAGE_SIZE) PageDirectory -{ - PageTableEntry entries[512]; -}; - -static_assert(sizeof(PageTableEntry) == 8UL); -static_assert(sizeof(PageDirectory) == PAGE_SIZE); - namespace MMU { @@ -213,7 +170,7 @@ namespace MMU u64 addr = TRY(MemoryManager::alloc_frame()); l4.present = true; l4.set_address(addr); - memset(l3_table(virt), 0, PAGE_SIZE); + memset(l3_table(virt), 0, ARCH_PAGE_SIZE); l4.ignore0 = l4.ignore1 = 0; } if (flags & Flags::ReadWrite) l4.read_write = true; @@ -225,7 +182,7 @@ namespace MMU u64 addr = TRY(MemoryManager::alloc_frame()); l3.present = true; l3.set_address(addr); - memset(l2_table(virt), 0, PAGE_SIZE); + memset(l2_table(virt), 0, ARCH_PAGE_SIZE); l3.ignore0 = l3.ignore1 = 0; } if (flags & Flags::ReadWrite) l3.read_write = true; @@ -239,7 +196,7 @@ namespace MMU u64 addr = TRY(MemoryManager::alloc_frame()); l2.present = true; l2.set_address(addr); - memset(l1_table(virt), 0, PAGE_SIZE); + memset(l1_table(virt), 0, ARCH_PAGE_SIZE); l2.ignore0 = l2.ignore1 = 0; } if (flags & Flags::ReadWrite) l2.read_write = true; diff --git a/kernel/src/arch/x86_64/MMU.h b/kernel/src/arch/x86_64/MMU.h new file mode 100644 index 00000000..0ebc7978 --- /dev/null +++ b/kernel/src/arch/x86_64/MMU.h @@ -0,0 +1,43 @@ +#pragma once +#include + +const usize ARCH_PAGE_SIZE = 4096; + +const u64 rindex = 0776; // recursive index +const u64 sign = 0177777UL << 48; // sign extension + +struct [[gnu::packed]] PageTableEntry +{ + union { + struct [[gnu::packed]] + { + bool present : 1; + bool read_write : 1; + bool user : 1; + bool write_through : 1; + bool cache_disabled : 1; + bool accessed : 1; + bool ignore0 : 1; + bool larger_pages : 1; + bool ignore1 : 1; + u8 available : 3; + u64 address : 48; + u8 available2 : 3; + bool no_execute : 1; + }; + u64 raw; + }; + + void set_address(u64 addr); + u64 get_address() const; + + void clear(); +}; + +struct alignas(ARCH_PAGE_SIZE) PageDirectory +{ + PageTableEntry entries[512]; +}; + +static_assert(sizeof(PageTableEntry) == 8UL); +static_assert(sizeof(PageDirectory) == ARCH_PAGE_SIZE); \ No newline at end of file diff --git a/kernel/src/arch/x86_64/Timer.cpp b/kernel/src/arch/x86_64/Timer.cpp index 9add861b..c35a4cf5 100644 --- a/kernel/src/arch/x86_64/Timer.cpp +++ b/kernel/src/arch/x86_64/Timer.cpp @@ -4,7 +4,6 @@ #define PIT_CHANNEL_0 0x40 const u64 base_frequency = 1193182; -const usize ARCH_TIMER_FREQ = 5; void Timer::arch_init() { diff --git a/kernel/src/arch/x86_64/Timer.h b/kernel/src/arch/x86_64/Timer.h new file mode 100644 index 00000000..1a0e474b --- /dev/null +++ b/kernel/src/arch/x86_64/Timer.h @@ -0,0 +1,4 @@ +#pragma once +#include + +const usize ARCH_TIMER_FREQ = 5; \ No newline at end of file diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 1ac0c37f..8cb8b56b 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -24,11 +24,6 @@ target_compile_options(luna-freestanding PRIVATE -fno-rtti -ffreestanding -fno-e target_compile_options(luna-freestanding PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) target_compile_options(luna-freestanding PRIVATE -nostdlib -mcmodel=kernel) -if("${ARCH}" MATCHES "x86_64") -target_compile_options(luna-freestanding PRIVATE -mno-red-zone) -target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) -endif() - target_include_directories(luna-freestanding PUBLIC include/) set_target_properties(luna-freestanding PROPERTIES CXX_STANDARD 20) @@ -39,4 +34,11 @@ target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wca target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) target_include_directories(luna PUBLIC include/) -set_target_properties(luna PROPERTIES CXX_STANDARD 20) \ No newline at end of file +set_target_properties(luna PROPERTIES CXX_STANDARD 20) + +if("${ARCH}" MATCHES "x86_64") +target_compile_options(luna-freestanding PRIVATE -mno-red-zone) +target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) +target_compile_definitions(luna-freestanding PUBLIC ARCH_X86_64) +target_compile_definitions(luna PUBLIC ARCH_X86_64) +endif() \ No newline at end of file From 2eaa4585558d458f5c3944ca34a188c1d4252ed0 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 16:41:39 +0100 Subject: [PATCH 144/407] Remove release_value call --- kernel/src/arch/Timer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 7f29500b..58ce56c7 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -2,7 +2,6 @@ #include "Log.h" #include "arch/Serial.h" #include "boot/bootboot.h" -#include static u64 timer_ticks = 0; static u64 boot_timestamp; @@ -47,7 +46,7 @@ static u64 bootloader_time_to_unix(const u8 boottime[8]) const int second = bcd_number_to_decimal(boottime[6]); // "The last byte can store 1/100th second precision, but in lack of support on most platforms, it is 0x00". // Therefore, let's not rely on it. - kinfoln("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC", day, month, year, hour, minute, second).release_value(); + kinfoln("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC", day, month, year, hour, minute, second); return broken_down_to_unix(year - 1900, make_yday(year, month) + (day - 1), hour, minute, second); } From 762131a42516ce98c2b44ad3b3ebba06683d16e7 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 16:43:52 +0100 Subject: [PATCH 145/407] Make more constexpr --- kernel/src/arch/Timer.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 58ce56c7..35599f2c 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -6,23 +6,22 @@ static u64 timer_ticks = 0; static u64 boot_timestamp; -static int isleap(int year) +static inline constexpr int isleap(int year) { return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); } -static int make_yday(int year, int month) +static constexpr int make_yday(int year, int month) { - static const short int upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - int yd; + constexpr short int upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - yd = upto[month - 1]; + int yd = upto[month - 1]; if (month > 2 && isleap(year)) yd++; return yd; } // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16 -static u64 broken_down_to_unix(u64 year, u64 yday, u64 hour, u64 min, u64 sec) +static constexpr u64 broken_down_to_unix(u64 year, u64 yday, u64 hour, u64 min, u64 sec) { return sec + min * 60 + hour * 3600 + yday * 86400 + (year - 70) * 31536000 + ((year - 69) / 4) * 86400 - ((year - 1) / 100) * 86400 + ((year + 299) / 400) * 86400; From 95d969ed2538f81cabb3fb07a3006b9b3802c602 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 17:48:26 +0100 Subject: [PATCH 146/407] Add message to inform of prebuilt toolchains --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 17bbbb78..242b0ce8 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ A simple kernel and userspace for the x86_64 platform, written mostly in C++ and ## Setup (broken) **WARNING**: Setup will fail on this branch, since we do not have the required libc headers yet, and I removed the patches for now. Your best bet to build the toolchain is to switch to the `main` branch, where it will build successfully, and run `tools/setup.sh`. Then switch back to this branch, remove some files created by the `main` branch, and continue development :) +Alternatively, you can also download prebuilt toolchains for x86_64/arm64 Linux hosts from [here](https://pub.cloudapio.eu/luna). Then run `tar xf toolchain-linux-ARCH.tar.gz -C /path/to/luna`. + To build and run Luna, you will need to build a [GCC Cross-Compiler](https://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler) and cross-binutils for `x86_64-luna`. (Yes, Luna is advanced enough that it can use its own [OS-Specific Toolchain](https://wiki.osdev.org/OS_Specific_Toolchain), instead of a bare metal target like `x86_64-elf`. It is the first of my OS projects to be able to do so. The patches for Binutils and GCC are [binutils.patch](tools/binutils.patch) and [gcc.patch](tools/gcc.patch)). You should start by installing the [required dependencies](https://wiki.osdev.org/GCC_Cross_Compiler#Installing_Dependencies). From e6c56172d352d5cc906ec8e2508de1599532aef0 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:00:05 +0100 Subject: [PATCH 147/407] Try adding a drone.yml --- .drone.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 00000000..67c978e0 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,30 @@ +kind: pipeline +type: docker +name: lint-pr + +steps: +- name: setup-env + image: ubuntu:latest + commands: + - apt install build-essential cmake ninja-build wget + - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz + - tar xf toolchain-linux-arm64.tar.gz +- name: check-formatting + commands: + - tools/check-formatting.sh +- name: check-stdint + commands: + - tools/check-stdint.sh + when: + branch: + - restart +- name: check-build + commands: + - tools/rebuild-iso.sh + +trigger: + branch: + - main + - restart + event: + - pull_request \ No newline at end of file From 4074835185286b47db4de6b0fd4e2d2034a34de3 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:06:30 +0100 Subject: [PATCH 148/407] Update drone.yml --- .drone.yml | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/.drone.yml b/.drone.yml index 67c978e0..82930e3c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -3,28 +3,31 @@ type: docker name: lint-pr steps: -- name: setup-env - image: ubuntu:latest - commands: - - apt install build-essential cmake ninja-build wget - - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz - - tar xf toolchain-linux-arm64.tar.gz -- name: check-formatting - commands: - - tools/check-formatting.sh -- name: check-stdint - commands: - - tools/check-stdint.sh - when: - branch: - - restart -- name: check-build - commands: - - tools/rebuild-iso.sh + - name: setup-env + image: ubuntu:latest + commands: + - apt install build-essential cmake ninja-build wget + - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz + - tar xf toolchain-linux-arm64.tar.gz + + - name: check-formatting + commands: + - tools/check-formatting.sh + + - name: check-stdint + commands: + - tools/check-stdint.sh + when: + branch: + - restart + + - name: check-build + commands: + - tools/rebuild-iso.sh trigger: branch: - - main - - restart + - main + - restart event: - - pull_request \ No newline at end of file + - pull_request \ No newline at end of file From 8f3e80ae478eb7acdb926fed383d7e8d5900d391 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:08:50 +0100 Subject: [PATCH 149/407] Try to get it right? --- .drone.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.drone.yml b/.drone.yml index 82930e3c..b35ef16c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -9,20 +9,7 @@ steps: - apt install build-essential cmake ninja-build wget - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz - tar xf toolchain-linux-arm64.tar.gz - - - name: check-formatting - commands: - tools/check-formatting.sh - - - name: check-stdint - commands: - - tools/check-stdint.sh - when: - branch: - - restart - - - name: check-build - commands: - tools/rebuild-iso.sh trigger: From 08b4c078dd51d9a32dd135f09326824c29973212 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:11:22 +0100 Subject: [PATCH 150/407] Will it work now? --- .drone.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.drone.yml b/.drone.yml index b35ef16c..b4f07ab6 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,16 +1,17 @@ kind: pipeline type: docker -name: lint-pr +name: test-pr + +platform: + arch: arm64 steps: - - name: setup-env - image: ubuntu:latest - commands: - - apt install build-essential cmake ninja-build wget - - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz - - tar xf toolchain-linux-arm64.tar.gz - - tools/check-formatting.sh - - tools/rebuild-iso.sh +- name: test + image: ubuntu + commands: + - ./configure + - make + - make test trigger: branch: From d8a3d747797469d3c55a59503d433a98341631ab Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:13:12 +0100 Subject: [PATCH 151/407] Actual steps --- .drone.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index b4f07ab6..ecfdea0b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -9,9 +9,10 @@ steps: - name: test image: ubuntu commands: - - ./configure - - make - - make test + - apt install build-essential cmake ninja-build wget + - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz + - tar xf toolchain-linux-arm64.tar.gz + - tools/rebuild-iso.sh trigger: branch: From 82eda5d6aa998cfe3bb04210ac978292b273ab27 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:19:55 +0100 Subject: [PATCH 152/407] Update drone.yml --- .drone.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index ecfdea0b..300bd0c7 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,12 +6,15 @@ platform: arch: arm64 steps: -- name: test +- name: prepare image: ubuntu commands: + - apt update - apt install build-essential cmake ninja-build wget - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz - tar xf toolchain-linux-arm64.tar.gz +- name: build + commands: - tools/rebuild-iso.sh trigger: From f21d15307743dfb918c0cb234355b59076e69751 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:21:30 +0100 Subject: [PATCH 153/407] Update drone.yml --- .drone.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index 300bd0c7..d06e4e7c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,15 +6,13 @@ platform: arch: arm64 steps: -- name: prepare +- name: build image: ubuntu commands: - apt update - apt install build-essential cmake ninja-build wget - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz - tar xf toolchain-linux-arm64.tar.gz -- name: build - commands: - tools/rebuild-iso.sh trigger: From 0c9b822304f8f5217b2ed8c0eadd68f351937869 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:22:52 +0100 Subject: [PATCH 154/407] Update drone.yml --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index d06e4e7c..696fe33b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -10,7 +10,7 @@ steps: image: ubuntu commands: - apt update - - apt install build-essential cmake ninja-build wget + - apt install build-essential cmake ninja-build wget -y - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz - tar xf toolchain-linux-arm64.tar.gz - tools/rebuild-iso.sh From 744d39c27b8956c82b6163a9b5516ac27f87975b Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:24:34 +0100 Subject: [PATCH 155/407] Update drone.yml --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 696fe33b..0761b65e 100644 --- a/.drone.yml +++ b/.drone.yml @@ -11,7 +11,7 @@ steps: commands: - apt update - apt install build-essential cmake ninja-build wget -y - - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz + - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz --quiet - tar xf toolchain-linux-arm64.tar.gz - tools/rebuild-iso.sh From ca0e47b8e4549fb79fb52d5d188397f814917b8b Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:26:31 +0100 Subject: [PATCH 156/407] Update drone.yml --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 0761b65e..7fa8e166 100644 --- a/.drone.yml +++ b/.drone.yml @@ -10,7 +10,7 @@ steps: image: ubuntu commands: - apt update - - apt install build-essential cmake ninja-build wget -y + - apt install build-essential cmake ninja-build wget nasm -y - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz --quiet - tar xf toolchain-linux-arm64.tar.gz - tools/rebuild-iso.sh From bd7b9ad23759b52d3062c87e86d578a07c237531 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:44:44 +0100 Subject: [PATCH 157/407] Update drone.yml --- .drone.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 7fa8e166..f4807364 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,14 +6,22 @@ platform: arch: arm64 steps: -- name: build +- name: prepare image: ubuntu commands: - apt update - apt install build-essential cmake ninja-build wget nasm -y - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz --quiet - tar xf toolchain-linux-arm64.tar.gz + - rm toolchain-linux-arm64.tar.gz +- name: build + image: ubuntu + commands: - tools/rebuild-iso.sh +- name: check-formatting + image: ubuntu + commands: + - tools/check-formatting.sh trigger: branch: From ac2da14319feacb40cdf4519dda32379ad257a15 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:48:40 +0100 Subject: [PATCH 158/407] Update config for CI --- .drone.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.drone.yml b/.drone.yml index f4807364..7f50a960 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,7 +6,11 @@ platform: arch: arm64 steps: -- name: prepare +- name: check-formatting + image: ubuntu + commands: + - tools/check-formatting.sh +- name: build image: ubuntu commands: - apt update @@ -14,14 +18,7 @@ steps: - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz --quiet - tar xf toolchain-linux-arm64.tar.gz - rm toolchain-linux-arm64.tar.gz -- name: build - image: ubuntu - commands: - tools/rebuild-iso.sh -- name: check-formatting - image: ubuntu - commands: - - tools/check-formatting.sh trigger: branch: From 62e4ed824d9decb06de76f96fa6a21f4b268d19d Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 18:50:01 +0100 Subject: [PATCH 159/407] Update drone.yml --- .drone.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.drone.yml b/.drone.yml index 7f50a960..094073f4 100644 --- a/.drone.yml +++ b/.drone.yml @@ -9,6 +9,8 @@ steps: - name: check-formatting image: ubuntu commands: + - apt update + - apt install clang-format-14 -y - tools/check-formatting.sh - name: build image: ubuntu From 999d90d58892b6682ace204f1cad79076d773224 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:02:23 +0100 Subject: [PATCH 160/407] Update check-formatting.sh --- tools/check-formatting.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/check-formatting.sh b/tools/check-formatting.sh index 029a3a05..5e5699d5 100755 --- a/tools/check-formatting.sh +++ b/tools/check-formatting.sh @@ -12,8 +12,9 @@ ALL_OK=1 for f in ${SOURCES[@]} do - clang-format -n $f 2>&1 | grep ".*" >/dev/null - if [ "$?" = "0" ] + clang-format -n $f 2>&1 | grep -q ^ + RESULT=$? + if [ "$RESULT" = "0" ] then echo "File $f needs formatting" ALL_OK=0 From adf6844d49efd37232d699f301bf6e204de52de0 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:03:06 +0100 Subject: [PATCH 161/407] Update drone.yml --- .drone.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.drone.yml b/.drone.yml index 094073f4..bbff99c1 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,12 +6,6 @@ platform: arch: arm64 steps: -- name: check-formatting - image: ubuntu - commands: - - apt update - - apt install clang-format-14 -y - - tools/check-formatting.sh - name: build image: ubuntu commands: @@ -21,6 +15,12 @@ steps: - tar xf toolchain-linux-arm64.tar.gz - rm toolchain-linux-arm64.tar.gz - tools/rebuild-iso.sh +- name: check-formatting + image: ubuntu + commands: + - apt update + - apt install clang-format-14 grep -y + - tools/check-formatting.sh trigger: branch: From f767d9803765f764f256bba0277ea9dd87bee0e2 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:07:01 +0100 Subject: [PATCH 162/407] Please work --- tools/check-formatting.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/check-formatting.sh b/tools/check-formatting.sh index 5e5699d5..9be40812 100755 --- a/tools/check-formatting.sh +++ b/tools/check-formatting.sh @@ -14,7 +14,7 @@ for f in ${SOURCES[@]} do clang-format -n $f 2>&1 | grep -q ^ RESULT=$? - if [ "$RESULT" = "0" ] + if [ "$RESULT" -eq "0" ] then echo "File $f needs formatting" ALL_OK=0 From 2677fca5b757880288484f9182d3eaffd66132bd Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:09:33 +0100 Subject: [PATCH 163/407] Remove formatting step --- .drone.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.drone.yml b/.drone.yml index bbff99c1..a2b39437 100644 --- a/.drone.yml +++ b/.drone.yml @@ -15,12 +15,6 @@ steps: - tar xf toolchain-linux-arm64.tar.gz - rm toolchain-linux-arm64.tar.gz - tools/rebuild-iso.sh -- name: check-formatting - image: ubuntu - commands: - - apt update - - apt install clang-format-14 grep -y - - tools/check-formatting.sh trigger: branch: From 4ec6442ba05c56c8a5f94841e38fd5d0e1dcf8b1 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:16:11 +0100 Subject: [PATCH 164/407] Add build status badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 242b0ce8..a37b352c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Luna -A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C. (rewrite, listed features are currently mostly from the old version) +A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C. (rewrite, listed features are currently mostly from the old version) [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg?ref=refs/heads/restart)](https://drone.cloudapio.eu/apio/Luna) ## Features - x86_64-compatible [kernel](kernel/). From 20eeecb3e16edd37f41f8a5ef7cd51bcac4828ee Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:16:58 +0100 Subject: [PATCH 165/407] Run CI on push --- .drone.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.drone.yml b/.drone.yml index a2b39437..08e996c2 100644 --- a/.drone.yml +++ b/.drone.yml @@ -21,4 +21,5 @@ trigger: - main - restart event: + - push - pull_request \ No newline at end of file From bf7bcd7d5604e25c21a0754b45b5269bf3216b50 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:19:50 +0100 Subject: [PATCH 166/407] Rename CI pipeline --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 08e996c2..3df12e03 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,6 +1,6 @@ kind: pipeline type: docker -name: test-pr +name: test platform: arch: arm64 From eaf8a8aafe6c537f41f7effda1e172b25244fb13 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:26:27 +0100 Subject: [PATCH 167/407] Make sure the OS used in CI is Linux --- .drone.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.drone.yml b/.drone.yml index 3df12e03..d532a47f 100644 --- a/.drone.yml +++ b/.drone.yml @@ -4,6 +4,7 @@ name: test platform: arch: arm64 + os: linux steps: - name: build From a8fb4ca73986eaf2ee0460fdb89e7728922e11d3 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 19:57:41 +0100 Subject: [PATCH 168/407] Move CI badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a37b352c..fccd41f5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Luna -A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C. (rewrite, listed features are currently mostly from the old version) [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg?ref=refs/heads/restart)](https://drone.cloudapio.eu/apio/Luna) +A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C. [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg?ref=refs/heads/restart)](https://drone.cloudapio.eu/apio/Luna) (rewrite, listed features are currently mostly from the old version) ## Features - x86_64-compatible [kernel](kernel/). From d445b294776104b635c2edcd7f065dcfe279d865 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 20:36:24 +0100 Subject: [PATCH 169/407] Add a virtual memory allocator for the kernel --- kernel/CMakeLists.txt | 1 + kernel/src/memory/KernelVM.cpp | 104 +++++++++++++++++++++++++++++++++ kernel/src/memory/KernelVM.h | 18 ++++++ 3 files changed, 123 insertions(+) create mode 100644 kernel/src/memory/KernelVM.cpp create mode 100644 kernel/src/memory/KernelVM.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 687a9c56..e20cca1c 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES src/video/TextConsole.cpp src/memory/MemoryManager.cpp src/memory/Heap.cpp + src/memory/KernelVM.cpp src/memory/MemoryMap.cpp src/boot/Init.cpp src/arch/Serial.cpp diff --git a/kernel/src/memory/KernelVM.cpp b/kernel/src/memory/KernelVM.cpp new file mode 100644 index 00000000..0a4a445b --- /dev/null +++ b/kernel/src/memory/KernelVM.cpp @@ -0,0 +1,104 @@ +#include "memory/KernelVM.h" +#include "arch/MMU.h" +#include + +static const u64 KERNEL_VM_RANGE_START = 0xfffffffff0000000; + +static Bitmap g_kernelvm_bitmap; + +static u8 bitmap_memory[4096]; + +static const usize KERNEL_VM_RANGE_SIZE = (sizeof(bitmap_memory) * 8) * ARCH_PAGE_SIZE; + +static const u64 KERNEL_VM_RANGE_END = KERNEL_VM_RANGE_SIZE + KERNEL_VM_RANGE_START; + +static_assert(KERNEL_VM_RANGE_END == 0xfffffffff8000000); + +static usize g_used_vm; + +namespace KernelVM +{ + void init() + { + g_kernelvm_bitmap.initialize(bitmap_memory, sizeof(bitmap_memory)); + } + + Result alloc_one_page() + { + for (u64 index = 0; index < g_kernelvm_bitmap.size(); index++) + { + if (g_kernelvm_bitmap.get(index)) continue; + g_kernelvm_bitmap.set(index, true); + g_used_vm += ARCH_PAGE_SIZE; + return KERNEL_VM_RANGE_START + (index * ARCH_PAGE_SIZE); + } + + return err(ENOMEM); + } + + Result alloc_several_pages(usize count) + { + u64 first_free_index = 0; + u64 free_contiguous_pages = 0; + for (u64 index = 0; index < g_kernelvm_bitmap.size(); index++) + { + if (g_kernelvm_bitmap.get(index)) + { + free_contiguous_pages = 0; + continue; + } + + // At this point, we have a free page. + + if (!free_contiguous_pages) first_free_index = index; + free_contiguous_pages++; + + // Found enough contiguous free pages!! + if (free_contiguous_pages == count) + { + g_used_vm += ARCH_PAGE_SIZE * count; + g_kernelvm_bitmap.clear_region(first_free_index, count, true); + return KERNEL_VM_RANGE_START + (first_free_index * ARCH_PAGE_SIZE); + } + } + + return err(ENOMEM); + } + + Result free_one_page(u64 address) + { + if (address < KERNEL_VM_RANGE_START) return err(EFAULT); + + u64 index = (address - KERNEL_VM_RANGE_START) / ARCH_PAGE_SIZE; + + if (index >= g_kernelvm_bitmap.size()) return err(EFAULT); + + g_kernelvm_bitmap.set(index, false); + g_used_vm -= ARCH_PAGE_SIZE; + + return {}; + } + + Result free_several_pages(u64 address, usize count) + { + if (address < KERNEL_VM_RANGE_START) return err(EFAULT); + if (address + (count * ARCH_PAGE_SIZE) >= KERNEL_VM_RANGE_END) return err(EFAULT); + + u64 index = (address - KERNEL_VM_RANGE_START) / ARCH_PAGE_SIZE; + + g_kernelvm_bitmap.clear_region(index, count, false); + g_used_vm -= ARCH_PAGE_SIZE * count; + + return {}; + } + + usize used() + { + return g_used_vm; + } + + usize free() + { + return KERNEL_VM_RANGE_SIZE - g_used_vm; + } +} \ No newline at end of file diff --git a/kernel/src/memory/KernelVM.h b/kernel/src/memory/KernelVM.h new file mode 100644 index 00000000..9a7f358b --- /dev/null +++ b/kernel/src/memory/KernelVM.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include + +// Simple bitmap allocator which hands out kernel-space virtual addresses for use in kmalloc() and friends. +namespace KernelVM +{ + void init(); + + Result alloc_one_page(); + Result alloc_several_pages(usize count); + + Result free_one_page(u64 address); + Result free_several_pages(u64 address, usize count); + + usize free(); + usize used(); +} \ No newline at end of file From 0edabd6d8717e4aa65618e3c588a94c274c71081 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 21:00:21 +0100 Subject: [PATCH 170/407] Heap: Add a new block to the end of the linked list *facepalm* This was causing page faults when having two blocks and the first one (oldest one) being freed first. --- kernel/src/memory/Heap.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index a95244be..5887e7dc 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -222,6 +222,7 @@ Result kmalloc(usize size) block->status = BLOCK_START_MEM | BLOCK_END_MEM; block->next = nullptr; block->last = heap_end; + heap_end->next = block; heap_end = block; } From 6c3024d4ee8812146b4179f962b4638157b11af5 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 21:01:06 +0100 Subject: [PATCH 171/407] Heap: Count the heap blocks' size in the size required for an allocation --- kernel/src/memory/Heap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 5887e7dc..dc172a83 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -176,7 +176,7 @@ Result kmalloc(usize size) if (!heap_start) { - const usize pages = get_pages_for_allocation(size); + const usize pages = get_pages_for_allocation(size + sizeof(HeapBlock)); HeapBlock* const block = TRY(allocate_pages(pages)); block->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); @@ -214,7 +214,7 @@ Result kmalloc(usize size) if (!block) // No free blocks, let's allocate a new one { - usize pages = get_pages_for_allocation(size); + usize pages = get_pages_for_allocation(size + sizeof(HeapBlock)); block = TRY(allocate_pages(pages)); block->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); From ba758bcef8711f6418105598c45c528bd2133722 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 21:01:18 +0100 Subject: [PATCH 172/407] Initialize the KernelVM --- kernel/src/memory/MemoryManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 0122b9e8..d220710d 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -2,6 +2,7 @@ #include "Log.h" #include "arch/CPU.h" #include "arch/MMU.h" +#include "memory/KernelVM.h" #include "memory/MemoryMap.h" #include #include @@ -96,6 +97,7 @@ namespace MemoryManager void init() { init_physical_frame_allocator(); + KernelVM::init(); MMU::setup_initial_page_directory(); } From 1d0dd8fa939d82723e46249e7188c86bda8e513e Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 21:02:05 +0100 Subject: [PATCH 173/407] Use KernelVM in kmalloc() and friends Much better now!! --- kernel/src/memory/Heap.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index dc172a83..d3c87ac6 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -2,6 +2,7 @@ #include "Log.h" #include "arch/MMU.h" #include "arch/Serial.h" +#include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include #include @@ -31,20 +32,19 @@ static_assert(sizeof(HeapBlock) == 48UL); static HeapBlock* heap_start = nullptr; static HeapBlock* heap_end = nullptr; -static usize start_addr = 0xffffffff80000000; - static Result allocate_pages( usize count) // FIXME: Keep track of virtual address space usage. For now, since the address // space is so huge, we can just start at a fairly large address and assume // we'll never run into anything, but this will probably bite us in the future. { - void* const ptr = (void*)TRY(MemoryManager::alloc_at(start_addr, count, MMU::ReadWrite | MMU::NoExecute)); - if (ptr) start_addr += (count * ARCH_PAGE_SIZE); + u64 virt = TRY(KernelVM::alloc_several_pages(count)); + void* const ptr = (void*)TRY(MemoryManager::alloc_at(virt, count, MMU::ReadWrite | MMU::NoExecute)); return (HeapBlock*)ptr; } static Result release_pages(void* ptr, usize count) { + TRY(KernelVM::free_several_pages((u64)ptr, count)); return MemoryManager::unmap_owned((u64)ptr, count); } From 8ff9cb4b96c682650212c2bfe664e1f89b4525cc Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 5 Dec 2022 21:02:21 +0100 Subject: [PATCH 174/407] x86_64: Add a friendlier handler for page faults --- kernel/src/arch/x86_64/CPU.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 73ffbafd..fa1b86b8 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -293,7 +293,15 @@ static void setup_idt() kerrorln("FIXME(interrupt): %s", name); \ CPU::efficient_halt(); -extern "C" void handle_x86_exception([[maybe_unused]] Registers* regs) +[[noreturn]] void handle_page_fault(Registers* regs) +{ + u64 cr2; + asm volatile("mov %%cr2, %0" : "=r"(cr2)); + kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2); + CPU::efficient_halt(); +} + +extern "C" void handle_x86_exception(Registers* regs) { switch (regs->isr) { @@ -309,7 +317,7 @@ extern "C" void handle_x86_exception([[maybe_unused]] Registers* regs) case 11: FIXME_UNHANDLED_INTERRUPT("Segment not present"); case 12: FIXME_UNHANDLED_INTERRUPT("Stack-segment fault"); case 13: FIXME_UNHANDLED_INTERRUPT("General protection fault"); - case 14: FIXME_UNHANDLED_INTERRUPT("Page fault"); + case 14: handle_page_fault(regs); case 16: FIXME_UNHANDLED_INTERRUPT("x87 floating-point exception"); case 17: FIXME_UNHANDLED_INTERRUPT("Alignment check"); case 19: FIXME_UNHANDLED_INTERRUPT("SIMD floating-point exception"); From e91c04b1d110bb1739afefb4e5f9bd25db47934f Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 15:40:18 +0100 Subject: [PATCH 175/407] luna: Introduce safe arithmetic operations, which return an error if an operation would overflow --- luna/include/luna/SafeArithmetic.h | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 luna/include/luna/SafeArithmetic.h diff --git a/luna/include/luna/SafeArithmetic.h b/luna/include/luna/SafeArithmetic.h new file mode 100644 index 00000000..b0336d6d --- /dev/null +++ b/luna/include/luna/SafeArithmetic.h @@ -0,0 +1,38 @@ +#pragma once +#include + +template constexpr bool add_will_overflow(T a, T b) +{ + return __builtin_add_overflow_p(a, b, (T)0); +} + +template constexpr bool sub_will_overflow(T a, T b) +{ + return __builtin_sub_overflow_p(a, b, (T)0); +} + +template constexpr bool mul_will_overflow(T a, T b) +{ + return __builtin_mul_overflow_p(a, b, (T)0); +} + +template Result safe_add(T a, T b) +{ + if (add_will_overflow(a, b)) return err(EOVERFLOW); + + return a + b; +} + +template Result safe_sub(T a, T b) +{ + if (sub_will_overflow(a, b)) return err(EOVERFLOW); + + return a - b; +} + +template Result safe_mul(T a, T b) +{ + if (mul_will_overflow(a, b)) return err(EOVERFLOW); + + return a * b; +} \ No newline at end of file From b3381268547d2e7dc5adecab7f7995ce2cd3f97d Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 15:44:21 +0100 Subject: [PATCH 176/407] Heap: Use safe_mul in kcalloc() --- kernel/src/memory/Heap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index d3c87ac6..f1c76857 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -5,6 +5,7 @@ #include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include +#include #include #include @@ -332,8 +333,7 @@ Result krealloc(void* ptr, usize size) Result kcalloc(usize nmemb, usize size) { - // FIXME: Check for overflows. - const usize realsize = nmemb * size; + const usize realsize = TRY(safe_mul(nmemb, size)); void* const ptr = TRY(kmalloc(realsize)); return memset(ptr, 0, realsize); } From 26b44e651dedc2868027dcdc3ccf60f8ffbe0c25 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 15:47:59 +0100 Subject: [PATCH 177/407] Change safe_{sub,add,mul} so they perform the operation only once --- luna/include/luna/SafeArithmetic.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/luna/include/luna/SafeArithmetic.h b/luna/include/luna/SafeArithmetic.h index b0336d6d..31d59856 100644 --- a/luna/include/luna/SafeArithmetic.h +++ b/luna/include/luna/SafeArithmetic.h @@ -18,21 +18,27 @@ template constexpr bool mul_will_overflow(T a, T b) template Result safe_add(T a, T b) { - if (add_will_overflow(a, b)) return err(EOVERFLOW); + T result; - return a + b; + if (__builtin_add_overflow(a, b, &result)) return err(EOVERFLOW); + + return result; } template Result safe_sub(T a, T b) { - if (sub_will_overflow(a, b)) return err(EOVERFLOW); + T result; - return a - b; + if (__builtin_sub_overflow(a, b, &result)) return err(EOVERFLOW); + + return result; } template Result safe_mul(T a, T b) { - if (mul_will_overflow(a, b)) return err(EOVERFLOW); + T result; - return a * b; + if (__builtin_mul_overflow(a, b, &result)) return err(EOVERFLOW); + + return result; } \ No newline at end of file From 1fa99f4f640d56ce81e2799fe63396762be96127 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 15:53:06 +0100 Subject: [PATCH 178/407] Make {add,sub,mul}_will_overflow more compiler-independent --- luna/include/luna/SafeArithmetic.h | 42 +++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/luna/include/luna/SafeArithmetic.h b/luna/include/luna/SafeArithmetic.h index 31d59856..90cc3897 100644 --- a/luna/include/luna/SafeArithmetic.h +++ b/luna/include/luna/SafeArithmetic.h @@ -1,21 +1,6 @@ #pragma once #include -template constexpr bool add_will_overflow(T a, T b) -{ - return __builtin_add_overflow_p(a, b, (T)0); -} - -template constexpr bool sub_will_overflow(T a, T b) -{ - return __builtin_sub_overflow_p(a, b, (T)0); -} - -template constexpr bool mul_will_overflow(T a, T b) -{ - return __builtin_mul_overflow_p(a, b, (T)0); -} - template Result safe_add(T a, T b) { T result; @@ -41,4 +26,31 @@ template Result safe_mul(T a, T b) if (__builtin_mul_overflow(a, b, &result)) return err(EOVERFLOW); return result; +} + +template bool add_will_overflow(T a, T b) +{ +#ifdef __GNUC__ + return __builtin_add_overflow_p(a, b, (T)0); +#else + return safe_add(a, b).has_error(); +#endif +} + +template bool sub_will_overflow(T a, T b) +{ +#ifdef __GNUC__ + return __builtin_sub_overflow_p(a, b, (T)0); +#else + return safe_sub(a, b).has_error(); +#endif +} + +template bool mul_will_overflow(T a, T b) +{ +#ifdef __GNUC__ + return __builtin_mul_overflow_p(a, b, (T)0); +#else + return safe_mul(a, b).has_error(); +#endif } \ No newline at end of file From a021e7a309a0c22538eff58730e8a8c816e5c84e Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 16:41:22 +0100 Subject: [PATCH 179/407] Move make and destroy to luna --- kernel/src/memory/Heap.h | 12 ------------ luna/include/luna/Alloc.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 luna/include/luna/Alloc.h diff --git a/kernel/src/memory/Heap.h b/kernel/src/memory/Heap.h index 80d4b410..6e57f744 100644 --- a/kernel/src/memory/Heap.h +++ b/kernel/src/memory/Heap.h @@ -7,16 +7,4 @@ Result kcalloc(usize nmemb, usize size); Result krealloc(void* ptr, usize size); Result kfree(void* ptr); -template Result make() -{ - void* ptr = TRY(kcalloc(1, sizeof(T))); - return new (ptr) T; -} - -template Result destroy(T* item) -{ - item->~T(); - return kfree(item); -} - void dump_heap_usage(); \ No newline at end of file diff --git a/luna/include/luna/Alloc.h b/luna/include/luna/Alloc.h new file mode 100644 index 00000000..9985d363 --- /dev/null +++ b/luna/include/luna/Alloc.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include +#include + +template Result make() +{ + T* const result = new T; + if (!result) return err(ENOMEM); + return result; +} + +template Result make_array(usize count) +{ + T* const result = new T[count]; + if (!result) return err(ENOMEM); + return result; +} + +template void destroy(T* item) +{ + delete item; +} + +template void destroy_array(T* item) +{ + delete[] item; +} \ No newline at end of file From eef74e2897dacb1d7c7d68cadac3df8910c4aecc Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 17:35:38 +0100 Subject: [PATCH 180/407] Add a generic error code (ENONE) --- luna/include/luna/SystemError.h | 3 ++- luna/src/SystemError.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/luna/include/luna/SystemError.h b/luna/include/luna/SystemError.h index 0c952b57..16bef760 100644 --- a/luna/include/luna/SystemError.h +++ b/luna/include/luna/SystemError.h @@ -52,7 +52,8 @@ #define ETIMEDOUT 110 // Connection timed out #define EALREADY 114 // Operation already in progress -// This one is Luna-specific. +// These ones are Luna-specific. #define EFIXME 342 // Functionality not yet implemented +#define ENONE 343 // Internal or insignificant error const char* error_string(int error); \ No newline at end of file diff --git a/luna/src/SystemError.cpp b/luna/src/SystemError.cpp index 2e1f63ad..27aa0853 100644 --- a/luna/src/SystemError.cpp +++ b/luna/src/SystemError.cpp @@ -55,6 +55,7 @@ const char* error_string(int error) case ETIMEDOUT: return "Connection timed out"; case EALREADY: return "Operation already in progress"; case EFIXME: return "Functionality not yet implemented"; + case ENONE: return "Internal or insignificant error"; default: return "Unknown error"; } } \ No newline at end of file From dd29156c85265678c3120d07c3f24d2bd029cc0f Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 17:36:20 +0100 Subject: [PATCH 181/407] Alloc: make() now takes variadic arguments, to forward to the constructor --- luna/include/luna/Alloc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luna/include/luna/Alloc.h b/luna/include/luna/Alloc.h index 9985d363..fc89132f 100644 --- a/luna/include/luna/Alloc.h +++ b/luna/include/luna/Alloc.h @@ -3,9 +3,9 @@ #include #include -template Result make() +template Result make(Args... args) { - T* const result = new T; + T* const result = new T(args...); if (!result) return err(ENOMEM); return result; } From 87fb19520268842b09caa5094dca441ffa488769 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 17:37:43 +0100 Subject: [PATCH 182/407] Add DoublyLinkedList data structure --- luna/include/luna/LinkedList.h | 118 +++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 luna/include/luna/LinkedList.h diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h new file mode 100644 index 00000000..c4ab8f58 --- /dev/null +++ b/luna/include/luna/LinkedList.h @@ -0,0 +1,118 @@ +#pragma once +#include + +template inline Result nonnull_or_error(T* ptr) +{ + return ptr == nullptr ? err(ENONE) : ptr; +} + +template class DoublyLinkedList; + +template class DoublyLinkedListNode +{ + + private: + DoublyLinkedListNode* m_next_node; + DoublyLinkedListNode* m_last_node; + + void detach_from_list() + { + m_next_node->m_last_node = m_last_node; + m_last_node->m_next_node = m_next_node; + } + + void add_to_list(DoublyLinkedListNode* end_node) + { + end_node->m_next_node = this; + this->m_last_node = end_node; + } + + friend class DoublyLinkedList; +}; + +template class DoublyLinkedList +{ + public: + void append(T* ptr) + { + DoublyLinkedListNode* node = (DoublyLinkedListNode*)ptr; + if (!m_start_node) m_start_node = node; + if (m_end_node) node->add_to_list(m_end_node); + m_end_node = node; + + m_count++; + } + + T* remove(T* ptr) + { + DoublyLinkedListNode* node = (DoublyLinkedListNode*)ptr; + + if (node == m_end_node) m_end_node = node->m_last_node; + if (node == m_start_node) m_start_node = node->m_next_node; + + node->detach_from_list(); + + m_count--; + + return ptr; + } + + Result first() + { + return nonnull_or_error((T*)m_start_node); + } + + Result last() + { + return nonnull_or_error((T*)m_end_node); + } + + Result next(T* item) + { + return nonnull_or_error(((DoublyLinkedListNode*)item)->m_next_node); + } + + Result previous(T* item) + { + return nonnull_or_error(((DoublyLinkedListNode*)item)->m_last_node); + } + + template void for_each(Callback callback) + { + for (DoublyLinkedListNode* node = m_start_node; node; node = node->m_next_node) { callback((T*)node); } + } + + template void for_each_reversed(Callback callback) + { + for (DoublyLinkedListNode* node = m_end_node; node; node = node->m_last_node) { callback((T*)node); } + } + + template void for_each_after(T* start, Callback callback) + { + for (DoublyLinkedListNode* node = ((DoublyLinkedListNode*)start)->m_next_node; node; + node = node->m_next_node) + { + callback((T*)node); + } + } + + template void for_each_before(T* end, Callback callback) + { + for (DoublyLinkedListNode* node = ((DoublyLinkedListNode*)end)->m_last_node; node; + node = node->m_last_node) + { + callback((T*)node); + } + } + + usize count() + { + return m_count; + } + + private: + DoublyLinkedListNode* m_start_node = nullptr; + DoublyLinkedListNode* m_end_node = nullptr; + + usize m_count = 0; +}; \ No newline at end of file From cccf89dd16b70724b83d2d6086be6139711e32e6 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 18:20:18 +0100 Subject: [PATCH 183/407] Heap: Remove outdated FIXME --- kernel/src/memory/Heap.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index f1c76857..31a1004c 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -33,10 +33,7 @@ static_assert(sizeof(HeapBlock) == 48UL); static HeapBlock* heap_start = nullptr; static HeapBlock* heap_end = nullptr; -static Result allocate_pages( - usize count) // FIXME: Keep track of virtual address space usage. For now, since the address - // space is so huge, we can just start at a fairly large address and assume - // we'll never run into anything, but this will probably bite us in the future. +static Result allocate_pages(usize count) { u64 virt = TRY(KernelVM::alloc_several_pages(count)); void* const ptr = (void*)TRY(MemoryManager::alloc_at(virt, count, MMU::ReadWrite | MMU::NoExecute)); From 2734353a5d567d7b3124589ca2d4993154404f28 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 18:21:19 +0100 Subject: [PATCH 184/407] Heap: Just align it on a 16-byte boundary if it's not aligned --- kernel/src/memory/Heap.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 31a1004c..b77a0646 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -85,8 +85,7 @@ static usize get_fair_offset_to_split_at(HeapBlock* block, usize min) available -= (available / 2); // reserve half of the rest for the new block, while still leaving another half for the old one. - check(is_aligned(available, - 16UL)); // If necessary, we can just align it. This is more of a sanity check than a requirement. + available = align_down(available, 16UL); // Everything has to be aligned on a 16-byte boundary return available + block->req_size; } From 07e6ebd3cc0ca08fba936c6547726ce6dbbaa166 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 18:22:45 +0100 Subject: [PATCH 185/407] LinkedList: Fix nonnull_or_error --- luna/include/luna/LinkedList.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index c4ab8f58..081dec8e 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -3,7 +3,9 @@ template inline Result nonnull_or_error(T* ptr) { - return ptr == nullptr ? err(ENONE) : ptr; + if (ptr == nullptr) return err(ENONE); + else + return ptr; } template class DoublyLinkedList; @@ -69,12 +71,12 @@ template class DoublyLinkedList Result next(T* item) { - return nonnull_or_error(((DoublyLinkedListNode*)item)->m_next_node); + return nonnull_or_error((T*)((DoublyLinkedListNode*)item)->m_next_node); } Result previous(T* item) { - return nonnull_or_error(((DoublyLinkedListNode*)item)->m_last_node); + return nonnull_or_error((T*)((DoublyLinkedListNode*)item)->m_last_node); } template void for_each(Callback callback) From 146da13e432e35a29f42f60f781fd5c5b0284c3a Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 18:23:19 +0100 Subject: [PATCH 186/407] LinkedList: Make sure to explicitly mark the first node's next and last nodes as nullptr --- luna/include/luna/LinkedList.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 081dec8e..e6056a19 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -40,6 +40,8 @@ template class DoublyLinkedList DoublyLinkedListNode* node = (DoublyLinkedListNode*)ptr; if (!m_start_node) m_start_node = node; if (m_end_node) node->add_to_list(m_end_node); + else + node->m_next_node = node->m_last_node = nullptr; m_end_node = node; m_count++; From d8f75f1d3c1734e108b91db2eea5ce0a088ff26e Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 18:25:08 +0100 Subject: [PATCH 187/407] LinkedList: Add an append_after() method Can be used to append an item after another one instead of at the end of the list. With doubly linked lists, this is extremely easy to achieve (O(1)). --- luna/include/luna/LinkedList.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index e6056a19..e5e1e279 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -47,6 +47,20 @@ template class DoublyLinkedList m_count++; } + void append_after(T* base, T* ptr) + { + DoublyLinkedListNode* new_node = (DoublyLinkedListNode*)ptr; + DoublyLinkedListNode* base_node = (DoublyLinkedListNode*)base; + + if (m_end_node == base_node) m_end_node = new_node; + + new_node->m_next_node = base_node->m_next_node; + base_node->m_next_node = new_node; + new_node->m_last_node = base_node; + + m_count++; + } + T* remove(T* ptr) { DoublyLinkedListNode* node = (DoublyLinkedListNode*)ptr; From 09e447d9d2e0fd519a932f14d4aa800b83b7c88d Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 18:28:04 +0100 Subject: [PATCH 188/407] Heap: Use LinkedList instead of doing things manually --- kernel/src/memory/Heap.cpp | 73 +++++++++++++++----------------------- 1 file changed, 28 insertions(+), 45 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index b77a0646..d0f65e5d 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -5,6 +5,7 @@ #include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include +#include #include #include #include @@ -18,20 +19,17 @@ static constexpr usize BLOCK_DEAD = 0xdeaddeaddeaddead; static constexpr usize MINIMUM_PAGES_PER_ALLOCATION = 4; -struct HeapBlock +struct HeapBlock : DoublyLinkedListNode { usize req_size; usize full_size; int status; - HeapBlock* next; - HeapBlock* last; usize magic; }; static_assert(sizeof(HeapBlock) == 48UL); -static HeapBlock* heap_start = nullptr; -static HeapBlock* heap_end = nullptr; +static DoublyLinkedList heap; static Result allocate_pages(usize count) { @@ -96,7 +94,8 @@ static Result split(HeapBlock* block, usize size) const usize old_size = block->full_size; // Save the old value of this variable since we are going to use it after modifying it - if (available < (size + sizeof(HeapBlock))) return err(0); // This error is not propagated. + if (available < (size + sizeof(HeapBlock))) + return err(ENONE); // This block hasn't got enough free space to hold the requested size. const usize offset = get_fair_offset_to_split_at(block, size + sizeof(HeapBlock)); block->full_size = offset; // shrink the old block to fit this offset @@ -106,24 +105,20 @@ static Result split(HeapBlock* block, usize size) new_block->magic = BLOCK_MAGIC; new_block->status = (block->status & BLOCK_END_MEM) ? BLOCK_END_MEM : 0; new_block->full_size = old_size - (offset + sizeof(HeapBlock)); - new_block->next = block->next; - new_block->last = block; + heap.append_after(block, new_block); - block->status &= ~BLOCK_END_MEM; // this block is no longer the last block in this memory range - block->next = new_block; + block->status &= ~BLOCK_END_MEM; // this block is no longer the last block in its memory range return new_block; } static Result combine_forward(HeapBlock* block) { - HeapBlock* const next = block->next; - if (next == heap_end) heap_end = block; + // The caller needs to ensure there is a next block. + HeapBlock* const next = heap.next(block).value(); + heap.remove(next); next->magic = BLOCK_DEAD; - block->next = block->next->next; - if (block->next) block->next->last = block; - if (next->status & BLOCK_END_MEM) { if (next->status & BLOCK_START_MEM) @@ -142,13 +137,11 @@ static Result combine_forward(HeapBlock* block) static Result combine_backward(HeapBlock* block) { - HeapBlock* const last = block->last; - if (block == heap_end) heap_end = last; + // The caller needs to ensure there is a last block. + HeapBlock* const last = heap.previous(block).value(); + heap.remove(block); block->magic = BLOCK_DEAD; - last->next = block->next; - if (last->next) last->next->last = last; - if (block->status & BLOCK_END_MEM) { if (block->status & BLOCK_START_MEM) @@ -171,7 +164,7 @@ Result kmalloc(usize size) size = align_up(size, 16UL); - if (!heap_start) + if (!heap.first().has_value()) { const usize pages = get_pages_for_allocation(size + sizeof(HeapBlock)); HeapBlock* const block = TRY(allocate_pages(pages)); @@ -179,15 +172,10 @@ Result kmalloc(usize size) block->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); block->magic = BLOCK_MAGIC; block->status = BLOCK_START_MEM | BLOCK_END_MEM; - block->next = block->last = nullptr; - heap_start = block; - - check(!heap_end); - - heap_end = heap_start; + heap.append(block); } - HeapBlock* block = heap_start; + HeapBlock* block = heap.first().value(); while (block) { // Trying to find a free block... @@ -195,7 +183,7 @@ Result kmalloc(usize size) { if (block->full_size < size) { - block = block->next; // Let's not try to split this block, it's not big enough + block = heap.next(block).value_or(nullptr); continue; } break; // We found a free block that's big enough!! @@ -203,10 +191,10 @@ Result kmalloc(usize size) auto rc = split(block, size); if (rc.has_value()) { - block = rc.release_value(); // We managed to get a free block from a larger used block!! + block = rc.value(); // We managed to get a free block from a larger used block!! break; } - block = block->next; + block = heap.next(block).value_or(nullptr); } if (!block) // No free blocks, let's allocate a new one @@ -217,11 +205,7 @@ Result kmalloc(usize size) block->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); block->magic = BLOCK_MAGIC; block->status = BLOCK_START_MEM | BLOCK_END_MEM; - block->next = nullptr; - block->last = heap_end; - heap_end->next = block; - - heap_end = block; + heap.append(block); } block->req_size = size; @@ -257,13 +241,15 @@ Result kfree(void* ptr) else block->status &= ~BLOCK_USED; - if (block->next && is_block_free(block->next)) + auto maybe_next = heap.next(block); + if (maybe_next.has_value() && is_block_free(maybe_next.value())) { // The next block is also free, thus we can merge! TRY(combine_forward(block)); } - if (block->last && is_block_free(block->last)) + auto maybe_last = heap.previous(block); + if (maybe_last.has_value() && is_block_free(maybe_last.value())) { // The last block is also free, thus we can merge! block = TRY(combine_backward(block)); @@ -271,10 +257,7 @@ Result kfree(void* ptr) if ((block->status & BLOCK_START_MEM) && (block->status & BLOCK_END_MEM)) { - if (block == heap_start) heap_start = block->next; - if (block == heap_end) heap_end = block->last; - if (block->last) block->last->next = block->next; - if (block->next) block->next->last = block->last; + heap.remove(block); TRY(release_pages(block, get_blocks_from_size(block->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE))); } @@ -337,14 +320,14 @@ Result kcalloc(usize nmemb, usize size) void dump_heap_usage() { kdbgln("-- Dumping usage stats for kernel heap:"); - if (!heap_start) + if (!heap.count()) { kdbgln("- Heap is not currently being used"); return; } usize alloc_total = 0; usize alloc_used = 0; - HeapBlock* block = heap_start; + HeapBlock* block = heap.first().value(); while (block) { if (is_block_free(block)) @@ -358,7 +341,7 @@ void dump_heap_usage() alloc_total += block->full_size + sizeof(HeapBlock); alloc_used += block->req_size; } - block = block->next; + block = heap.next(block).value_or(nullptr); } kdbgln("-- Total memory allocated for heap: %zu bytes", alloc_total); From b5c6ae253dc286c86cadc68e854e02e2c99cb69a Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 18:41:35 +0100 Subject: [PATCH 189/407] Make LinkedList a lot better --- luna/include/luna/LinkedList.h | 81 ++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index e5e1e279..5e343b3d 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -12,10 +12,31 @@ template class DoublyLinkedList; template class DoublyLinkedListNode { + using SelfType = DoublyLinkedListNode; private: - DoublyLinkedListNode* m_next_node; - DoublyLinkedListNode* m_last_node; + SelfType* m_next_node; + SelfType* m_last_node; + + void set_next(SelfType* next) + { + m_next_node = next; + } + + void set_last(SelfType* last) + { + m_last_node = last; + } + + SelfType* get_next() + { + return m_next_node; + } + + SelfType* get_last() + { + return m_last_node; + } void detach_from_list() { @@ -23,7 +44,7 @@ template class DoublyLinkedListNode m_last_node->m_next_node = m_next_node; } - void add_to_list(DoublyLinkedListNode* end_node) + void add_to_list(SelfType* end_node) { end_node->m_next_node = this; this->m_last_node = end_node; @@ -34,14 +55,19 @@ template class DoublyLinkedListNode template class DoublyLinkedList { + using Node = DoublyLinkedListNode; + public: void append(T* ptr) { - DoublyLinkedListNode* node = (DoublyLinkedListNode*)ptr; + Node* const node = extract_node(ptr); if (!m_start_node) m_start_node = node; if (m_end_node) node->add_to_list(m_end_node); else - node->m_next_node = node->m_last_node = nullptr; + { + node->set_next(nullptr); + node->set_last(nullptr); + } m_end_node = node; m_count++; @@ -49,24 +75,24 @@ template class DoublyLinkedList void append_after(T* base, T* ptr) { - DoublyLinkedListNode* new_node = (DoublyLinkedListNode*)ptr; - DoublyLinkedListNode* base_node = (DoublyLinkedListNode*)base; + Node* const new_node = extract_node(ptr); + Node* const base_node = extract_node(base); if (m_end_node == base_node) m_end_node = new_node; - new_node->m_next_node = base_node->m_next_node; - base_node->m_next_node = new_node; - new_node->m_last_node = base_node; + new_node->set_next(base_node->get_next()); + base_node->set_next(new_node); + new_node->set_last(base_node); m_count++; } T* remove(T* ptr) { - DoublyLinkedListNode* node = (DoublyLinkedListNode*)ptr; + Node* const node = extract_node(ptr); - if (node == m_end_node) m_end_node = node->m_last_node; - if (node == m_start_node) m_start_node = node->m_next_node; + if (node == m_end_node) m_end_node = node->get_last(); + if (node == m_start_node) m_start_node = node->get_next(); node->detach_from_list(); @@ -87,40 +113,32 @@ template class DoublyLinkedList Result next(T* item) { - return nonnull_or_error((T*)((DoublyLinkedListNode*)item)->m_next_node); + return nonnull_or_error((T*)extract_node(item)->get_next()); } Result previous(T* item) { - return nonnull_or_error((T*)((DoublyLinkedListNode*)item)->m_last_node); + return nonnull_or_error((T*)extract_node(item)->get_last()); } template void for_each(Callback callback) { - for (DoublyLinkedListNode* node = m_start_node; node; node = node->m_next_node) { callback((T*)node); } + for (Node* node = m_start_node; node; node = node->get_next()) { callback((T*)node); } } template void for_each_reversed(Callback callback) { - for (DoublyLinkedListNode* node = m_end_node; node; node = node->m_last_node) { callback((T*)node); } + for (Node* node = m_end_node; node; node = node->get_last()) { callback((T*)node); } } template void for_each_after(T* start, Callback callback) { - for (DoublyLinkedListNode* node = ((DoublyLinkedListNode*)start)->m_next_node; node; - node = node->m_next_node) - { - callback((T*)node); - } + for (Node* node = extract_node(start)->m_next_node; node; node = node->get_next()) { callback((T*)node); } } template void for_each_before(T* end, Callback callback) { - for (DoublyLinkedListNode* node = ((DoublyLinkedListNode*)end)->m_last_node; node; - node = node->m_last_node) - { - callback((T*)node); - } + for (Node* node = extract_node(end)->m_last_node; node; node = node->get_last()) { callback((T*)node); } } usize count() @@ -129,8 +147,13 @@ template class DoublyLinkedList } private: - DoublyLinkedListNode* m_start_node = nullptr; - DoublyLinkedListNode* m_end_node = nullptr; + Node* m_start_node = nullptr; + Node* m_end_node = nullptr; + + Node* extract_node(T* item) + { + return (Node*)item; + } usize m_count = 0; }; \ No newline at end of file From d48eb85d1d8205c8b0dc68f459e72675cc1a656e Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 19:05:00 +0100 Subject: [PATCH 190/407] Heap: Avoid magic numbers --- kernel/src/memory/Heap.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index d0f65e5d..703b7922 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -29,6 +29,8 @@ struct HeapBlock : DoublyLinkedListNode static_assert(sizeof(HeapBlock) == 48UL); +static const isize HEAP_BLOCK_SIZE = 48; + static DoublyLinkedList heap; static Result allocate_pages(usize count) @@ -64,14 +66,15 @@ static usize space_available(HeapBlock* block) return block->full_size - block->req_size; } +// The heap block is stored right behind a memory block. static HeapBlock* get_heap_block_for_pointer(void* ptr) { - return (HeapBlock*)offset_ptr(ptr, -48); + return (HeapBlock*)offset_ptr(ptr, -HEAP_BLOCK_SIZE); } static void* get_pointer_from_heap_block(HeapBlock* block) { - return (void*)offset_ptr(block, 48); + return (void*)offset_ptr(block, HEAP_BLOCK_SIZE); } static usize get_fair_offset_to_split_at(HeapBlock* block, usize min) From 39b310b6b9ce114984c04677e5eaced75e96bf44 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 19:27:58 +0100 Subject: [PATCH 191/407] Make alignment a template parameter to help the compiler optimize --- kernel/src/memory/Heap.cpp | 6 ++--- kernel/src/memory/MemoryManager.cpp | 6 ++--- luna/include/luna/Alignment.h | 35 ++++++++++++++++------------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 703b7922..ad16eebe 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -86,7 +86,7 @@ static usize get_fair_offset_to_split_at(HeapBlock* block, usize min) available -= (available / 2); // reserve half of the rest for the new block, while still leaving another half for the old one. - available = align_down(available, 16UL); // Everything has to be aligned on a 16-byte boundary + available = align_down<16>(available); // Everything has to be aligned on a 16-byte boundary return available + block->req_size; } @@ -165,7 +165,7 @@ Result kmalloc(usize size) { if (!size) return (void*)BLOCK_MAGIC; - size = align_up(size, 16UL); + size = align_up<16>(size); if (!heap.first().has_value()) { @@ -291,7 +291,7 @@ Result krealloc(void* ptr, usize size) return err(EFAULT); } - size = align_up(size, 16UL); + size = align_up<16>(size); if (is_block_free(block)) { diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index d220710d..acaaf1b1 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -23,7 +23,7 @@ static u64 start_index = 0; static Bitmap g_frame_bitmap; -#define CHECK_PAGE_ALIGNED(address) expect(is_aligned(address, ARCH_PAGE_SIZE), "Address is not page-aligned") +#define CHECK_PAGE_ALIGNED(address) expect(is_aligned(address), "Address is not page-aligned") static usize get_physical_address_space_size() { @@ -215,8 +215,8 @@ namespace MemoryManager Result remap_unaligned(u64 address, usize count, int flags) { - if (!is_aligned(address, ARCH_PAGE_SIZE)) count++; - address = align_down(address, ARCH_PAGE_SIZE); + if (!is_aligned(address)) count++; + address = align_down(address); while (count--) { diff --git a/luna/include/luna/Alignment.h b/luna/include/luna/Alignment.h index 0721aae5..439bf2a1 100644 --- a/luna/include/luna/Alignment.h +++ b/luna/include/luna/Alignment.h @@ -1,32 +1,37 @@ #pragma once -template constexpr T is_aligned(T value, T alignment) +// Must ALWAYS be called with a power of two as alignment. +template constexpr T is_aligned(T value) { + static_assert((alignment & (alignment - 1)) == 0); return (value % alignment == 0); } -static_assert(is_aligned(1024, 512)); -static_assert(!is_aligned(235, 32)); -static_assert(is_aligned(40960, 4096)); +static_assert(is_aligned<512>(1024)); +static_assert(!is_aligned<32>(235)); +static_assert(is_aligned<4096>(40960)); -template constexpr T align_down(T value, T alignment) +// Must ALWAYS be called with a power of two as alignment. +template constexpr T align_down(T value) { - return value - (value % alignment); + static_assert((alignment & (alignment - 1)) == 0); + return value - value % alignment; } -static_assert(align_down(598, 512) == 512); -static_assert(align_down(194, 64) == 192); -static_assert(align_down(62, 31) == 62); +static_assert(align_down<512>(598) == 512); +static_assert(align_down<64>(194) == 192); +static_assert(align_down<32>(64) == 64); -template constexpr T align_up(T value, T alignment) +// Must ALWAYS be called with a power of two as alignment. +template constexpr T align_up(T value) { - if (is_aligned(value, alignment)) return value; - return align_down(value, alignment) + alignment; + if (is_aligned(value)) return value; + return align_down(value) + alignment; } -static_assert(align_up(598, 512) == 1024); -static_assert(align_up(194, 64) == 256); -static_assert(align_up(62, 31) == 62); +static_assert(align_up<512>(598) == 1024); +static_assert(align_up<64>(194) == 256); +static_assert(align_up<32>(64) == 64); template constexpr T get_blocks_from_size(T value, T block_size) { From 314acbfe21b6bcee500a1b5b98e7645916b89ea7 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 19:31:41 +0100 Subject: [PATCH 192/407] Change the serial log to display only milliseconds --- kernel/src/Log.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 0b008e58..2dd3291b 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -25,7 +25,7 @@ static Result log_serial(LogLevel level, const char* format, va_list origi TRY(Serial::printf("\x1b[%sm%c\x1b[0m ", ansi_color_codes_per_log_level[(int)level], log_level_letters[(int)level])); - TRY(Serial::printf("[%6zu.%.6zu] ", Timer::ticks(), Timer::ticks_us() - (Timer::ticks() * 1000000))); + TRY(Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000))); TRY(cstyle_format( format, From c099877c35c1ebee5598117c0d58e78314725cf1 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 19:35:34 +0100 Subject: [PATCH 193/407] Remove unnecessary error propagation in Log.cpp Serial and TextConsole always succeed, no need to act as if they could fail --- kernel/src/Log.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 2dd3291b..e4079699 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -17,32 +17,29 @@ static constexpr u32 RED = 0xffff0000; static char log_level_letters[] = {'D', 'I', 'W', 'E'}; // D for debug, I for info, W for warning, E for error static const char* ansi_color_codes_per_log_level[] = {"37", "37", "33", "31"}; // 37 is white, 33 yellow, 31 red -static Result log_serial(LogLevel level, const char* format, va_list origin) +static void log_serial(LogLevel level, const char* format, va_list origin) { va_list ap; va_copy(ap, origin); - TRY(Serial::printf("\x1b[%sm%c\x1b[0m ", ansi_color_codes_per_log_level[(int)level], - log_level_letters[(int)level])); + Serial::printf("\x1b[%sm%c\x1b[0m ", ansi_color_codes_per_log_level[(int)level], log_level_letters[(int)level]); - TRY(Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000))); + Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000)); - TRY(cstyle_format( + cstyle_format( format, [](char c, void*) -> Result { Serial::putchar(c); return {}; }, - nullptr, ap)); + nullptr, ap); Serial::putchar('\n'); va_end(ap); - - return {}; } -static Result log_text_console(LogLevel level, const char* format, va_list origin) +static void log_text_console(LogLevel level, const char* format, va_list origin) { va_list ap; va_copy(ap, origin); @@ -58,13 +55,13 @@ static Result log_text_console(LogLevel level, const char* format, va_list else TextConsole::set_foreground(WHITE); - TRY(cstyle_format( + cstyle_format( format, [](char c, void*) -> Result { TextConsole::putchar(c); return {}; }, - nullptr, ap)); + nullptr, ap); TextConsole::putchar('\n'); @@ -73,16 +70,14 @@ static Result log_text_console(LogLevel level, const char* format, va_list TextConsole::set_foreground(original_foreground); va_end(ap); - - return {}; } Result vlog(LogLevel level, const char* format, va_list ap) { if (!g_debug_enabled && level == LogLevel::Debug) return {}; - if (g_serial_enabled) TRY(log_serial(level, format, ap)); - if (g_text_console_enabled) TRY(log_text_console(level, format, ap)); + if (g_serial_enabled) log_serial(level, format, ap); + if (g_text_console_enabled) log_text_console(level, format, ap); return {}; } From 8598b1e8fcaa8e863a693341499cf52082baa816 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 19:40:35 +0100 Subject: [PATCH 194/407] Replace the _noreturn macro with the C++ native attribute [[noreturn]] --- kernel/src/Log.cpp | 2 +- luna/include/luna/Attributes.h | 3 +-- luna/include/luna/Check.h | 2 +- luna/src/Check.cpp | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index e4079699..5d242ac6 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -118,7 +118,7 @@ bool log_text_console_enabled() static bool g_check_already_failed = false; -_noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr) +[[noreturn]] bool __check_failed(const char* file, const char* line, const char* func, const char* expr) { if (!g_check_already_failed) { // Avoid endlessly failing when trying to report a failed check. diff --git a/luna/include/luna/Attributes.h b/luna/include/luna/Attributes.h index f137161d..2f8edf7e 100644 --- a/luna/include/luna/Attributes.h +++ b/luna/include/luna/Attributes.h @@ -2,5 +2,4 @@ #define _weak __attribute__((weak)) #define _format(n, m) __attribute__((format(printf, n, m))) -#define _align(x) __attribute__((aligned(x))) -#define _noreturn __attribute__((noreturn)) \ No newline at end of file +#define _align(x) __attribute__((aligned(x))) \ No newline at end of file diff --git a/luna/include/luna/Check.h b/luna/include/luna/Check.h index fe1c7f50..37c3b13f 100644 --- a/luna/include/luna/Check.h +++ b/luna/include/luna/Check.h @@ -1,7 +1,7 @@ #pragma once #include -extern _noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr); +[[noreturn]] extern bool __check_failed(const char* file, const char* line, const char* func, const char* expr); #ifndef STRINGIZE_VALUE_OF #define STRINGIZE(x) #x diff --git a/luna/src/Check.cpp b/luna/src/Check.cpp index 4f522f79..f01fef8d 100644 --- a/luna/src/Check.cpp +++ b/luna/src/Check.cpp @@ -1,6 +1,6 @@ #include -_weak _noreturn bool __check_failed(const char*, const char*, const char*, const char*) +_weak [[noreturn]] bool __check_failed(const char*, const char*, const char*, const char*) { __builtin_trap(); } \ No newline at end of file From 1ebd892c1666fa54eabc141a97ddff487db268f1 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 10:55:47 +0100 Subject: [PATCH 195/407] Convert uses of u64 to usize Not all of them, but if you're measuring a size it's more appropriate to use usize than u64. --- kernel/src/memory/MemoryManager.cpp | 28 ++++++++++++++-------------- kernel/src/memory/MemoryManager.h | 10 +++++----- kernel/src/memory/MemoryMap.cpp | 2 +- kernel/src/memory/MemoryMap.h | 6 +++--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index acaaf1b1..8ebe0b98 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -15,9 +15,9 @@ extern const u8 end_of_kernel_rodata[1]; extern const u8 start_of_kernel_data[1]; extern const u8 end_of_kernel_data[1]; -static u64 free_mem = 0; -static u64 used_mem = 0; -static u64 reserved_mem = 0; +static usize free_mem = 0; +static usize used_mem = 0; +static usize reserved_mem = 0; static u64 start_index = 0; @@ -38,12 +38,12 @@ namespace MemoryManager { Result protect_kernel_sections() { - const u64 rodata_size = (u64)(end_of_kernel_rodata - start_of_kernel_rodata); - const u64 rodata_pages = get_blocks_from_size(rodata_size, ARCH_PAGE_SIZE); + const usize rodata_size = (usize)(end_of_kernel_rodata - start_of_kernel_rodata); + const usize rodata_pages = get_blocks_from_size(rodata_size, ARCH_PAGE_SIZE); TRY(remap((u64)start_of_kernel_rodata, rodata_pages, MMU::NoExecute)); - const u64 data_size = (u64)(end_of_kernel_data - start_of_kernel_data); - const u64 data_pages = get_blocks_from_size(data_size, ARCH_PAGE_SIZE); + const usize data_size = (usize)(end_of_kernel_data - start_of_kernel_data); + const usize data_pages = get_blocks_from_size(data_size, ARCH_PAGE_SIZE); TRY(remap((u64)start_of_kernel_data, data_pages, MMU::NoExecute | MMU::ReadWrite)); return {}; @@ -81,7 +81,7 @@ namespace MemoryManager while (iter.next().try_set_value(entry)) { const u64 index = entry.address() / ARCH_PAGE_SIZE; - const u64 pages = entry.size() / ARCH_PAGE_SIZE; + const usize pages = entry.size() / ARCH_PAGE_SIZE; if (!entry.is_free()) { reserved_mem += entry.size(); } else { @@ -110,9 +110,9 @@ namespace MemoryManager free_mem -= ARCH_PAGE_SIZE; } - void lock_frames(u64 frames, u64 count) + void lock_frames(u64 frames, usize count) { - for (u64 index = 0; index < count; index++) { lock_frame(frames + (index * ARCH_PAGE_SIZE)); } + for (usize index = 0; index < count; index++) { lock_frame(frames + (index * ARCH_PAGE_SIZE)); } } Result alloc_frame() @@ -242,22 +242,22 @@ namespace MemoryManager return false; } - u64 free() + usize free() { return free_mem; } - u64 used() + usize used() { return used_mem; } - u64 reserved() + usize reserved() { return reserved_mem; } - u64 total() + usize total() { return free_mem + used_mem + reserved_mem; } diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 8179e12e..5ef62177 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -12,7 +12,7 @@ namespace MemoryManager Result free_frame(u64 frame); void lock_frame(u64 frame); - void lock_frames(u64 frames, u64 count); + void lock_frames(u64 frames, usize count); Result remap(u64 address, usize count, int flags); Result remap_unaligned(u64 address, usize count, int flags); @@ -27,8 +27,8 @@ namespace MemoryManager Result unmap_owned(u64 virt, usize count); Result unmap_weak(u64 virt, usize count); - u64 free(); - u64 used(); - u64 reserved(); - u64 total(); + usize free(); + usize used(); + usize reserved(); + usize total(); } \ No newline at end of file diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index 9573a7d7..4aa24521 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -2,7 +2,7 @@ extern const BOOTBOOT bootboot; -MemoryMapEntry::MemoryMapEntry(u64 address, u64 size, bool is_free) +MemoryMapEntry::MemoryMapEntry(u64 address, usize size, bool is_free) : m_address(address), m_size(size), m_is_free(is_free) { } diff --git a/kernel/src/memory/MemoryMap.h b/kernel/src/memory/MemoryMap.h index 05b30b8d..4c53bde4 100644 --- a/kernel/src/memory/MemoryMap.h +++ b/kernel/src/memory/MemoryMap.h @@ -7,7 +7,7 @@ struct MemoryMapEntry { MemoryMapEntry() = default; MemoryMapEntry(const MemoryMapEntry& other) = default; - MemoryMapEntry(u64 address, u64 size, bool is_free); + MemoryMapEntry(u64 address, usize size, bool is_free); u64 address() const { @@ -19,7 +19,7 @@ struct MemoryMapEntry return (void*)m_address; } - u64 size() const + usize size() const { return m_size; } @@ -33,7 +33,7 @@ struct MemoryMapEntry private: u64 m_address; - u64 m_size; + usize m_size; bool m_is_free; }; From dad95a81601a1f40814ea774861a215c90b2c4cb Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 10:58:59 +0100 Subject: [PATCH 196/407] Map the page bitmap to virtual memory --- kernel/src/memory/MemoryManager.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 8ebe0b98..dffbd6cd 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -99,6 +99,17 @@ namespace MemoryManager init_physical_frame_allocator(); KernelVM::init(); MMU::setup_initial_page_directory(); + + // NOTE: We force these operations to succeed, because if we can't map the frame bitmap to virtual memory + // there's no point in continuing. + auto bitmap_pages = g_frame_bitmap.size_in_bytes() / ARCH_PAGE_SIZE; + + auto virtual_bitmap_base = KernelVM::alloc_several_pages(bitmap_pages).release_value(); + map_frames_at(virtual_bitmap_base, (u64)g_frame_bitmap.location(), bitmap_pages, + MMU::ReadWrite | MMU::NoExecute) + .release_value(); + + g_frame_bitmap.initialize((void*)virtual_bitmap_base, g_frame_bitmap.size_in_bytes()); } void lock_frame(u64 frame) From ee276a3a35ae1ba4181efc6d73ea27dd5f629658 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 11:01:45 +0100 Subject: [PATCH 197/407] Add the nodiscard attribute to make and make_array --- luna/include/luna/Alloc.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/luna/include/luna/Alloc.h b/luna/include/luna/Alloc.h index fc89132f..ba8a0151 100644 --- a/luna/include/luna/Alloc.h +++ b/luna/include/luna/Alloc.h @@ -1,16 +1,14 @@ #pragma once -#include #include -#include -template Result make(Args... args) +template [[nodiscard]] Result make(Args... args) { T* const result = new T(args...); if (!result) return err(ENOMEM); return result; } -template Result make_array(usize count) +template [[nodiscard]] Result make_array(usize count) { T* const result = new T[count]; if (!result) return err(ENOMEM); From a3b69a0cfafc30aac2e70d03d986d198a2e63cac Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 11:13:16 +0100 Subject: [PATCH 198/407] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fccd41f5..2def0b6c 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,12 @@ A simple kernel and userspace for the x86_64 platform, written mostly in C++ and - The default user is named 'selene' and you can log into it with the password 'moon'. ## Setup (broken) -**WARNING**: Setup will fail on this branch, since we do not have the required libc headers yet, and I removed the patches for now. Your best bet to build the toolchain is to switch to the `main` branch, where it will build successfully, and run `tools/setup.sh`. Then switch back to this branch, remove some files created by the `main` branch, and continue development :) +**WARNING**: Setup will fail on this branch, since we do not have the required libc headers yet, and I removed the patches for now. Your best bet to build the toolchain is to switch to the `main` branch, where it will build successfully, and run `tools/setup.sh`. Then switch back to this branch, run `git clean -fd`, and continue development :) Alternatively, you can also download prebuilt toolchains for x86_64/arm64 Linux hosts from [here](https://pub.cloudapio.eu/luna). Then run `tar xf toolchain-linux-ARCH.tar.gz -C /path/to/luna`. +**ORIGINAL INSTRUCTIONS** + To build and run Luna, you will need to build a [GCC Cross-Compiler](https://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler) and cross-binutils for `x86_64-luna`. (Yes, Luna is advanced enough that it can use its own [OS-Specific Toolchain](https://wiki.osdev.org/OS_Specific_Toolchain), instead of a bare metal target like `x86_64-elf`. It is the first of my OS projects to be able to do so. The patches for Binutils and GCC are [binutils.patch](tools/binutils.patch) and [gcc.patch](tools/gcc.patch)). You should start by installing the [required dependencies](https://wiki.osdev.org/GCC_Cross_Compiler#Installing_Dependencies). From c2927de1913f2bdfa6ccc079e92739fba270abec Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 11:22:34 +0100 Subject: [PATCH 199/407] Remove unused includes --- kernel/src/main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 2056716f..dd05b26f 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,13 +1,9 @@ #include "Log.h" #include "arch/CPU.h" -#include "arch/MMU.h" -#include "arch/Serial.h" #include "arch/Timer.h" #include "boot/Init.h" #include "config.h" -#include "memory/Heap.h" #include "memory/MemoryManager.h" -#include "video/TextConsole.h" #include Result init() From 1badc40a4ae6df82109096af9b846d2290682e04 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 11:40:02 +0100 Subject: [PATCH 200/407] Run include-what-you-use everywhere --- kernel/src/arch/Serial.cpp | 3 ++- kernel/src/arch/x86_64/CPU.cpp | 4 +++- kernel/src/arch/x86_64/CPU.h | 1 - kernel/src/arch/x86_64/MMU.cpp | 1 + kernel/src/boot/Init.cpp | 2 +- kernel/src/main.cpp | 1 + kernel/src/memory/MemoryMap.cpp | 2 ++ kernel/src/video/TextConsole.cpp | 2 ++ luna/src/Format.cpp | 3 +++ luna/src/Units.cpp | 3 ++- 10 files changed, 17 insertions(+), 5 deletions(-) diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index 2282d157..1f0d59ea 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -1,6 +1,7 @@ #include "arch/Serial.h" -#include "arch/CPU.h" +#include #include +#include namespace Serial { diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index fa1b86b8..e3ef18a2 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -1,12 +1,14 @@ +#include "arch/CPU.h" #include "arch/x86_64/CPU.h" #include "Log.h" -#include "arch/Serial.h" #include "arch/Timer.h" #include "arch/x86_64/IO.h" #include #include #include #include +#include +#include extern "C" void enable_sse(); extern "C" void enable_write_protect(); diff --git a/kernel/src/arch/x86_64/CPU.h b/kernel/src/arch/x86_64/CPU.h index a4e8d52f..9e81fd41 100644 --- a/kernel/src/arch/x86_64/CPU.h +++ b/kernel/src/arch/x86_64/CPU.h @@ -1,4 +1,3 @@ -#include "arch/CPU.h" #include struct Registers // Saved CPU registers for x86-64 diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index d4088c1f..7d76da52 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -2,6 +2,7 @@ #include "memory/MemoryManager.h" #include #include +#include #pragma GCC push_options #pragma GCC diagnostic ignored "-Wconversion" diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 11537b84..870d385e 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -1,11 +1,11 @@ #include "boot/Init.h" #include "Log.h" #include "arch/CPU.h" -#include "arch/Serial.h" #include "boot/bootboot.h" #include "memory/MemoryManager.h" #include "video/Framebuffer.h" #include +#include extern const BOOTBOOT bootboot; diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index dd05b26f..6bc1c5b6 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,6 +5,7 @@ #include "config.h" #include "memory/MemoryManager.h" #include +#include Result init() { diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index 4aa24521..f4917633 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -1,4 +1,6 @@ #include "memory/MemoryMap.h" +#include +#include extern const BOOTBOOT bootboot; diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index b49588bf..80565daf 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -3,6 +3,8 @@ #include "video/Framebuffer.h" #include #include +#include +#include extern const BOOTBOOT bootboot; diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index 0080475c..6547a7d0 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include extern "C" usize strlen(const char*); diff --git a/luna/src/Units.cpp b/luna/src/Units.cpp index fa2a0e1b..d0362a75 100644 --- a/luna/src/Units.cpp +++ b/luna/src/Units.cpp @@ -1,7 +1,8 @@ #include #include +#include -Result to_dynamic_unit(usize value, char* buffer, size_t max) +Result to_dynamic_unit(usize value, char* buffer, usize max) { if (value < 1024) { return string_format(buffer, max, "%u bytes", value); } From beab3454b5e741cbd5b7ac7f5d5ab2ebc85efaef Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 11:47:46 +0100 Subject: [PATCH 201/407] kernel: Enable -Wsign-conversion and -Wcast-align --- luna/CMakeLists.txt | 2 +- luna/include/luna/Bitmap.h | 2 +- luna/src/Bitmap.cpp | 10 +++++----- luna/src/Format.cpp | 10 +++++----- luna/src/NumberParsing.cpp | 2 +- luna/src/String.cpp | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 8cb8b56b..b8e43f9e 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -17,7 +17,7 @@ set(SOURCES add_library(luna-freestanding ${FREESTANDING_SOURCES}) target_compile_definitions(luna-freestanding PRIVATE USE_FREESTANDING) target_compile_options(luna-freestanding PRIVATE -Wall -Wextra -Werror -Wvla) -target_compile_options(luna-freestanding PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) +target_compile_options(luna-freestanding PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self -Wcast-align -Wsign-conversion) target_compile_options(luna-freestanding PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) target_compile_options(luna-freestanding PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) target_compile_options(luna-freestanding PRIVATE -fno-rtti -ffreestanding -fno-exceptions) diff --git a/luna/include/luna/Bitmap.h b/luna/include/luna/Bitmap.h index b7464e14..b8ab0c40 100644 --- a/luna/include/luna/Bitmap.h +++ b/luna/include/luna/Bitmap.h @@ -43,6 +43,6 @@ class Bitmap return b ? 0xff : 0; } - char* m_location = nullptr; + u8* m_location = nullptr; usize m_size_in_bytes = 0; }; \ No newline at end of file diff --git a/luna/src/Bitmap.cpp b/luna/src/Bitmap.cpp index 05566e3b..1928208e 100644 --- a/luna/src/Bitmap.cpp +++ b/luna/src/Bitmap.cpp @@ -6,13 +6,13 @@ Bitmap::Bitmap() { } -Bitmap::Bitmap(void* location, usize size_in_bytes) : m_location((char*)location), m_size_in_bytes(size_in_bytes) +Bitmap::Bitmap(void* location, usize size_in_bytes) : m_location((u8*)location), m_size_in_bytes(size_in_bytes) { } void Bitmap::initialize(void* location, usize size_in_bytes) { - m_location = (char*)location; + m_location = (u8*)location; m_size_in_bytes = size_in_bytes; } @@ -26,7 +26,7 @@ void* Bitmap::move(void* new_location, usize new_location_size_in_bytes) void* old_location = (void*)m_location; - m_location = (char*)new_location; + m_location = (u8*)new_location; m_size_in_bytes = new_location_size_in_bytes; return old_location; @@ -37,7 +37,7 @@ void Bitmap::set(usize index, bool value) expect(initialized(), "Bitmap was never initialized"); expect(index < size(), "Bitmap access out of range"); u64 byte_index = index / 8; - u8 bit_mask = 0b10000000 >> (index % 8); + u8 bit_mask = (u8)(0b10000000 >> (index % 8)); m_location[byte_index] &= (u8)(~bit_mask); if (value) { m_location[byte_index] |= bit_mask; } } @@ -47,7 +47,7 @@ bool Bitmap::get(usize index) const expect(initialized(), "Bitmap was never initialized"); expect(index < size(), "Bitmap access out of range"); usize byte_index = index / 8; - usize bit_mask = 0b10000000 >> (index % 8); + u8 bit_mask = (u8)(0b10000000 >> (index % 8)); return (m_location[byte_index] & bit_mask) > 0; } diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index 6547a7d0..5bb9cb1e 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -290,7 +290,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, v, negative); + return output_integer(specifier, vstate, state, (unsigned char)v, negative); } else { @@ -308,7 +308,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, v, negative); + return output_integer(specifier, vstate, state, (unsigned short)v, negative); } else { @@ -326,7 +326,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, v, negative); + return output_integer(specifier, vstate, state, (unsigned long long)v, negative); } else { @@ -344,7 +344,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, v, negative); + return output_integer(specifier, vstate, state, (unsigned long)v, negative); } else { @@ -362,7 +362,7 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, v, negative); + return output_integer(specifier, vstate, state, (unsigned int)v, negative); } else { diff --git a/luna/src/NumberParsing.cpp b/luna/src/NumberParsing.cpp index 0790ad9f..dd3d6df7 100644 --- a/luna/src/NumberParsing.cpp +++ b/luna/src/NumberParsing.cpp @@ -38,7 +38,7 @@ usize _strtou(const char* str, const char** endptr, int base) while (is_valid_digit_for_base(base, *str)) { - val = (base * val) + parse_digit_unchecked(*str); + val = ((usize)base * val) + (usize)parse_digit_unchecked(*str); str++; } diff --git a/luna/src/String.cpp b/luna/src/String.cpp index bd174d93..85535188 100644 --- a/luna/src/String.cpp +++ b/luna/src/String.cpp @@ -31,7 +31,7 @@ extern "C" { if (dest == src) return dest; if (dest > src) - for (long i = n - 1; i >= 0; i++) { *((u8*)dest + i) = *((const u8*)src + i); } + for (long i = (long)n - 1; i >= 0; i++) { *((u8*)dest + i) = *((const u8*)src + i); } else for (long i = 0; i < (long)n; i++) { *((u8*)dest + i) = *((const u8*)src + i); } return dest; @@ -42,6 +42,6 @@ extern "C" const char* i = str; for (; *i; ++i) ; - return (i - str); + return (usize)(i - str); } } \ No newline at end of file From 986aa019482d005779002b27f70229937088967d Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 17:06:29 +0100 Subject: [PATCH 202/407] size_t -> usize --- luna/include/luna/Format.h | 4 ++-- luna/src/Format.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/luna/include/luna/Format.h b/luna/include/luna/Format.h index 245979a7..e1cccc3c 100644 --- a/luna/include/luna/Format.h +++ b/luna/include/luna/Format.h @@ -6,5 +6,5 @@ typedef Result (*callback_t)(char, void*); Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); -Result vstring_format(char* buf, size_t max, const char* format, va_list ap); -Result string_format(char* buf, size_t max, const char* format, ...); \ No newline at end of file +Result vstring_format(char* buf, usize max, const char* format, va_list ap); +Result string_format(char* buf, usize max, const char* format, ...); \ No newline at end of file diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index 5bb9cb1e..ccdde3ab 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -475,10 +475,10 @@ Result cstyle_format(const char* format, callback_t callback, void* arg, struct StringFormatInfo { char* buffer; - size_t remaining; + usize remaining; }; -Result vstring_format(char* buf, size_t max, const char* format, va_list ap) +Result vstring_format(char* buf, usize max, const char* format, va_list ap) { StringFormatInfo info = {.buffer = buf, .remaining = max - 1}; @@ -499,7 +499,7 @@ Result vstring_format(char* buf, size_t max, const char* format, va_list return result; } -Result string_format(char* buf, size_t max, const char* format, ...) +Result string_format(char* buf, usize max, const char* format, ...) { va_list ap; va_start(ap, format); From bbfaa4645a5f9e3afae29998d816e06390eeb3ef Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 12:15:30 +0100 Subject: [PATCH 203/407] Add a should_invoke_scheduler method --- kernel/src/arch/Timer.cpp | 5 +++++ kernel/src/arch/Timer.h | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 35599f2c..42667e1c 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -126,4 +126,9 @@ namespace Timer boot_timestamp = bootloader_time_to_unix(bootboot.datetime); arch_init(); } +} + +bool should_invoke_scheduler() +{ + return (timer_ticks % ARCH_TIMER_FREQ) == 0; } \ No newline at end of file diff --git a/kernel/src/arch/Timer.h b/kernel/src/arch/Timer.h index c540631b..2cd462d1 100644 --- a/kernel/src/arch/Timer.h +++ b/kernel/src/arch/Timer.h @@ -34,4 +34,6 @@ namespace Timer void arch_init(); void init(); -} \ No newline at end of file +} + +bool should_invoke_scheduler(); \ No newline at end of file From 287c4ab060578e2d33a45ae2365af9348181766d Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 12:25:42 +0100 Subject: [PATCH 204/407] Run clang-format --- kernel/src/arch/Serial.cpp | 2 +- kernel/src/arch/x86_64/MMU.cpp | 2 +- kernel/src/boot/Init.cpp | 2 +- kernel/src/main.cpp | 2 +- kernel/src/video/TextConsole.cpp | 2 +- luna/src/Format.cpp | 2 +- luna/src/Units.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index 1f0d59ea..7e6f5f98 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -1,6 +1,6 @@ #include "arch/Serial.h" -#include #include +#include #include namespace Serial diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 7d76da52..25edd6ff 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -1,8 +1,8 @@ #include "arch/MMU.h" #include "memory/MemoryManager.h" +#include #include #include -#include #pragma GCC push_options #pragma GCC diagnostic ignored "-Wconversion" diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 870d385e..64605a5b 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -4,8 +4,8 @@ #include "boot/bootboot.h" #include "memory/MemoryManager.h" #include "video/Framebuffer.h" -#include #include +#include extern const BOOTBOOT bootboot; diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 6bc1c5b6..33f7410e 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,8 +4,8 @@ #include "boot/Init.h" #include "config.h" #include "memory/MemoryManager.h" -#include #include +#include Result init() { diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index 80565daf..dc5f96a0 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -2,8 +2,8 @@ #include "boot/bootboot.h" #include "video/Framebuffer.h" #include -#include #include +#include #include extern const BOOTBOOT bootboot; diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index ccdde3ab..a74b0a38 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -2,8 +2,8 @@ #include #include #include -#include #include +#include extern "C" usize strlen(const char*); diff --git a/luna/src/Units.cpp b/luna/src/Units.cpp index d0362a75..0b64dd9e 100644 --- a/luna/src/Units.cpp +++ b/luna/src/Units.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include Result to_dynamic_unit(usize value, char* buffer, usize max) { From fd6a74e61c2758c8a775bba207f9c4c7dc1f9e43 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 12:26:09 +0100 Subject: [PATCH 205/407] CPU: Add an idle_loop method --- kernel/src/arch/CPU.h | 2 ++ kernel/src/arch/x86_64/CPU.cpp | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index abf826e3..9d973a3d 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -13,6 +13,8 @@ namespace CPU [[noreturn]] void efficient_halt(); + void idle_loop(); + void switch_kernel_stack(u64 top); void enable_interrupts(); diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index e3ef18a2..8a9346fb 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -1,14 +1,14 @@ #include "arch/CPU.h" -#include "arch/x86_64/CPU.h" #include "Log.h" #include "arch/Timer.h" +#include "arch/x86_64/CPU.h" #include "arch/x86_64/IO.h" #include +#include +#include #include #include #include -#include -#include extern "C" void enable_sse(); extern "C" void enable_write_protect(); @@ -430,6 +430,14 @@ namespace CPU goto loop; // Safeguard: if we ever wake up, start our low-power rest again } + void idle_loop() + { + asm volatile("sti"); + loop: + asm volatile("hlt"); + goto loop; + } + void switch_kernel_stack(u64 top) { task_state_segment.rsp[0] = top; From c657b302c9688d2dfb9667021b426db451ea28c4 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 14:31:40 +0100 Subject: [PATCH 206/407] Timer: add raw_ticks --- kernel/src/arch/Timer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 42667e1c..4ed1b780 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -58,6 +58,11 @@ namespace Timer timer_ticks++; } + usize raw_ticks() + { + return timer_ticks; + } + usize ticks() { return ticks_ms() / 1000; @@ -130,5 +135,6 @@ namespace Timer bool should_invoke_scheduler() { + // FIXME: Modulo is SLOW. We're calling this every tick. return (timer_ticks % ARCH_TIMER_FREQ) == 0; } \ No newline at end of file From 4fdd1d57f5b0979ca97565cf906e0b49992be967 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 14:32:07 +0100 Subject: [PATCH 207/407] Make build-debug.sh also add debug symbols to luna --- luna/CMakeLists.txt | 7 +++++++ tools/build-debug.sh | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index b8e43f9e..a8af5718 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -7,6 +7,7 @@ set(FREESTANDING_SOURCES src/Units.cpp src/SystemError.cpp src/Bitmap.cpp + src/Stack.cpp ) set(SOURCES @@ -41,4 +42,10 @@ target_compile_options(luna-freestanding PRIVATE -mno-red-zone) target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) target_compile_definitions(luna-freestanding PUBLIC ARCH_X86_64) target_compile_definitions(luna PUBLIC ARCH_X86_64) +endif() + +if(LUNA_DEBUG_SYMBOLS) + message(STATUS "Building Luna with debug symbols") + target_compile_options(luna PRIVATE -ggdb) + target_compile_options(luna-freestanding PRIVATE -ggdb) endif() \ No newline at end of file diff --git a/tools/build-debug.sh b/tools/build-debug.sh index 85d83455..0fcb695e 100755 --- a/tools/build-debug.sh +++ b/tools/build-debug.sh @@ -9,7 +9,7 @@ tools/setup.sh tools/full-clean.sh -cmake -S . -B $BUILD_DIR -DMOON_DEBUG_SYMBOLS=ON -G "$CMAKE_GEN" +cmake -S . -B $BUILD_DIR -DMOON_DEBUG_SYMBOLS=ON -DLUNA_DEBUG_SYMBOLS=ON -G "$CMAKE_GEN" cmake --build $BUILD_DIR cmake --install $BUILD_DIR From d3458f2f0f4d49dbd623f33c07f56651e6956215 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 14:32:41 +0100 Subject: [PATCH 208/407] Bitmap: short circuit on 0-byte clears --- luna/src/Bitmap.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/luna/src/Bitmap.cpp b/luna/src/Bitmap.cpp index 1928208e..a29fc947 100644 --- a/luna/src/Bitmap.cpp +++ b/luna/src/Bitmap.cpp @@ -62,6 +62,8 @@ void Bitmap::clear_region(usize start, usize bits, bool value) expect(initialized(), "Bitmap was never initialized"); expect((start + bits) <= size(), "Bitmap clear out of range"); + if (!bits) return; + // Set individual bits while not on a byte boundary. while ((start % 8) && bits--) { From f65ed465c486a3d5f9bb5f885de5c2691cd4b002 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 14:46:11 +0100 Subject: [PATCH 209/407] Bitmap: Fix crash by attempting to memset -1 bits (UINT64_MAX) --- luna/src/Bitmap.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luna/src/Bitmap.cpp b/luna/src/Bitmap.cpp index a29fc947..7fb5302b 100644 --- a/luna/src/Bitmap.cpp +++ b/luna/src/Bitmap.cpp @@ -65,10 +65,11 @@ void Bitmap::clear_region(usize start, usize bits, bool value) if (!bits) return; // Set individual bits while not on a byte boundary. - while ((start % 8) && bits--) + while ((start % 8) && bits) { set(start, value); start++; + bits--; } // Clear out the rest in bytes. From 5d988c088f6c5cedd84659796fb6d856ad0c0b4f Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 14:46:56 +0100 Subject: [PATCH 210/407] Make idle_loop noreturn --- kernel/src/arch/CPU.h | 2 +- kernel/src/arch/x86_64/CPU.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index 9d973a3d..0021fea8 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -13,7 +13,7 @@ namespace CPU [[noreturn]] void efficient_halt(); - void idle_loop(); + [[noreturn]] void idle_loop(); void switch_kernel_stack(u64 top); diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 8a9346fb..40e86dc6 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -430,7 +430,7 @@ namespace CPU goto loop; // Safeguard: if we ever wake up, start our low-power rest again } - void idle_loop() + [[noreturn]] void idle_loop() { asm volatile("sti"); loop: From 0bbd02666075435b316ffefdcd5e5b226d4ed8e7 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 14:48:08 +0100 Subject: [PATCH 211/407] CPU.h: pragma once --- kernel/src/arch/x86_64/CPU.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/src/arch/x86_64/CPU.h b/kernel/src/arch/x86_64/CPU.h index 9e81fd41..a06de7b9 100644 --- a/kernel/src/arch/x86_64/CPU.h +++ b/kernel/src/arch/x86_64/CPU.h @@ -1,3 +1,4 @@ +#pragma once #include struct Registers // Saved CPU registers for x86-64 From 8da55212737b5c7bfb252b76316f20d0578ed6c4 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 14:48:24 +0100 Subject: [PATCH 212/407] Add a Stack convenience class --- luna/include/luna/Stack.h | 23 +++++++++++++++++++++++ luna/src/Stack.cpp | 10 ++++++++++ 2 files changed, 33 insertions(+) create mode 100644 luna/include/luna/Stack.h create mode 100644 luna/src/Stack.cpp diff --git a/luna/include/luna/Stack.h b/luna/include/luna/Stack.h new file mode 100644 index 00000000..7870402c --- /dev/null +++ b/luna/include/luna/Stack.h @@ -0,0 +1,23 @@ +#pragma once +#include + +struct Stack +{ + Stack(u64 base, usize bytes); + + u64 bottom() + { + return m_base; + } + + u64 top(); + + usize bytes() + { + return m_bytes; + } + + private: + u64 m_base; + usize m_bytes; +}; \ No newline at end of file diff --git a/luna/src/Stack.cpp b/luna/src/Stack.cpp new file mode 100644 index 00000000..0c53e6f3 --- /dev/null +++ b/luna/src/Stack.cpp @@ -0,0 +1,10 @@ +#include + +Stack::Stack(u64 base, usize bytes) : m_base(base), m_bytes(bytes) +{ +} + +u64 Stack::top() +{ + return (m_base + m_bytes) - sizeof(void*); +} \ No newline at end of file From fbd290c01b1f84fc730659e01cdace04a3a95392 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 14:48:50 +0100 Subject: [PATCH 213/407] KernelVM: clean up a bit --- kernel/src/memory/KernelVM.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/kernel/src/memory/KernelVM.cpp b/kernel/src/memory/KernelVM.cpp index 0a4a445b..dbb4eb85 100644 --- a/kernel/src/memory/KernelVM.cpp +++ b/kernel/src/memory/KernelVM.cpp @@ -21,6 +21,7 @@ namespace KernelVM void init() { g_kernelvm_bitmap.initialize(bitmap_memory, sizeof(bitmap_memory)); + g_kernelvm_bitmap.clear(false); } Result alloc_one_page() @@ -36,7 +37,7 @@ namespace KernelVM return err(ENOMEM); } - Result alloc_several_pages(usize count) + bool find_several_pages_impl(usize count, u64& start_index) { u64 first_free_index = 0; u64 free_contiguous_pages = 0; @@ -56,12 +57,24 @@ namespace KernelVM // Found enough contiguous free pages!! if (free_contiguous_pages == count) { - g_used_vm += ARCH_PAGE_SIZE * count; - g_kernelvm_bitmap.clear_region(first_free_index, count, true); - return KERNEL_VM_RANGE_START + (first_free_index * ARCH_PAGE_SIZE); + start_index = first_free_index; + return true; } } + return false; + } + + Result alloc_several_pages(const usize count) + { + u64 start_index; + if (find_several_pages_impl(count, start_index)) + { + g_kernelvm_bitmap.clear_region(start_index, count, true); + g_used_vm += ARCH_PAGE_SIZE * count; + return KERNEL_VM_RANGE_START + (start_index * ARCH_PAGE_SIZE); + } + return err(ENOMEM); } From 12aa014a3dcb18ea6ef2d36816e9fbccbfb7d659 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 15:02:46 +0100 Subject: [PATCH 214/407] Add a Thread class which can be part of a DoublyLinkedList --- kernel/src/arch/x86_64/Thread.cpp | 49 +++++++++++++++++++++++++++++++ kernel/src/thread/Thread.cpp | 15 ++++++++++ kernel/src/thread/Thread.h | 46 +++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 kernel/src/arch/x86_64/Thread.cpp create mode 100644 kernel/src/thread/Thread.cpp create mode 100644 kernel/src/thread/Thread.h diff --git a/kernel/src/arch/x86_64/Thread.cpp b/kernel/src/arch/x86_64/Thread.cpp new file mode 100644 index 00000000..1abd34a0 --- /dev/null +++ b/kernel/src/arch/x86_64/Thread.cpp @@ -0,0 +1,49 @@ +#include "thread/Thread.h" +#include + +bool is_in_kernel(Registers* regs) +{ + return regs->cs == 8; +} + +void Thread::set_ip(u64 ip) +{ + regs.rip = ip; +} + +u64 Thread::ip() +{ + return regs.rip; +} + +void Thread::set_sp(u64 sp) +{ + regs.rsp = sp; +} + +u64 Thread::sp() +{ + return regs.rsp; +} + +void Thread::init_regs_kernel() +{ + memset(®s, 0, sizeof(Registers)); + regs.cs = 0x08; + regs.ss = 0x10; +} + +void Thread::set_arguments(u64 arg1, u64 arg2, u64 arg3, u64 arg4) +{ + regs.rdi = arg1; + regs.rsi = arg2; + regs.rdx = arg3; + regs.rcx = arg4; +} + +void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs) +{ + if (!old_thread->is_idle) memcpy(&old_thread->regs, regs, sizeof(Registers)); + + memcpy(regs, &new_thread->regs, sizeof(Registers)); +} \ No newline at end of file diff --git a/kernel/src/thread/Thread.cpp b/kernel/src/thread/Thread.cpp new file mode 100644 index 00000000..5f834d6e --- /dev/null +++ b/kernel/src/thread/Thread.cpp @@ -0,0 +1,15 @@ +#include "thread/Thread.h" +#include + +static u64 g_next_id = 1; + +DoublyLinkedList g_threads; + +Result new_thread() +{ + Thread* thread = TRY(make()); + + thread->id = g_next_id++; + + return thread; +} \ No newline at end of file diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h new file mode 100644 index 00000000..3b3b7a39 --- /dev/null +++ b/kernel/src/thread/Thread.h @@ -0,0 +1,46 @@ +#pragma once + +#include "arch/CPU.h" +#include +#include + +#ifdef ARCH_X86_64 +#include "arch/x86_64/CPU.h" +#else +#error "Unknown architecture." +#endif + +struct Thread : public DoublyLinkedListNode +{ + Registers regs; + + u64 id; + + u64 ticks = 0; + u64 ticks_in_user = 0; + u64 ticks_in_kernel = 0; + + u64 ticks_left; + + bool is_idle = false; + + void init_regs_kernel(); + void init_regs_user(); + + void set_arguments(u64 arg1, u64 arg2, u64 arg3, u64 arg4); + + void set_ip(u64 ip); + u64 ip(); + + void set_sp(u64 sp); + u64 sp(); +}; + +void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs); + +bool is_in_kernel(Registers* regs); + +Result new_thread(); +Result create_idle_thread(); + +extern DoublyLinkedList g_threads; \ No newline at end of file From 13f5d09cfd5885f986cac25ba03774abed0c83b5 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 15:03:34 +0100 Subject: [PATCH 215/407] Add a Scheduler!! --- kernel/CMakeLists.txt | 3 + kernel/src/thread/Scheduler.cpp | 144 ++++++++++++++++++++++++++++++++ kernel/src/thread/Scheduler.h | 19 +++++ 3 files changed, 166 insertions(+) create mode 100644 kernel/src/thread/Scheduler.cpp create mode 100644 kernel/src/thread/Scheduler.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index e20cca1c..5e8e03c6 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -12,6 +12,8 @@ set(SOURCES src/boot/Init.cpp src/arch/Serial.cpp src/arch/Timer.cpp + src/thread/Thread.cpp + src/thread/Scheduler.cpp ) if("${ARCH}" MATCHES "x86_64") @@ -22,6 +24,7 @@ if("${ARCH}" MATCHES "x86_64") src/arch/x86_64/MMU.cpp src/arch/x86_64/CPU.cpp src/arch/x86_64/Timer.cpp + src/arch/x86_64/Thread.cpp ) endif() diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp new file mode 100644 index 00000000..c4058e24 --- /dev/null +++ b/kernel/src/thread/Scheduler.cpp @@ -0,0 +1,144 @@ +#include "thread/Scheduler.h" +#include "Log.h" +#include "arch/CPU.h" +#include "arch/MMU.h" +#include "memory/KernelVM.h" +#include "memory/MemoryManager.h" +#include + +static Thread g_idle; +static Thread* g_current = nullptr; + +static const usize TICKS_PER_TIMESLICE = 20; + +namespace Scheduler +{ + void init() + { + g_idle.id = 0; + g_idle.init_regs_kernel(); + g_idle.set_ip((u64)CPU::idle_loop); + g_idle.is_idle = true; + + g_idle.ticks_left = 1; + + // Map some stack for the idle task + u64 idle_stack_vm = KernelVM::alloc_one_page().release_value(); + MemoryManager::alloc_at(idle_stack_vm, 1, MMU::NoExecute | MMU::ReadWrite).release_value(); + + Stack idle_stack{idle_stack_vm, ARCH_PAGE_SIZE}; + g_idle.set_sp(idle_stack.top()); + + kinfoln("CREATED IDLE THREAD: id %lu with ip %lx and sp %lx", g_idle.id, g_idle.ip(), g_idle.sp()); + + g_current = &g_idle; + } + + Thread* current() + { + return g_current; + } + + Result kernel_thread_alloc_stack_and_append_impl(Thread* thread) + { + // FIXME: We will leak the thread if VM allocation or alloc_at fail. + u64 thread_stack_vm = TRY(KernelVM::alloc_several_pages(4)); + TRY(MemoryManager::alloc_at(thread_stack_vm, 4, MMU::NoExecute | MMU::ReadWrite)); + + Stack thread_stack{thread_stack_vm, ARCH_PAGE_SIZE * 4}; + thread->set_sp(thread_stack.top()); + + g_threads.append(thread); + + kinfoln("CREATED THREAD: id %lu with ip %lx and sp %lx", thread->id, thread->ip(), thread->sp()); + + return {}; + } + + Result new_kernel_thread(u64 address) + { + Thread* thread = TRY(new_thread()); + thread->init_regs_kernel(); + thread->set_ip(address); + + return kernel_thread_alloc_stack_and_append_impl(thread); + } + + Result new_kernel_thread(void (*func)(void)) + { + Thread* thread = TRY(new_thread()); + thread->init_regs_kernel(); + thread->set_ip((u64)func); + + return kernel_thread_alloc_stack_and_append_impl(thread); + } + + Result new_kernel_thread(void (*func)(void*), void* arg) + { + Thread* thread = TRY(new_thread()); + thread->init_regs_kernel(); + thread->set_ip((u64)func); + thread->set_arguments((u64)arg, 0, 0, 0); + + return kernel_thread_alloc_stack_and_append_impl(thread); + } + + Thread* pick_task() + { + Thread* old = g_current; + if (old->is_idle) + { + auto maybe_first = g_threads.last(); + if (maybe_first.has_error()) // No threads!! + return &g_idle; + g_current = old = maybe_first.value(); + } + + do { + auto maybe_next = g_threads.next(g_current); + if (maybe_next.has_error()) g_current = g_threads.first().value(); + else + g_current = maybe_next.value(); + + if (true) // FIXME: Check if the current task is runnable. + break; + } while (g_current != old); + + return g_current; + } + + void generic_switch_context(Thread* old_thread, Thread* new_thread, Registers* regs) + { + if (old_thread != new_thread) switch_context(old_thread, new_thread, regs); + + if (new_thread->is_idle) + { + new_thread->ticks_left = 1; // The idle task only runs for 1 tick so we can check for new runnable tasks + // as fast as possible. + } + else + new_thread->ticks_left = TICKS_PER_TIMESLICE; + } + + void switch_task(Registers* regs) + { + Thread* old_thread = g_current; + Thread* new_thread = pick_task(); + generic_switch_context(old_thread, new_thread, regs); + } + + void invoke(Registers* regs) + { + CPU::disable_interrupts(); + + g_current->ticks++; + + if (is_in_kernel(regs)) g_current->ticks_in_kernel++; + else + g_current->ticks_in_user++; + + g_current->ticks_left--; + + if (!g_current->ticks_left) switch_task(regs); + } +} \ No newline at end of file diff --git a/kernel/src/thread/Scheduler.h b/kernel/src/thread/Scheduler.h new file mode 100644 index 00000000..95b12451 --- /dev/null +++ b/kernel/src/thread/Scheduler.h @@ -0,0 +1,19 @@ +#pragma once +#include "thread/Thread.h" + +namespace Scheduler +{ + void init(); + + Thread* current(); + + Result new_kernel_thread(u64 address); + Result new_kernel_thread(void (*func)(void)); + Result new_kernel_thread(void (*func)(void*), void* arg); + + Thread* pick_task(); + + void switch_task(Registers* regs); + + void invoke(Registers* regs); +} \ No newline at end of file From c907e163114735e9d18c24b0287e5a6d4deda598 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 15:04:02 +0100 Subject: [PATCH 216/407] x86_64: Invoke the scheduler every millisecond --- kernel/src/arch/x86_64/CPU.asm | 7 +------ kernel/src/arch/x86_64/CPU.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 59f4d68a..f3e2d2fc 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -48,12 +48,7 @@ load_tr: ltr ax ret -global switch_task -switch_task: - cli -.loop: - hlt - jmp .loop +extern switch_task global kernel_yield kernel_yield: diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 40e86dc6..6a9f8600 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -3,6 +3,7 @@ #include "arch/Timer.h" #include "arch/x86_64/CPU.h" #include "arch/x86_64/IO.h" +#include "thread/Scheduler.h" #include #include #include @@ -336,6 +337,7 @@ extern "C" void arch_interrupt_entry(Registers* regs) else if (regs->isr == 32) { Timer::tick(); + if (should_invoke_scheduler()) Scheduler::invoke(regs); pic_eoi(regs); } else @@ -442,4 +444,10 @@ namespace CPU { task_state_segment.rsp[0] = top; } +} + +// called by kernel_yield +extern "C" void switch_task(Registers* regs) +{ + Scheduler::switch_task(regs); } \ No newline at end of file From f169718a4b550356a30a7d3a97b74238da55c96c Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 15:04:11 +0100 Subject: [PATCH 217/407] Initialize and demo the scheduler --- kernel/src/main.cpp | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 33f7410e..7016296d 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,12 +1,35 @@ #include "Log.h" #include "arch/CPU.h" +#include "arch/Serial.h" #include "arch/Timer.h" #include "boot/Init.h" #include "config.h" #include "memory/MemoryManager.h" +#include "thread/Scheduler.h" #include #include +void print_in_loop() +{ + while (true) + { + CPU::disable_interrupts(); + Serial::printf("%lu", Scheduler::current()->id); + CPU::enable_interrupts(); + } +} + +void print_one_and_then_yield() +{ + while (true) + { + CPU::disable_interrupts(); + Serial::printf("%lu", Scheduler::current()->id); + kernel_yield(); + CPU::enable_interrupts(); + } +} + Result init() { kinfoln("Starting Moon %s", MOON_VERSION); @@ -17,10 +40,6 @@ Result init() Timer::init(); - CPU::platform_finish_init(); - - CPU::enable_interrupts(); - char buffer[64]; to_dynamic_unit(MemoryManager::total(), buffer, sizeof(buffer)); kinfoln("Total memory: %s", buffer); @@ -31,6 +50,20 @@ Result init() to_dynamic_unit(MemoryManager::reserved(), buffer, sizeof(buffer)); kinfoln("Reserved memory: %s", buffer); + Scheduler::init(); + + TRY(Scheduler::new_kernel_thread(print_in_loop)); + TRY(Scheduler::new_kernel_thread(print_in_loop)); + TRY(Scheduler::new_kernel_thread(print_in_loop)); + TRY(Scheduler::new_kernel_thread(print_in_loop)); + TRY(Scheduler::new_kernel_thread(print_in_loop)); + TRY(Scheduler::new_kernel_thread(print_in_loop)); + TRY(Scheduler::new_kernel_thread(print_one_and_then_yield)); + + CPU::platform_finish_init(); + + CPU::enable_interrupts(); + return {}; } @@ -40,5 +73,5 @@ extern "C" [[noreturn]] void _start() Init::early_init(); auto rc = init(); if (rc.has_error()) kerrorln("Runtime error: %s", rc.error_string()); - CPU::efficient_halt(); + CPU::idle_loop(); } \ No newline at end of file From 57517252d846c567e1daa036b4eb039a655ab132 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 15:14:58 +0100 Subject: [PATCH 218/407] Add a state to Thread --- kernel/src/arch/x86_64/Thread.cpp | 2 +- kernel/src/thread/Scheduler.cpp | 6 +++--- kernel/src/thread/Thread.h | 14 +++++++++++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/kernel/src/arch/x86_64/Thread.cpp b/kernel/src/arch/x86_64/Thread.cpp index 1abd34a0..7eb3160e 100644 --- a/kernel/src/arch/x86_64/Thread.cpp +++ b/kernel/src/arch/x86_64/Thread.cpp @@ -43,7 +43,7 @@ void Thread::set_arguments(u64 arg1, u64 arg2, u64 arg3, u64 arg4) void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs) { - if (!old_thread->is_idle) memcpy(&old_thread->regs, regs, sizeof(Registers)); + if (!old_thread->is_idle()) memcpy(&old_thread->regs, regs, sizeof(Registers)); memcpy(regs, &new_thread->regs, sizeof(Registers)); } \ No newline at end of file diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index c4058e24..04dd4e1f 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -18,7 +18,7 @@ namespace Scheduler g_idle.id = 0; g_idle.init_regs_kernel(); g_idle.set_ip((u64)CPU::idle_loop); - g_idle.is_idle = true; + g_idle.state = ThreadState::Idle; g_idle.ticks_left = 1; @@ -86,7 +86,7 @@ namespace Scheduler Thread* pick_task() { Thread* old = g_current; - if (old->is_idle) + if (old->is_idle()) { auto maybe_first = g_threads.last(); if (maybe_first.has_error()) // No threads!! @@ -111,7 +111,7 @@ namespace Scheduler { if (old_thread != new_thread) switch_context(old_thread, new_thread, regs); - if (new_thread->is_idle) + if (new_thread->is_idle()) { new_thread->ticks_left = 1; // The idle task only runs for 1 tick so we can check for new runnable tasks // as fast as possible. diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 3b3b7a39..d63e58c4 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -10,6 +10,13 @@ #error "Unknown architecture." #endif +enum class ThreadState +{ + Idle, + Runnable, + Sleeping +}; + struct Thread : public DoublyLinkedListNode { Registers regs; @@ -22,7 +29,12 @@ struct Thread : public DoublyLinkedListNode u64 ticks_left; - bool is_idle = false; + ThreadState state = ThreadState::Runnable; + + bool is_idle() + { + return state == ThreadState::Idle; + } void init_regs_kernel(); void init_regs_user(); From 70497c37fb3adb2005de04af5b1d60dd58c4f628 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 15:17:20 +0100 Subject: [PATCH 219/407] Check for runnable threads --- kernel/src/thread/Scheduler.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 04dd4e1f..c925d356 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -88,22 +88,29 @@ namespace Scheduler Thread* old = g_current; if (old->is_idle()) { - auto maybe_first = g_threads.last(); - if (maybe_first.has_error()) // No threads!! + auto maybe_last = g_threads.last(); + if (maybe_last.has_error()) // No threads!! return &g_idle; - g_current = old = maybe_first.value(); + g_current = old = maybe_last.value(); } + bool has_found_thread = false; + do { auto maybe_next = g_threads.next(g_current); if (maybe_next.has_error()) g_current = g_threads.first().value(); else g_current = maybe_next.value(); - if (true) // FIXME: Check if the current task is runnable. + if (g_current->state == ThreadState::Runnable) + { + has_found_thread = true; break; + } } while (g_current != old); + if (!has_found_thread) g_current = &g_idle; + return g_current; } From 757cee46934d5b50e769f0093e45bbcc25f3e4ce Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 15:21:50 +0100 Subject: [PATCH 220/407] Add accessors for when you're sure a linked list is not empty --- kernel/src/memory/Heap.cpp | 4 ++-- kernel/src/thread/Scheduler.cpp | 2 +- luna/include/luna/LinkedList.h | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index ad16eebe..e7dba4f2 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -178,7 +178,7 @@ Result kmalloc(usize size) heap.append(block); } - HeapBlock* block = heap.first().value(); + HeapBlock* block = heap.expect_first(); while (block) { // Trying to find a free block... @@ -330,7 +330,7 @@ void dump_heap_usage() } usize alloc_total = 0; usize alloc_used = 0; - HeapBlock* block = heap.first().value(); + HeapBlock* block = heap.expect_first(); while (block) { if (is_block_free(block)) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index c925d356..9722afac 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -98,7 +98,7 @@ namespace Scheduler do { auto maybe_next = g_threads.next(g_current); - if (maybe_next.has_error()) g_current = g_threads.first().value(); + if (maybe_next.has_error()) g_current = g_threads.expect_first(); else g_current = maybe_next.value(); diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 5e343b3d..698e5a9a 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -106,11 +106,21 @@ template class DoublyLinkedList return nonnull_or_error((T*)m_start_node); } + T* expect_first() + { + return first().value(); + } + Result last() { return nonnull_or_error((T*)m_end_node); } + T* expect_last() + { + return last().value(); + } + Result next(T* item) { return nonnull_or_error((T*)extract_node(item)->get_next()); From d93d95f23c8c65fa049e9f6b59f044dcfb46fd52 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 15:55:58 +0100 Subject: [PATCH 221/407] Add sleeping mechanism --- kernel/src/arch/CPU.h | 4 +--- kernel/src/arch/x86_64/Thread.cpp | 1 + kernel/src/main.cpp | 29 ++++++++--------------------- kernel/src/thread/Scheduler.cpp | 19 +++++++++++++++++++ kernel/src/thread/Scheduler.h | 6 +++++- kernel/src/thread/Thread.h | 1 + 6 files changed, 35 insertions(+), 25 deletions(-) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index 0021fea8..35159630 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -20,6 +20,4 @@ namespace CPU void enable_interrupts(); void disable_interrupts(); void wait_for_interrupt(); -} - -extern "C" void kernel_yield(); \ No newline at end of file +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/Thread.cpp b/kernel/src/arch/x86_64/Thread.cpp index 7eb3160e..4e1ffe86 100644 --- a/kernel/src/arch/x86_64/Thread.cpp +++ b/kernel/src/arch/x86_64/Thread.cpp @@ -31,6 +31,7 @@ void Thread::init_regs_kernel() memset(®s, 0, sizeof(Registers)); regs.cs = 0x08; regs.ss = 0x10; + regs.rflags = 1 << 9; // IF (Interrupt enable flag) } void Thread::set_arguments(u64 arg1, u64 arg2, u64 arg3, u64 arg4) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 7016296d..80c7accc 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -9,24 +9,17 @@ #include #include -void print_in_loop() +void async_thread() { while (true) { - CPU::disable_interrupts(); - Serial::printf("%lu", Scheduler::current()->id); - CPU::enable_interrupts(); - } -} + Thread* current = Scheduler::current(); + kinfoln("Ticks: %lu, %lu user, %lu kernel, %lu idle", current->ticks, current->ticks_in_user, + current->ticks_in_kernel, Scheduler::idle()->ticks); -void print_one_and_then_yield() -{ - while (true) - { - CPU::disable_interrupts(); - Serial::printf("%lu", Scheduler::current()->id); - kernel_yield(); - CPU::enable_interrupts(); + CPU::wait_for_interrupt(); + + kernel_sleep(1000); } } @@ -52,13 +45,7 @@ Result init() Scheduler::init(); - TRY(Scheduler::new_kernel_thread(print_in_loop)); - TRY(Scheduler::new_kernel_thread(print_in_loop)); - TRY(Scheduler::new_kernel_thread(print_in_loop)); - TRY(Scheduler::new_kernel_thread(print_in_loop)); - TRY(Scheduler::new_kernel_thread(print_in_loop)); - TRY(Scheduler::new_kernel_thread(print_in_loop)); - TRY(Scheduler::new_kernel_thread(print_one_and_then_yield)); + TRY(Scheduler::new_kernel_thread(async_thread)); CPU::platform_finish_init(); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 9722afac..c6b7fe90 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -39,6 +39,11 @@ namespace Scheduler return g_current; } + Thread* idle() + { + return &g_idle; + } + Result kernel_thread_alloc_stack_and_append_impl(Thread* thread) { // FIXME: We will leak the thread if VM allocation or alloc_at fail. @@ -146,6 +151,20 @@ namespace Scheduler g_current->ticks_left--; + g_threads.for_each([](Thread* thread) { + if (thread->state == ThreadState::Sleeping) + { + if (--thread->sleep_ticks_left == 0) thread->state = ThreadState::Runnable; + } + }); + if (!g_current->ticks_left) switch_task(regs); } +} + +void kernel_sleep(u64 ms) +{ + g_current->sleep_ticks_left = ms; + g_current->state = ThreadState::Sleeping; + kernel_yield(); } \ No newline at end of file diff --git a/kernel/src/thread/Scheduler.h b/kernel/src/thread/Scheduler.h index 95b12451..57bb85ad 100644 --- a/kernel/src/thread/Scheduler.h +++ b/kernel/src/thread/Scheduler.h @@ -6,6 +6,7 @@ namespace Scheduler void init(); Thread* current(); + Thread* idle(); Result new_kernel_thread(u64 address); Result new_kernel_thread(void (*func)(void)); @@ -16,4 +17,7 @@ namespace Scheduler void switch_task(Registers* regs); void invoke(Registers* regs); -} \ No newline at end of file +} + +extern "C" void kernel_yield(); +void kernel_sleep(u64 ms); \ No newline at end of file diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index d63e58c4..53e41a21 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -28,6 +28,7 @@ struct Thread : public DoublyLinkedListNode u64 ticks_in_kernel = 0; u64 ticks_left; + u64 sleep_ticks_left; ThreadState state = ThreadState::Runnable; From 0d437cfcca4f117d27e78fb2873b02b869a08442 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 17:39:59 +0100 Subject: [PATCH 222/407] Add support for stack traces --- kernel/src/arch/CPU.h | 3 +++ kernel/src/arch/x86_64/CPU.cpp | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index 35159630..ac05ed6a 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -20,4 +20,7 @@ namespace CPU void enable_interrupts(); void disable_interrupts(); void wait_for_interrupt(); + + void get_stack_trace(void (*callback)(u64, void*), void* arg); + void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg); } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 6a9f8600..8d8476c9 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -3,6 +3,7 @@ #include "arch/Timer.h" #include "arch/x86_64/CPU.h" #include "arch/x86_64/IO.h" +#include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include #include @@ -301,6 +302,17 @@ static void setup_idt() u64 cr2; asm volatile("mov %%cr2, %0" : "=r"(cr2)); kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2); + + int frame_index = 0; + CPU::get_stack_trace_at( + regs, + [](u64 instruction, void* arg) { + int* ptr = (int*)arg; + kinfoln("#%d at %p", *ptr, (void*)instruction); + (*ptr)++; + }, + &frame_index); + CPU::efficient_halt(); } @@ -444,6 +456,37 @@ namespace CPU { task_state_segment.rsp[0] = top; } + + struct StackFrame + { + StackFrame* next; + u64 instruction; + }; + + void get_stack_trace(void (*callback)(u64, void*), void* arg) + { + u64 rbp; + asm volatile("mov %%rbp, %0" : "=r"(rbp)); + StackFrame* current_frame = (StackFrame*)rbp; + // FIXME: Validate that the frame itself is readable, might span across multiple pages + while (current_frame && MemoryManager::validate_readable_page((u64)current_frame)) + { + callback(current_frame->instruction, arg); + current_frame = current_frame->next; + } + } + + void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg) + { + callback(regs->rip, arg); + StackFrame* current_frame = (StackFrame*)regs->rbp; + // FIXME: Validate that the frame itself is readable, might span across multiple pages + while (current_frame && MemoryManager::validate_readable_page((u64)current_frame)) + { + callback(current_frame->instruction, arg); + current_frame = current_frame->next; + } + } } // called by kernel_yield From c8302a4feff7e03136b20ae92facb9412e81c933 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 18:11:24 +0100 Subject: [PATCH 223/407] Add convenience functions to print the stack trace directly --- kernel/src/arch/CPU.h | 2 ++ kernel/src/arch/x86_64/CPU.cpp | 37 +++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index ac05ed6a..edf51cba 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -22,5 +22,7 @@ namespace CPU void wait_for_interrupt(); void get_stack_trace(void (*callback)(u64, void*), void* arg); + void print_stack_trace(); void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg); + void print_stack_trace_at(Registers* regs); } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 8d8476c9..8654fe38 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -303,15 +303,7 @@ static void setup_idt() asm volatile("mov %%cr2, %0" : "=r"(cr2)); kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2); - int frame_index = 0; - CPU::get_stack_trace_at( - regs, - [](u64 instruction, void* arg) { - int* ptr = (int*)arg; - kinfoln("#%d at %p", *ptr, (void*)instruction); - (*ptr)++; - }, - &frame_index); + CPU::print_stack_trace_at(regs); CPU::efficient_halt(); } @@ -476,6 +468,20 @@ namespace CPU } } + void print_stack_trace() + { + u64 rbp; + int frame_index = 0; + asm volatile("mov %%rbp, %0" : "=r"(rbp)); + StackFrame* current_frame = (StackFrame*)rbp; + // FIXME: Validate that the frame itself is readable, might span across multiple pages + while (current_frame && MemoryManager::validate_readable_page((u64)current_frame)) + { + kinfoln("#%d at %p", frame_index++, (void*)current_frame->instruction); + current_frame = current_frame->next; + } + } + void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg) { callback(regs->rip, arg); @@ -487,6 +493,19 @@ namespace CPU current_frame = current_frame->next; } } + + void print_stack_trace_at(Registers* regs) + { + int frame_index = 0; + get_stack_trace_at( + regs, + [](u64 instruction, void* arg) { + int* ptr = (int*)arg; + kinfoln("#%d at %p", *ptr, (void*)instruction); + (*ptr)++; + }, + &frame_index); + } } // called by kernel_yield From 6de7753b4c66c42c0b759541ce22892ee643157d Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 18:17:49 +0100 Subject: [PATCH 224/407] Add malloc wrappers --- luna/CMakeLists.txt | 21 +++++++++++---------- luna/include/luna/Alloc.h | 3 +++ luna/src/Alloc.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 luna/src/Alloc.cpp diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index a8af5718..286619d6 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -8,6 +8,7 @@ set(FREESTANDING_SOURCES src/SystemError.cpp src/Bitmap.cpp src/Stack.cpp + src/Alloc.cpp ) set(SOURCES @@ -28,24 +29,24 @@ target_compile_options(luna-freestanding PRIVATE -nostdlib -mcmodel=kernel) target_include_directories(luna-freestanding PUBLIC include/) set_target_properties(luna-freestanding PROPERTIES CXX_STANDARD 20) -add_library(luna ${SOURCES}) -target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) -target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) -target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) -target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) -target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) -target_include_directories(luna PUBLIC include/) -set_target_properties(luna PROPERTIES CXX_STANDARD 20) +#add_library(luna ${SOURCES}) +#target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) +#target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) +#target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) +#target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) +#target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) +#target_include_directories(luna PUBLIC include/) +#set_target_properties(luna PROPERTIES CXX_STANDARD 20) if("${ARCH}" MATCHES "x86_64") target_compile_options(luna-freestanding PRIVATE -mno-red-zone) target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) target_compile_definitions(luna-freestanding PUBLIC ARCH_X86_64) -target_compile_definitions(luna PUBLIC ARCH_X86_64) +#target_compile_definitions(luna PUBLIC ARCH_X86_64) endif() if(LUNA_DEBUG_SYMBOLS) message(STATUS "Building Luna with debug symbols") - target_compile_options(luna PRIVATE -ggdb) + #target_compile_options(luna PRIVATE -ggdb) target_compile_options(luna-freestanding PRIVATE -ggdb) endif() \ No newline at end of file diff --git a/luna/include/luna/Alloc.h b/luna/include/luna/Alloc.h index ba8a0151..d76b7442 100644 --- a/luna/include/luna/Alloc.h +++ b/luna/include/luna/Alloc.h @@ -1,6 +1,9 @@ #pragma once #include +[[nodiscard]] void* raw_malloc(usize); +void raw_free(void*); + template [[nodiscard]] Result make(Args... args) { T* const result = new T(args...); diff --git a/luna/src/Alloc.cpp b/luna/src/Alloc.cpp new file mode 100644 index 00000000..105f4ac9 --- /dev/null +++ b/luna/src/Alloc.cpp @@ -0,0 +1,25 @@ +#include + +#ifndef USE_FREESTANDING +#include +#endif + +[[nodiscard]] void* raw_malloc(usize size) +{ +#ifdef USE_FREESTANDING + char* const rc = new char[size]; + return (void*)rc; +#else + return malloc(size); +#endif +} + +void raw_free(void* ptr) +{ +#ifdef USE_FREESTANDING + char* const arr = (char*)ptr; + delete[] arr; +#else + return free(ptr); +#endif +} \ No newline at end of file From 1d5d1daa575410d80ebfeb77b44f42e327fcc84b Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 8 Dec 2022 14:56:11 +0100 Subject: [PATCH 225/407] Add scope guards --- kernel/src/thread/Scheduler.cpp | 18 +++++++++++++----- luna/include/luna/ScopeGuard.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 luna/include/luna/ScopeGuard.h diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index c6b7fe90..a6b91f90 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -4,6 +4,7 @@ #include "arch/MMU.h" #include "memory/KernelVM.h" #include "memory/MemoryManager.h" +#include #include static Thread g_idle; @@ -44,12 +45,19 @@ namespace Scheduler return &g_idle; } - Result kernel_thread_alloc_stack_and_append_impl(Thread* thread) + Result new_kernel_thread_impl(Thread* thread) { - // FIXME: We will leak the thread if VM allocation or alloc_at fail. + // If anything fails, make sure to clean up. + auto thread_guard = make_scope_guard([&] { delete thread; }); + u64 thread_stack_vm = TRY(KernelVM::alloc_several_pages(4)); + auto vm_guard = make_scope_guard([&] { KernelVM::free_several_pages(thread_stack_vm, 4); }); + TRY(MemoryManager::alloc_at(thread_stack_vm, 4, MMU::NoExecute | MMU::ReadWrite)); + thread_guard.deactivate(); + vm_guard.deactivate(); + Stack thread_stack{thread_stack_vm, ARCH_PAGE_SIZE * 4}; thread->set_sp(thread_stack.top()); @@ -66,7 +74,7 @@ namespace Scheduler thread->init_regs_kernel(); thread->set_ip(address); - return kernel_thread_alloc_stack_and_append_impl(thread); + return new_kernel_thread_impl(thread); } Result new_kernel_thread(void (*func)(void)) @@ -75,7 +83,7 @@ namespace Scheduler thread->init_regs_kernel(); thread->set_ip((u64)func); - return kernel_thread_alloc_stack_and_append_impl(thread); + return new_kernel_thread_impl(thread); } Result new_kernel_thread(void (*func)(void*), void* arg) @@ -85,7 +93,7 @@ namespace Scheduler thread->set_ip((u64)func); thread->set_arguments((u64)arg, 0, 0, 0); - return kernel_thread_alloc_stack_and_append_impl(thread); + return new_kernel_thread_impl(thread); } Thread* pick_task() diff --git a/luna/include/luna/ScopeGuard.h b/luna/include/luna/ScopeGuard.h new file mode 100644 index 00000000..4d214002 --- /dev/null +++ b/luna/include/luna/ScopeGuard.h @@ -0,0 +1,28 @@ +#pragma once + +template class ScopeGuard +{ + public: + ScopeGuard(const Callback& callback) : m_callback(callback) + { + } + + void deactivate() + { + m_activated = false; + } + + ~ScopeGuard() + { + if (m_activated) m_callback(); + } + + private: + bool m_activated{true}; + Callback m_callback; +}; + +template [[nodiscard]] ScopeGuard make_scope_guard(const Callback& callback) +{ + return {callback}; +} \ No newline at end of file From 779fda307a73e4047eee32e672c7fd3a451c356c Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 8 Dec 2022 15:01:04 +0100 Subject: [PATCH 226/407] More scope guards!! --- kernel/src/memory/Heap.cpp | 3 +++ kernel/src/thread/Scheduler.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index e7dba4f2..f47fd530 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -36,7 +37,9 @@ static DoublyLinkedList heap; static Result allocate_pages(usize count) { u64 virt = TRY(KernelVM::alloc_several_pages(count)); + auto vm_guard = make_scope_guard([&] { KernelVM::free_several_pages(virt, count).value(); }); void* const ptr = (void*)TRY(MemoryManager::alloc_at(virt, count, MMU::ReadWrite | MMU::NoExecute)); + vm_guard.deactivate(); return (HeapBlock*)ptr; } diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index a6b91f90..2413f37b 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -51,7 +51,7 @@ namespace Scheduler auto thread_guard = make_scope_guard([&] { delete thread; }); u64 thread_stack_vm = TRY(KernelVM::alloc_several_pages(4)); - auto vm_guard = make_scope_guard([&] { KernelVM::free_several_pages(thread_stack_vm, 4); }); + auto vm_guard = make_scope_guard([&] { KernelVM::free_several_pages(thread_stack_vm, 4).value(); }); TRY(MemoryManager::alloc_at(thread_stack_vm, 4, MMU::NoExecute | MMU::ReadWrite)); From 6cee208e6262007941da9daf8801c4f8b28dfe47 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 8 Dec 2022 15:09:32 +0100 Subject: [PATCH 227/407] Kernel: Enable -Wsign-conversion For real this time, turns out me, being dumb, added it to Luna instead of the kernel. --- kernel/CMakeLists.txt | 2 +- kernel/src/Log.cpp | 2 +- kernel/src/arch/Serial.cpp | 6 +++--- kernel/src/arch/Timer.cpp | 22 +++++++++++----------- luna/CMakeLists.txt | 2 +- luna/include/luna/Alignment.h | 18 +++++++++--------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 5e8e03c6..f4a7e678 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -45,7 +45,7 @@ target_compile_definitions(moon PRIVATE IN_MOON) target_compile_options(moon PRIVATE -Os) -target_compile_options(moon PRIVATE -Wall -Wextra -Werror -Wvla) +target_compile_options(moon PRIVATE -Wall -Wextra -Werror -Wvla -Wsign-conversion) target_compile_options(moon PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) target_compile_options(moon PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) target_compile_options(moon PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 5d242ac6..e820dfd9 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -29,7 +29,7 @@ static void log_serial(LogLevel level, const char* format, va_list origin) cstyle_format( format, [](char c, void*) -> Result { - Serial::putchar(c); + Serial::putchar((u8)c); return {}; }, nullptr, ap); diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index 7e6f5f98..e82d75e1 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -7,12 +7,12 @@ namespace Serial { void write(const char* str, usize size) { - while (size--) putchar(*str++); + while (size--) putchar((u8)*str++); } void print(const char* str) { - while (*str) putchar(*str++); + while (*str) putchar((u8)*str++); } void println(const char* str) @@ -28,7 +28,7 @@ namespace Serial auto rc = cstyle_format( format, [](char c, void*) -> Result { - putchar(c); + putchar((u8)c); return {}; }, nullptr, ap); diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 4ed1b780..09500356 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -6,16 +6,16 @@ static u64 timer_ticks = 0; static u64 boot_timestamp; -static inline constexpr int isleap(int year) +static inline constexpr bool isleap(u32 year) { return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); } -static constexpr int make_yday(int year, int month) +static constexpr u32 make_yday(u32 year, u32 month) { - constexpr short int upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + constexpr u16 upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - int yd = upto[month - 1]; + u32 yd = upto[month - 1]; if (month > 2 && isleap(year)) yd++; return yd; } @@ -30,19 +30,19 @@ static constexpr u64 broken_down_to_unix(u64 year, u64 yday, u64 hour, u64 min, // The bootloader encodes the date and time in Binary-Coded Decimal (BCD), which represents decimal digits using // hexadecimal digits. For example, BCD 0x22 is 22 in decimal. // https://gitlab.com/bztsrc/bootboot/-/blob/master/bootboot_spec_1st_ed.pdf, page 15. -static inline constexpr int bcd_number_to_decimal(int num) +static inline constexpr u32 bcd_number_to_decimal(u32 num) { return ((num >> 4) * 10) + (num & 0xf); } static u64 bootloader_time_to_unix(const u8 boottime[8]) { - const int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); - const int month = bcd_number_to_decimal(boottime[2]); - const int day = bcd_number_to_decimal(boottime[3]); - const int hour = bcd_number_to_decimal(boottime[4]); - const int minute = bcd_number_to_decimal(boottime[5]); - const int second = bcd_number_to_decimal(boottime[6]); + const u32 year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); + const u32 month = bcd_number_to_decimal(boottime[2]); + const u32 day = bcd_number_to_decimal(boottime[3]); + const u32 hour = bcd_number_to_decimal(boottime[4]); + const u32 minute = bcd_number_to_decimal(boottime[5]); + const u32 second = bcd_number_to_decimal(boottime[6]); // "The last byte can store 1/100th second precision, but in lack of support on most platforms, it is 0x00". // Therefore, let's not rely on it. kinfoln("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC", day, month, year, hour, minute, second); diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 286619d6..afdc8c8e 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -19,7 +19,7 @@ set(SOURCES add_library(luna-freestanding ${FREESTANDING_SOURCES}) target_compile_definitions(luna-freestanding PRIVATE USE_FREESTANDING) target_compile_options(luna-freestanding PRIVATE -Wall -Wextra -Werror -Wvla) -target_compile_options(luna-freestanding PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self -Wcast-align -Wsign-conversion) +target_compile_options(luna-freestanding PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self -Wsign-conversion) target_compile_options(luna-freestanding PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) target_compile_options(luna-freestanding PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) target_compile_options(luna-freestanding PRIVATE -fno-rtti -ffreestanding -fno-exceptions) diff --git a/luna/include/luna/Alignment.h b/luna/include/luna/Alignment.h index 439bf2a1..90fa632a 100644 --- a/luna/include/luna/Alignment.h +++ b/luna/include/luna/Alignment.h @@ -7,9 +7,9 @@ template constexpr T is_aligned(T value) return (value % alignment == 0); } -static_assert(is_aligned<512>(1024)); -static_assert(!is_aligned<32>(235)); -static_assert(is_aligned<4096>(40960)); +static_assert(is_aligned<512>(1024u)); +static_assert(!is_aligned<32>(235u)); +static_assert(is_aligned<4096>(40960u)); // Must ALWAYS be called with a power of two as alignment. template constexpr T align_down(T value) @@ -18,9 +18,9 @@ template constexpr T align_down(T value) return value - value % alignment; } -static_assert(align_down<512>(598) == 512); -static_assert(align_down<64>(194) == 192); -static_assert(align_down<32>(64) == 64); +static_assert(align_down<512>(598ul) == 512ul); +static_assert(align_down<64>(194ul) == 192ul); +static_assert(align_down<32>(64ul) == 64ul); // Must ALWAYS be called with a power of two as alignment. template constexpr T align_up(T value) @@ -29,9 +29,9 @@ template constexpr T align_up(T value) return align_down(value) + alignment; } -static_assert(align_up<512>(598) == 1024); -static_assert(align_up<64>(194) == 256); -static_assert(align_up<32>(64) == 64); +static_assert(align_up<512>(598ul) == 1024ul); +static_assert(align_up<64>(194ul) == 256ul); +static_assert(align_up<32>(64ul) == 64ul); template constexpr T get_blocks_from_size(T value, T block_size) { From b58eba63f163bb2efe4551f32a0f9bc09dc8df23 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 8 Dec 2022 16:08:02 +0100 Subject: [PATCH 228/407] Add a new Option class which behaves like Result, but has no error number, just a value or no value --- luna/include/luna/Option.h | 139 +++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 luna/include/luna/Option.h diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h new file mode 100644 index 00000000..49d58ee7 --- /dev/null +++ b/luna/include/luna/Option.h @@ -0,0 +1,139 @@ +#pragma once +#include +#include +#include + +template class Option +{ + public: + Option(const T& value) + { + m_storage.store_reference(value); + m_has_value = true; + } + + Option(T&& value) + { + m_storage.store_moved_reference(move(value)); + m_has_value = true; + } + + Option(const Option& other) + { + m_has_value = other.has_value(); + if (m_has_value) { m_storage.store_reference(other.m_storage.fetch_reference()); } + } + + Option(Option&& other) + { + m_has_value = other.has_value(); + other.m_has_value = false; + if (m_has_value) { m_storage.store_moved_reference(move(other.m_storage.fetch_reference())); } + } + + Option() + { + m_has_value = false; + } + + bool has_value() const + { + return m_has_value; + } + + T value() const + { + expect(has_value(), "Option::value called on an empty Option"); + return m_storage.fetch_reference(); + } + + T release_value() + { + expect(has_value(), "Option::release_value called on an empty Option"); + T item = m_storage.fetch_reference(); + m_has_value = false; + m_storage.destroy(); + return move(item); + } + + T value_or(const T& other) const + { + if (has_value()) return m_storage.fetch_reference(); + return other; + } + + bool try_set_value(T& ref) const + { + if (!has_value()) return false; + ref = m_storage.fetch_reference(); + return true; + } + + ~Option() + { + if (has_value()) m_storage.destroy(); + } + + struct ErrorHandle + { + private: + explicit ErrorHandle() + { + } + }; + + Option(ErrorHandle) + { + m_has_value = false; + } + + // For compatibility with TRY() + ErrorHandle release_error() + { + expect(!has_value(), "Option::release_error called on a non-empty Option"); + return ErrorHandle{}; + } + + private: + struct Storage + { + u8 buffer[sizeof(T)]; + + T* fetch_ptr() + { + return (T*)buffer; + } + + T& fetch_reference() + { + return *fetch_ptr(); + } + + const T* fetch_ptr() const + { + return (const T*)buffer; + } + + const T& fetch_reference() const + { + return *fetch_ptr(); + } + + void store_reference(const T& ref) + { + new (buffer) T(ref); + } + + void store_moved_reference(T&& ref) + { + new (buffer) T(ref); + } + + void destroy() + { + fetch_reference().~T(); + } + }; + Storage m_storage; + bool m_has_value{false}; +}; \ No newline at end of file From 406af68a543265adca750bfe0b1565ddae81920f Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 8 Dec 2022 16:08:18 +0100 Subject: [PATCH 229/407] Result: Use Option as backend --- luna/include/luna/Result.h | 92 +++++++------------------------------- 1 file changed, 15 insertions(+), 77 deletions(-) diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index a923bff4..1b93b37e 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -18,25 +19,22 @@ struct Error template class Result { public: - Result(const T& value) + Result(const T& value) : m_value(value) { - m_storage.store_reference(value); m_has_value = true; m_has_error = false; } - Result(T&& value) + Result(T&& value) : m_value(value) { - m_storage.store_movable_reference(move(value)); m_has_value = true; m_has_error = false; } - Result(const Result& other) + Result(const Result& other) : m_value(other.m_value) { if (!other.m_has_error) { - m_storage.store_reference(other.m_storage.fetch_reference()); m_has_value = true; m_has_error = false; } @@ -48,11 +46,10 @@ template class Result } } - Result(Result&& other) + Result(Result&& other) : m_value(other.m_value) { if (!other.m_has_error) { - m_storage.store_movable_reference(move(other.m_storage.fetch_reference())); m_has_value = true; m_has_error = false; } @@ -64,7 +61,7 @@ template class Result } } - Result(const Error& err) + Result(const Error& err) : m_value() { m_error = err.error; m_has_error = true; @@ -102,98 +99,39 @@ template class Result T value() { expect(has_value(), "Result::value() called on a Result that holds an error"); - return m_storage.fetch_reference(); + return m_value.value(); } T expect_value(const char* reason) { expect(has_value(), reason); - return m_storage.fetch_reference(); + return move(m_value.release_value()); } - T value_or(T other) + T value_or(const T& other) { - if (has_value()) return m_storage.fetch_reference(); - return other; + return m_value.value_or(other); } bool try_set_value(T& ref) { - if (!has_value()) return false; - ref = m_storage.fetch_reference(); - return true; + return m_value.try_set_value(ref); } T release_value() { expect(has_value(), "Result::release_value() called on a Result that holds an error"); - T item = m_storage.fetch_reference(); - m_has_value = false; - m_storage.destroy(); - return move(item); + return m_value.release_value(); } T expect_release_value(const char* reason) { expect(has_value(), reason); - T item = m_storage.fetch_reference(); - m_has_value = false; - m_storage.destroy(); - return move(item); - } - - ~Result() - { - if (has_value()) m_storage.destroy(); + return m_value.release_value(); } private: - struct Storage - { - u8 buffer[sizeof(T)]; - - T* fetch_ptr() - { - return (T*)buffer; - } - - T& fetch_reference() - { - return *fetch_ptr(); - } - - const T* fetch_ptr() const - { - return (const T*)buffer; - } - - const T& fetch_reference() const - { - return *fetch_ptr(); - } - - void store_ptr(T* ptr) - { - new (buffer) T(*ptr); - } - - void store_reference(const T& ref) - { - new (buffer) T(ref); - } - - void store_movable_reference(T&& ref) - { - new (buffer) T(ref); - } - - void destroy() - { - fetch_reference().~T(); - } - }; - - Storage m_storage; + Option m_value; int m_error; bool m_has_error; bool m_has_value; @@ -289,6 +227,6 @@ template <> class Result #define TRY(expr) \ ({ \ auto _expr_rc = (expr); \ - if (_expr_rc.has_error()) return _expr_rc.release_error(); \ + if (!_expr_rc.has_value()) return _expr_rc.release_error(); \ _expr_rc.expect_release_value("sanity check failed: has_error() returned false, yet result has no value"); \ }) From b6173e2b673563a22b6bbab3c96b1adfadd602f0 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 8 Dec 2022 16:09:04 +0100 Subject: [PATCH 230/407] LinkedList: Return Option instead of ENONE if no value --- kernel/src/thread/Scheduler.cpp | 4 ++-- luna/include/luna/LinkedList.h | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 2413f37b..03e2be9c 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -102,7 +102,7 @@ namespace Scheduler if (old->is_idle()) { auto maybe_last = g_threads.last(); - if (maybe_last.has_error()) // No threads!! + if (!maybe_last.has_value()) // No threads!! return &g_idle; g_current = old = maybe_last.value(); } @@ -111,7 +111,7 @@ namespace Scheduler do { auto maybe_next = g_threads.next(g_current); - if (maybe_next.has_error()) g_current = g_threads.expect_first(); + if (!maybe_next.has_value()) g_current = g_threads.expect_first(); else g_current = maybe_next.value(); diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 698e5a9a..47a07cbf 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -1,9 +1,9 @@ #pragma once -#include +#include -template inline Result nonnull_or_error(T* ptr) +template inline Option nonnull_or_error(T* ptr) { - if (ptr == nullptr) return err(ENONE); + if (ptr == nullptr) return {}; else return ptr; } @@ -101,7 +101,7 @@ template class DoublyLinkedList return ptr; } - Result first() + Option first() { return nonnull_or_error((T*)m_start_node); } @@ -111,7 +111,7 @@ template class DoublyLinkedList return first().value(); } - Result last() + Option last() { return nonnull_or_error((T*)m_end_node); } @@ -121,12 +121,12 @@ template class DoublyLinkedList return last().value(); } - Result next(T* item) + Option next(T* item) { return nonnull_or_error((T*)extract_node(item)->get_next()); } - Result previous(T* item) + Option previous(T* item) { return nonnull_or_error((T*)extract_node(item)->get_last()); } From da104c87cb07f6d2db0240d24a31600eeb204699 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 8 Dec 2022 16:09:12 +0100 Subject: [PATCH 231/407] Heap: Return Option in split() --- kernel/src/memory/Heap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index f47fd530..10f558aa 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -94,14 +94,14 @@ static usize get_fair_offset_to_split_at(HeapBlock* block, usize min) return available + block->req_size; } -static Result split(HeapBlock* block, usize size) +static Option split(HeapBlock* block, usize size) { const usize available = space_available(block); // How much space can we steal from this block? const usize old_size = block->full_size; // Save the old value of this variable since we are going to use it after modifying it if (available < (size + sizeof(HeapBlock))) - return err(ENONE); // This block hasn't got enough free space to hold the requested size. + return {}; // This block hasn't got enough free space to hold the requested size. const usize offset = get_fair_offset_to_split_at(block, size + sizeof(HeapBlock)); block->full_size = offset; // shrink the old block to fit this offset From b9f3d3c349bcf1d68e5a7be990e0ee568cf0a41b Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 8 Dec 2022 16:09:33 +0100 Subject: [PATCH 232/407] Remove ENONE If you want to return an error without meaning, use Option. --- luna/include/luna/SystemError.h | 3 +-- luna/src/SystemError.cpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/luna/include/luna/SystemError.h b/luna/include/luna/SystemError.h index 16bef760..0c952b57 100644 --- a/luna/include/luna/SystemError.h +++ b/luna/include/luna/SystemError.h @@ -52,8 +52,7 @@ #define ETIMEDOUT 110 // Connection timed out #define EALREADY 114 // Operation already in progress -// These ones are Luna-specific. +// This one is Luna-specific. #define EFIXME 342 // Functionality not yet implemented -#define ENONE 343 // Internal or insignificant error const char* error_string(int error); \ No newline at end of file diff --git a/luna/src/SystemError.cpp b/luna/src/SystemError.cpp index 27aa0853..2e1f63ad 100644 --- a/luna/src/SystemError.cpp +++ b/luna/src/SystemError.cpp @@ -55,7 +55,6 @@ const char* error_string(int error) case ETIMEDOUT: return "Connection timed out"; case EALREADY: return "Operation already in progress"; case EFIXME: return "Functionality not yet implemented"; - case ENONE: return "Internal or insignificant error"; default: return "Unknown error"; } } \ No newline at end of file From 19a4e2ab58e1dd058709243ac9e7488e7d9f9a5a Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 18:11:17 +0100 Subject: [PATCH 233/407] Result, Option: Make sure everything is properly moved --- luna/include/luna/Option.h | 2 +- luna/include/luna/Result.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index 49d58ee7..a80cf433 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -126,7 +126,7 @@ template class Option void store_moved_reference(T&& ref) { - new (buffer) T(ref); + new (buffer) T(move(ref)); } void destroy() diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index 1b93b37e..68581a28 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -25,7 +25,7 @@ template class Result m_has_error = false; } - Result(T&& value) : m_value(value) + Result(T&& value) : m_value(move(value)) { m_has_value = true; m_has_error = false; @@ -46,7 +46,7 @@ template class Result } } - Result(Result&& other) : m_value(other.m_value) + Result(Result&& other) : m_value(move(other.m_value)) { if (!other.m_has_error) { From 32c8869973ea85647a0d5442557fc3bfdae6424f Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 18:13:40 +0100 Subject: [PATCH 234/407] Option: Simplify release_value This avoids copying + we don't need to destroy the item if we move it, since it either gets emptied by moving it or doesn't have anything to destroy. --- luna/include/luna/Option.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index a80cf433..9ef4a58d 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -50,10 +50,8 @@ template class Option T release_value() { expect(has_value(), "Option::release_value called on an empty Option"); - T item = m_storage.fetch_reference(); m_has_value = false; - m_storage.destroy(); - return move(item); + return move(m_storage.fetch_reference()); } T value_or(const T& other) const From d759058b80717cc7a309a40724aebcc0578f5c14 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 18:14:48 +0100 Subject: [PATCH 235/407] Introduce std::nothrow Let's make sure we explicitly tell new that we don't want exceptions --- kernel/src/memory/Heap.cpp | 10 ++++++++-- luna/include/luna/Alloc.h | 21 +++++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 10f558aa..5cf176e8 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -5,12 +5,18 @@ #include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include +#include #include #include #include #include #include +namespace std +{ + const std::nothrow_t nothrow; +} + static constexpr int BLOCK_USED = 1 << 0; static constexpr int BLOCK_START_MEM = 1 << 1; static constexpr int BLOCK_END_MEM = 1 << 2; @@ -354,12 +360,12 @@ void dump_heap_usage() kdbgln("-- Heap memory in use by the kernel: %zu bytes", alloc_used); } -void* operator new(usize size) noexcept +void* operator new(usize size, const std::nothrow_t&) noexcept { return kmalloc(size).value_or(nullptr); } -void* operator new[](usize size) noexcept +void* operator new[](usize size, const std::nothrow_t&) noexcept { return kmalloc(size).value_or(nullptr); } diff --git a/luna/include/luna/Alloc.h b/luna/include/luna/Alloc.h index d76b7442..562ac483 100644 --- a/luna/include/luna/Alloc.h +++ b/luna/include/luna/Alloc.h @@ -1,19 +1,36 @@ #pragma once #include +namespace std +{ + struct nothrow_t + { + explicit nothrow_t() = default; + }; + + extern const nothrow_t nothrow; + + enum class align_val_t : usize + { + }; +}; + [[nodiscard]] void* raw_malloc(usize); void raw_free(void*); +void* operator new(usize size, const std::nothrow_t&) noexcept; +void* operator new[](usize size, const std::nothrow_t&) noexcept; + template [[nodiscard]] Result make(Args... args) { - T* const result = new T(args...); + T* const result = new (std::nothrow) T(args...); if (!result) return err(ENOMEM); return result; } template [[nodiscard]] Result make_array(usize count) { - T* const result = new T[count]; + T* const result = new (std::nothrow) T[count]; if (!result) return err(ENOMEM); return result; } From be22cf62670b3b7e92b9c06475bbb24f93819445 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 18:17:15 +0100 Subject: [PATCH 236/407] Introduce OwnedStringView A managed String which uses RAII to free its contents. It's not a proper string though, since it's read-only. So it's a StringView... but an owned one. Can't be copied automatically, must be either moved or copied manually by calling clone() on it. --- luna/CMakeLists.txt | 1 + luna/include/luna/OwnedStringView.h | 27 ++++++++++++++++++++++ luna/src/OwnedStringView.cpp | 36 +++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 luna/include/luna/OwnedStringView.h create mode 100644 luna/src/OwnedStringView.cpp diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index afdc8c8e..655dc333 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -9,6 +9,7 @@ set(FREESTANDING_SOURCES src/Bitmap.cpp src/Stack.cpp src/Alloc.cpp + src/OwnedStringView.cpp ) set(SOURCES diff --git a/luna/include/luna/OwnedStringView.h b/luna/include/luna/OwnedStringView.h new file mode 100644 index 00000000..4dd59332 --- /dev/null +++ b/luna/include/luna/OwnedStringView.h @@ -0,0 +1,27 @@ +#pragma once + +class OwnedStringView +{ + public: + OwnedStringView(char* c_str); + OwnedStringView(); + OwnedStringView(OwnedStringView&&); + OwnedStringView(const OwnedStringView&) = delete; + ~OwnedStringView(); + + Result clone(); + + const char* chars() + { + return m_string; + } + + usize length() + { + return m_length; + } + + private: + char* m_string{nullptr}; + usize m_length{0}; +}; \ No newline at end of file diff --git a/luna/src/OwnedStringView.cpp b/luna/src/OwnedStringView.cpp new file mode 100644 index 00000000..d81a30cf --- /dev/null +++ b/luna/src/OwnedStringView.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +OwnedStringView::OwnedStringView() +{ +} + +OwnedStringView::OwnedStringView(OwnedStringView&& other) +{ + m_string = other.m_string; + m_length = other.m_length; + + other.m_string = nullptr; +} + +OwnedStringView::OwnedStringView(char* c_str) +{ + m_string = c_str; + + if (m_string) { m_length = strlen(m_string); } +} + +OwnedStringView::~OwnedStringView() +{ + if (m_string) destroy_array(m_string); +} + +Result OwnedStringView::clone() +{ + char* buf = TRY(make_array(m_length + 1)); + + memcpy(buf, m_string, m_length + 1); + + return OwnedStringView{buf}; +} \ No newline at end of file From 41b3c8adb2ae10847eb7b1d5013e6283b413a7e9 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 18:18:24 +0100 Subject: [PATCH 237/407] Convert to_dynamic_unit to OwnedStringView and rename the old variant to to_dynamic_unit_cstr --- kernel/src/main.cpp | 22 +++++++++++++--------- luna/include/luna/Units.h | 4 +++- luna/src/Units.cpp | 17 ++++++++++++++++- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 80c7accc..6947c075 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,6 +4,7 @@ #include "arch/Timer.h" #include "boot/Init.h" #include "config.h" +#include "memory/Heap.h" #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include @@ -23,6 +24,13 @@ void async_thread() } } +void heap_thread() +{ + CPU::disable_interrupts(); + dump_heap_usage(); + while (true) kernel_sleep(UINT64_MAX); +} + Result init() { kinfoln("Starting Moon %s", MOON_VERSION); @@ -33,19 +41,15 @@ Result init() Timer::init(); - char buffer[64]; - to_dynamic_unit(MemoryManager::total(), buffer, sizeof(buffer)); - kinfoln("Total memory: %s", buffer); - to_dynamic_unit(MemoryManager::free(), buffer, sizeof(buffer)); - kinfoln("Free memory: %s", buffer); - to_dynamic_unit(MemoryManager::used(), buffer, sizeof(buffer)); - kinfoln("Used memory: %s", buffer); - to_dynamic_unit(MemoryManager::reserved(), buffer, sizeof(buffer)); - kinfoln("Reserved memory: %s", buffer); + kinfoln("Total memory: %s", to_dynamic_unit(MemoryManager::total()).release_value().chars()); + kinfoln("Free memory: %s", to_dynamic_unit(MemoryManager::free()).release_value().chars()); + kinfoln("Used memory: %s", to_dynamic_unit(MemoryManager::used()).release_value().chars()); + kinfoln("Reserved memory: %s", to_dynamic_unit(MemoryManager::reserved()).release_value().chars()); Scheduler::init(); TRY(Scheduler::new_kernel_thread(async_thread)); + TRY(Scheduler::new_kernel_thread(heap_thread)); CPU::platform_finish_init(); diff --git a/luna/include/luna/Units.h b/luna/include/luna/Units.h index 854c18b8..d20b4e0e 100644 --- a/luna/include/luna/Units.h +++ b/luna/include/luna/Units.h @@ -1,4 +1,6 @@ #pragma once +#include #include -Result to_dynamic_unit(usize value, char* buffer, usize max); \ No newline at end of file +Result to_dynamic_unit_cstr(usize value, char* buffer, usize max); +Result to_dynamic_unit(usize value); \ No newline at end of file diff --git a/luna/src/Units.cpp b/luna/src/Units.cpp index 0b64dd9e..e8002d1c 100644 --- a/luna/src/Units.cpp +++ b/luna/src/Units.cpp @@ -1,8 +1,10 @@ +#include #include #include +#include #include -Result to_dynamic_unit(usize value, char* buffer, usize max) +Result to_dynamic_unit_cstr(usize value, char* buffer, usize max) { if (value < 1024) { return string_format(buffer, max, "%u bytes", value); } @@ -14,4 +16,17 @@ Result to_dynamic_unit(usize value, char* buffer, usize max) } return string_format(buffer, max, "%u.%u %ciB", value / 1024, (value % 1024) / 103, *unit_prefixes); +} + +Result to_dynamic_unit(usize value) +{ + char* buf = TRY(make_array(64)); + + auto guard = make_scope_guard([&] { destroy_array(buf); }); + + TRY(to_dynamic_unit_cstr(value, buf, 64)); + + guard.deactivate(); + + return OwnedStringView{buf}; } \ No newline at end of file From 814672c77107302b5ef1ce4a4ca2f2634b5b523e Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 18:32:29 +0100 Subject: [PATCH 238/407] Remove some redundant error propagation Why can printing to the serial port or format onto a string fail? Even if cstyle_format returns Result, we shouldn't always follow suit. --- kernel/src/Log.cpp | 18 ++++++++---------- kernel/src/Log.h | 11 +++-------- kernel/src/arch/Serial.cpp | 15 ++++++++------- kernel/src/arch/Serial.h | 2 +- kernel/src/video/TextConsole.cpp | 15 ++++++++------- kernel/src/video/TextConsole.h | 2 +- luna/include/luna/Format.h | 4 ++-- luna/include/luna/Result.h | 2 +- luna/include/luna/Units.h | 2 +- luna/src/Format.cpp | 29 +++++++++++++++-------------- luna/src/Units.cpp | 8 ++------ 11 files changed, 50 insertions(+), 58 deletions(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index e820dfd9..d26190b1 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -32,7 +32,8 @@ static void log_serial(LogLevel level, const char* format, va_list origin) Serial::putchar((u8)c); return {}; }, - nullptr, ap); + nullptr, ap) + .expect_value("Sanity check failed in log_serial: Should never fail"); Serial::putchar('\n'); @@ -61,7 +62,8 @@ static void log_text_console(LogLevel level, const char* format, va_list origin) TextConsole::putchar(c); return {}; }, - nullptr, ap); + nullptr, ap) + .expect_value("Sanity check failed in log_text_console: Should never fail"); TextConsole::putchar('\n'); @@ -72,26 +74,22 @@ static void log_text_console(LogLevel level, const char* format, va_list origin) va_end(ap); } -Result vlog(LogLevel level, const char* format, va_list ap) +void vlog(LogLevel level, const char* format, va_list ap) { - if (!g_debug_enabled && level == LogLevel::Debug) return {}; + if (!g_debug_enabled && level == LogLevel::Debug) return; if (g_serial_enabled) log_serial(level, format, ap); if (g_text_console_enabled) log_text_console(level, format, ap); - - return {}; } -Result log(LogLevel level, const char* format, ...) +void log(LogLevel level, const char* format, ...) { va_list ap; va_start(ap, format); - TRY(vlog(level, format, ap)); + vlog(level, format, ap); va_end(ap); - - return {}; } void setup_log(bool enable_debug, bool enable_serial, bool enable_text_console) diff --git a/kernel/src/Log.h b/kernel/src/Log.h index 10eaed9f..31dddd5c 100644 --- a/kernel/src/Log.h +++ b/kernel/src/Log.h @@ -11,8 +11,8 @@ enum class LogLevel Error, }; -Result vlog(LogLevel level, const char* format, va_list ap); -Result log(LogLevel level, const char* format, ...) _format(2, 3); +void vlog(LogLevel level, const char* format, va_list ap); +void log(LogLevel level, const char* format, ...) _format(2, 3); void setup_log(bool enable_debug, bool enable_serial, bool enable_text_console); bool log_debug_enabled(); @@ -22,9 +22,4 @@ bool log_text_console_enabled(); #define kdbgln(...) log(LogLevel::Debug, __VA_ARGS__) #define kinfoln(...) log(LogLevel::Info, __VA_ARGS__) #define kwarnln(...) log(LogLevel::Warn, __VA_ARGS__) -#define kerrorln(...) log(LogLevel::Error, __VA_ARGS__) - -#define try_kdbgln(...) TRY(log(LogLevel::Debug, __VA_ARGS__)) -#define try_kinfoln(...) TRY(log(LogLevel::Info, __VA_ARGS__)) -#define try_kwarnln(...) TRY(log(LogLevel::Warn, __VA_ARGS__)) -#define try_kerrorln(...) TRY(log(LogLevel::Error, __VA_ARGS__)) \ No newline at end of file +#define kerrorln(...) log(LogLevel::Error, __VA_ARGS__) \ No newline at end of file diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index e82d75e1..ce12ddae 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -21,17 +21,18 @@ namespace Serial putchar('\n'); } - Result printf(const char* format, ...) + usize printf(const char* format, ...) { va_list ap; va_start(ap, format); auto rc = cstyle_format( - format, - [](char c, void*) -> Result { - putchar((u8)c); - return {}; - }, - nullptr, ap); + format, + [](char c, void*) -> Result { + putchar((u8)c); + return {}; + }, + nullptr, ap) + .expect_value("Sanity check failed in Serial::printf: Should never fail"); va_end(ap); return rc; } diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h index 0efc6e47..f74597c7 100644 --- a/kernel/src/arch/Serial.h +++ b/kernel/src/arch/Serial.h @@ -10,5 +10,5 @@ namespace Serial void write(const char* str, usize size); void print(const char* str); void println(const char* str); - Result printf(const char* str, ...) _format(1, 2); + usize printf(const char* str, ...) _format(1, 2); } \ No newline at end of file diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index dc5f96a0..d3679350 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -157,17 +157,18 @@ namespace TextConsole putchar('\n'); } - Result printf(const char* format, ...) + usize printf(const char* format, ...) { va_list ap; va_start(ap, format); auto rc = cstyle_format( - format, - [](char c, void*) -> Result { - putchar(c); - return {}; - }, - nullptr, ap); + format, + [](char c, void*) -> Result { + putchar(c); + return {}; + }, + nullptr, ap) + .expect_value("Sanity check failed in TextConsole::printf: Should never fail"); va_end(ap); return rc; } diff --git a/kernel/src/video/TextConsole.h b/kernel/src/video/TextConsole.h index d502e485..73ae96b5 100644 --- a/kernel/src/video/TextConsole.h +++ b/kernel/src/video/TextConsole.h @@ -14,5 +14,5 @@ namespace TextConsole void move_to(u32 x, u32 y); void print(const char* str); void println(const char* str); - Result printf(const char* format, ...) _format(1, 2); + usize printf(const char* format, ...) _format(1, 2); } \ No newline at end of file diff --git a/luna/include/luna/Format.h b/luna/include/luna/Format.h index e1cccc3c..fc3a4610 100644 --- a/luna/include/luna/Format.h +++ b/luna/include/luna/Format.h @@ -6,5 +6,5 @@ typedef Result (*callback_t)(char, void*); Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); -Result vstring_format(char* buf, usize max, const char* format, va_list ap); -Result string_format(char* buf, usize max, const char* format, ...); \ No newline at end of file +usize vstring_format(char* buf, usize max, const char* format, va_list ap); +usize string_format(char* buf, usize max, const char* format, ...); \ No newline at end of file diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index 68581a28..b8ac716e 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -105,7 +105,7 @@ template class Result T expect_value(const char* reason) { expect(has_value(), reason); - return move(m_value.release_value()); + return m_value.value(); } T value_or(const T& other) diff --git a/luna/include/luna/Units.h b/luna/include/luna/Units.h index d20b4e0e..6b062f1a 100644 --- a/luna/include/luna/Units.h +++ b/luna/include/luna/Units.h @@ -2,5 +2,5 @@ #include #include -Result to_dynamic_unit_cstr(usize value, char* buffer, usize max); +usize to_dynamic_unit_cstr(usize value, char* buffer, usize max); Result to_dynamic_unit(usize value); \ No newline at end of file diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index a74b0a38..b10754be 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -478,33 +478,34 @@ struct StringFormatInfo usize remaining; }; -Result vstring_format(char* buf, usize max, const char* format, va_list ap) +usize vstring_format(char* buf, usize max, const char* format, va_list ap) { StringFormatInfo info = {.buffer = buf, .remaining = max - 1}; - usize result = TRY(cstyle_format( - format, - [](char c, void* arg) -> Result { - StringFormatInfo* info_arg = (StringFormatInfo*)arg; - if (!info_arg->remaining) return {}; - *(info_arg->buffer) = c; - info_arg->buffer++; - info_arg->remaining--; - return {}; - }, - &info, ap)); + usize result = cstyle_format( + format, + [](char c, void* arg) -> Result { + StringFormatInfo* info_arg = (StringFormatInfo*)arg; + if (!info_arg->remaining) return {}; + *(info_arg->buffer) = c; + info_arg->buffer++; + info_arg->remaining--; + return {}; + }, + &info, ap) + .expect_value("Sanity check failed in vstring_format: Should never fail"); *(info.buffer) = 0; return result; } -Result string_format(char* buf, usize max, const char* format, ...) +usize string_format(char* buf, usize max, const char* format, ...) { va_list ap; va_start(ap, format); - usize result = TRY(vstring_format(buf, max, format, ap)); + usize result = vstring_format(buf, max, format, ap); va_end(ap); diff --git a/luna/src/Units.cpp b/luna/src/Units.cpp index e8002d1c..85a73900 100644 --- a/luna/src/Units.cpp +++ b/luna/src/Units.cpp @@ -4,7 +4,7 @@ #include #include -Result to_dynamic_unit_cstr(usize value, char* buffer, usize max) +usize to_dynamic_unit_cstr(usize value, char* buffer, usize max) { if (value < 1024) { return string_format(buffer, max, "%u bytes", value); } @@ -22,11 +22,7 @@ Result to_dynamic_unit(usize value) { char* buf = TRY(make_array(64)); - auto guard = make_scope_guard([&] { destroy_array(buf); }); - - TRY(to_dynamic_unit_cstr(value, buf, 64)); - - guard.deactivate(); + to_dynamic_unit_cstr(value, buf, 64); return OwnedStringView{buf}; } \ No newline at end of file From cedcfa9c63f4732835f4b6722f0c21ed3a26eaf9 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 19:36:38 +0100 Subject: [PATCH 239/407] Improve cleanup on MemoryManager failure + add methods that use KernelVM --- kernel/src/main.cpp | 3 ++ kernel/src/memory/Heap.cpp | 8 ++---- kernel/src/memory/MemoryManager.cpp | 43 +++++++++++++++++++++++++++++ kernel/src/memory/MemoryManager.h | 2 ++ kernel/src/thread/Scheduler.cpp | 13 +++------ 5 files changed, 54 insertions(+), 15 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 6947c075..05768089 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,10 +1,12 @@ #include "Log.h" #include "arch/CPU.h" +#include "arch/MMU.h" #include "arch/Serial.h" #include "arch/Timer.h" #include "boot/Init.h" #include "config.h" #include "memory/Heap.h" +#include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include @@ -28,6 +30,7 @@ void heap_thread() { CPU::disable_interrupts(); dump_heap_usage(); + kdbgln("uses %lu vm pages", KernelVM::used() / ARCH_PAGE_SIZE); while (true) kernel_sleep(UINT64_MAX); } diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 5cf176e8..faea101d 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -42,17 +42,13 @@ static DoublyLinkedList heap; static Result allocate_pages(usize count) { - u64 virt = TRY(KernelVM::alloc_several_pages(count)); - auto vm_guard = make_scope_guard([&] { KernelVM::free_several_pages(virt, count).value(); }); - void* const ptr = (void*)TRY(MemoryManager::alloc_at(virt, count, MMU::ReadWrite | MMU::NoExecute)); - vm_guard.deactivate(); + void* const ptr = (void*)TRY(MemoryManager::alloc_for_kernel(count, MMU::ReadWrite | MMU::NoExecute)); return (HeapBlock*)ptr; } static Result release_pages(void* ptr, usize count) { - TRY(KernelVM::free_several_pages((u64)ptr, count)); - return MemoryManager::unmap_owned((u64)ptr, count); + return MemoryManager::unmap_owned_and_free_vm((u64)ptr, count); } // If we're allocating a large amount of memory, map enough pages for it, but otherwise just use the default amount of diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index dffbd6cd..8106a353 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -6,6 +6,7 @@ #include "memory/MemoryMap.h" #include #include +#include #include #include #include @@ -171,6 +172,9 @@ namespace MemoryManager CHECK_PAGE_ALIGNED(virt); CHECK_PAGE_ALIGNED(phys); + // Let's clean up after ourselves if we fail. + auto guard = make_scope_guard([=] { unmap_weak(virt, count); }); + while (count--) { TRY(MMU::map(virt, phys, flags)); @@ -178,6 +182,8 @@ namespace MemoryManager phys += ARCH_PAGE_SIZE; } + guard.deactivate(); + return {}; } @@ -187,6 +193,8 @@ namespace MemoryManager u64 start = virt; + auto guard = make_scope_guard([=] { unmap_owned(start, count); }); + while (count--) { u64 frame = TRY(alloc_frame()); @@ -194,6 +202,32 @@ namespace MemoryManager virt += ARCH_PAGE_SIZE; } + guard.deactivate(); + + return start; + } + + Result alloc_for_kernel(usize count, int flags) + { + u64 start = TRY(KernelVM::alloc_several_pages(count)); + + auto guard = make_scope_guard([=] { + KernelVM::free_several_pages(start, count); + // unmap_owned will fail as soon as we reach the end of the mapped range. That's fine, exactly what we want. + unmap_owned(start, count); + }); + + u64 virt = start; + + while (count--) + { + u64 frame = TRY(alloc_frame()); + TRY(MMU::map(virt, frame, flags)); + virt += ARCH_PAGE_SIZE; + } + + guard.deactivate(); + return start; } @@ -211,6 +245,15 @@ namespace MemoryManager return {}; } + Result unmap_owned_and_free_vm(u64 virt, usize count) + { + CHECK_PAGE_ALIGNED(virt); + + KernelVM::free_several_pages(virt, count); + + return unmap_owned(virt, count); + } + Result unmap_weak(u64 virt, usize count) { CHECK_PAGE_ALIGNED(virt); diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 5ef62177..cf3ed2ce 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -23,8 +23,10 @@ namespace MemoryManager Result map_frames_at(u64 virt, u64 phys, usize count, int flags); Result alloc_at(u64 virt, usize count, int flags); + Result alloc_for_kernel(usize count, int flags); Result unmap_owned(u64 virt, usize count); + Result unmap_owned_and_free_vm(u64 virt, usize count); Result unmap_weak(u64 virt, usize count); usize free(); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 03e2be9c..e6267ea2 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -24,8 +24,7 @@ namespace Scheduler g_idle.ticks_left = 1; // Map some stack for the idle task - u64 idle_stack_vm = KernelVM::alloc_one_page().release_value(); - MemoryManager::alloc_at(idle_stack_vm, 1, MMU::NoExecute | MMU::ReadWrite).release_value(); + u64 idle_stack_vm = MemoryManager::alloc_for_kernel(1, MMU::NoExecute | MMU::ReadWrite).release_value(); Stack idle_stack{idle_stack_vm, ARCH_PAGE_SIZE}; g_idle.set_sp(idle_stack.top()); @@ -48,15 +47,11 @@ namespace Scheduler Result new_kernel_thread_impl(Thread* thread) { // If anything fails, make sure to clean up. - auto thread_guard = make_scope_guard([&] { delete thread; }); + auto guard = make_scope_guard([&] { delete thread; }); - u64 thread_stack_vm = TRY(KernelVM::alloc_several_pages(4)); - auto vm_guard = make_scope_guard([&] { KernelVM::free_several_pages(thread_stack_vm, 4).value(); }); + u64 thread_stack_vm = TRY(MemoryManager::alloc_for_kernel(4, MMU::NoExecute | MMU::ReadWrite)); - TRY(MemoryManager::alloc_at(thread_stack_vm, 4, MMU::NoExecute | MMU::ReadWrite)); - - thread_guard.deactivate(); - vm_guard.deactivate(); + guard.deactivate(); Stack thread_stack{thread_stack_vm, ARCH_PAGE_SIZE * 4}; thread->set_sp(thread_stack.top()); From a32590ff8aa5e55f93919655a647917ea22095fa Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 19:44:33 +0100 Subject: [PATCH 240/407] Call expect_value more --- kernel/src/memory/MemoryManager.cpp | 8 +++++--- kernel/src/memory/MemoryMap.cpp | 4 ++-- kernel/src/thread/Scheduler.cpp | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 8106a353..75db28db 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -105,10 +105,12 @@ namespace MemoryManager // there's no point in continuing. auto bitmap_pages = g_frame_bitmap.size_in_bytes() / ARCH_PAGE_SIZE; - auto virtual_bitmap_base = KernelVM::alloc_several_pages(bitmap_pages).release_value(); + auto virtual_bitmap_base = + KernelVM::alloc_several_pages(bitmap_pages) + .expect_value("Unable to allocate virtual memory for the physical frame bitmap, cannot continue"); map_frames_at(virtual_bitmap_base, (u64)g_frame_bitmap.location(), bitmap_pages, MMU::ReadWrite | MMU::NoExecute) - .release_value(); + .expect_value("Unable to map the physical frame bitmap to virtual memory, cannot continue"); g_frame_bitmap.initialize((void*)virtual_bitmap_base, g_frame_bitmap.size_in_bytes()); } @@ -292,7 +294,7 @@ namespace MemoryManager { auto rc = MMU::get_flags(address); if (rc.has_error()) return false; - if (rc.release_value() & MMU::ReadWrite) return true; + if (rc.value() & MMU::ReadWrite) return true; return false; } diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index f4917633..cf83a67a 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -63,7 +63,7 @@ MemoryMapEntry MemoryMapIterator::largest_free() } } - return at(largest_index).release_value(); + return at(largest_index).value(); } MemoryMapEntry MemoryMapIterator::highest() @@ -83,5 +83,5 @@ MemoryMapEntry MemoryMapIterator::highest() } } - return at(highest_index).release_value(); + return at(highest_index).value(); } \ No newline at end of file diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index e6267ea2..36f2692e 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -24,7 +24,8 @@ namespace Scheduler g_idle.ticks_left = 1; // Map some stack for the idle task - u64 idle_stack_vm = MemoryManager::alloc_for_kernel(1, MMU::NoExecute | MMU::ReadWrite).release_value(); + u64 idle_stack_vm = MemoryManager::alloc_for_kernel(1, MMU::NoExecute | MMU::ReadWrite) + .expect_value("Error while setting up the idle task, cannot continue"); Stack idle_stack{idle_stack_vm, ARCH_PAGE_SIZE}; g_idle.set_sp(idle_stack.top()); From 2e24e091467c64a7b3720af34763469b5ff050d5 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 19:47:20 +0100 Subject: [PATCH 241/407] Convert MemoryMapIterator to Option --- kernel/src/memory/MemoryMap.cpp | 6 +++--- kernel/src/memory/MemoryMap.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index cf83a67a..8743e83c 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -35,13 +35,13 @@ void MemoryMapIterator::rewind() m_cur_ent = 0; } -Result MemoryMapIterator::at(usize index) const +Option MemoryMapIterator::at(usize index) const { - if (index >= m_mmap_entries) return err(ERANGE); + if (index >= m_mmap_entries) return {}; return memory_map_entry_from_mmapent(m_base_ent + index); } -Result MemoryMapIterator::next() +Option MemoryMapIterator::next() { return at(m_cur_ent++); } diff --git a/kernel/src/memory/MemoryMap.h b/kernel/src/memory/MemoryMap.h index 4c53bde4..669b07aa 100644 --- a/kernel/src/memory/MemoryMap.h +++ b/kernel/src/memory/MemoryMap.h @@ -44,13 +44,13 @@ class MemoryMapIterator void rewind(); - Result next(); + Option next(); MemoryMapEntry largest_free(); MemoryMapEntry highest(); - Result at(usize index) const; + Option at(usize index) const; usize entries() const { From 4a6c59d519394549d305d8ec69500733d7e4beed Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 19:48:22 +0100 Subject: [PATCH 242/407] Make all methods in OwnedStringView const --- luna/include/luna/OwnedStringView.h | 6 +++--- luna/src/OwnedStringView.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/luna/include/luna/OwnedStringView.h b/luna/include/luna/OwnedStringView.h index 4dd59332..50e208b3 100644 --- a/luna/include/luna/OwnedStringView.h +++ b/luna/include/luna/OwnedStringView.h @@ -9,14 +9,14 @@ class OwnedStringView OwnedStringView(const OwnedStringView&) = delete; ~OwnedStringView(); - Result clone(); + Result clone() const; - const char* chars() + const char* chars() const { return m_string; } - usize length() + usize length() const { return m_length; } diff --git a/luna/src/OwnedStringView.cpp b/luna/src/OwnedStringView.cpp index d81a30cf..1bf1b4ec 100644 --- a/luna/src/OwnedStringView.cpp +++ b/luna/src/OwnedStringView.cpp @@ -26,7 +26,7 @@ OwnedStringView::~OwnedStringView() if (m_string) destroy_array(m_string); } -Result OwnedStringView::clone() +Result OwnedStringView::clone() const { char* buf = TRY(make_array(m_length + 1)); From 345e13965e226825603740facf23e1aeceaf0aec Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 20:27:44 +0100 Subject: [PATCH 243/407] Add missing include No one was noticing because everyone using OwnedStringView included Result.h before it --- luna/include/luna/OwnedStringView.h | 1 + 1 file changed, 1 insertion(+) diff --git a/luna/include/luna/OwnedStringView.h b/luna/include/luna/OwnedStringView.h index 50e208b3..91b78da2 100644 --- a/luna/include/luna/OwnedStringView.h +++ b/luna/include/luna/OwnedStringView.h @@ -1,4 +1,5 @@ #pragma once +#include class OwnedStringView { From e56075fb4684859ad2a78a2c314a230de4ba31ad Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 20:36:43 +0100 Subject: [PATCH 244/407] Use nothrow in raw_malloc --- luna/src/Alloc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luna/src/Alloc.cpp b/luna/src/Alloc.cpp index 105f4ac9..57ec3eb7 100644 --- a/luna/src/Alloc.cpp +++ b/luna/src/Alloc.cpp @@ -7,7 +7,7 @@ [[nodiscard]] void* raw_malloc(usize size) { #ifdef USE_FREESTANDING - char* const rc = new char[size]; + char* const rc = new (std::nothrow) char[size]; return (void*)rc; #else return malloc(size); From 42a2c2af49c9c0846ff844df1c7af3c3cce4a1b2 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 20:37:57 +0100 Subject: [PATCH 245/407] Add strdup() --- luna/include/luna/OwnedStringView.h | 6 ++++++ luna/include/luna/String.h | 2 ++ luna/src/OwnedStringView.cpp | 8 ++++---- luna/src/String.cpp | 13 +++++++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/luna/include/luna/OwnedStringView.h b/luna/include/luna/OwnedStringView.h index 91b78da2..b5ce7622 100644 --- a/luna/include/luna/OwnedStringView.h +++ b/luna/include/luna/OwnedStringView.h @@ -22,6 +22,12 @@ class OwnedStringView return m_length; } + const char& operator[](usize index) const + { + expect(index < m_length, "OwnedStringView: index out of range"); + return m_string[index]; + } + private: char* m_string{nullptr}; usize m_length{0}; diff --git a/luna/include/luna/String.h b/luna/include/luna/String.h index 0dddc00b..0eca451c 100644 --- a/luna/include/luna/String.h +++ b/luna/include/luna/String.h @@ -8,4 +8,6 @@ extern "C" int memcmp(const void* a, const void* b, usize n); void* memmove(void* dest, const void* src, usize n); usize strlen(const char* str); + + char* strdup(const char* str); } \ No newline at end of file diff --git a/luna/src/OwnedStringView.cpp b/luna/src/OwnedStringView.cpp index 1bf1b4ec..a904a7ca 100644 --- a/luna/src/OwnedStringView.cpp +++ b/luna/src/OwnedStringView.cpp @@ -23,14 +23,14 @@ OwnedStringView::OwnedStringView(char* c_str) OwnedStringView::~OwnedStringView() { - if (m_string) destroy_array(m_string); + if (m_string) raw_free(m_string); } Result OwnedStringView::clone() const { - char* buf = TRY(make_array(m_length + 1)); + char* const c_str = strdup(m_string); - memcpy(buf, m_string, m_length + 1); + if (!c_str) return err(ENOMEM); - return OwnedStringView{buf}; + return OwnedStringView{c_str}; } \ No newline at end of file diff --git a/luna/src/String.cpp b/luna/src/String.cpp index 85535188..70b71d4f 100644 --- a/luna/src/String.cpp +++ b/luna/src/String.cpp @@ -1,3 +1,4 @@ +#include #include extern "C" @@ -44,4 +45,16 @@ extern "C" ; return (usize)(i - str); } + + char* strdup(const char* str) + { + const usize len = strlen(str); + + char* dest = (char*)raw_malloc(len + 1); + if (!dest) return nullptr; + + memcpy(dest, str, len + 1); + + return dest; + } } \ No newline at end of file From 59765aa3344d4005147088e6c4767ee19fbba6a7 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 20:40:04 +0100 Subject: [PATCH 246/407] Rename String.h -> CString.h Let's not confuse String.h with a managed string class, it's in fact the equivalent of the C stdlib's --- kernel/src/arch/x86_64/CPU.cpp | 2 +- kernel/src/arch/x86_64/MMU.cpp | 2 +- kernel/src/arch/x86_64/Thread.cpp | 2 +- kernel/src/boot/Init.cpp | 2 +- kernel/src/memory/Heap.cpp | 2 +- kernel/src/memory/MemoryManager.cpp | 2 +- kernel/src/video/TextConsole.cpp | 2 +- luna/CMakeLists.txt | 2 +- luna/include/luna/{String.h => CString.h} | 0 luna/src/Bitmap.cpp | 2 +- luna/src/{String.cpp => CString.cpp} | 2 +- luna/src/OwnedStringView.cpp | 2 +- 12 files changed, 11 insertions(+), 11 deletions(-) rename luna/include/luna/{String.h => CString.h} (100%) rename luna/src/{String.cpp => CString.cpp} (98%) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 8654fe38..11043411 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -6,9 +6,9 @@ #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include +#include #include #include -#include #include #include diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 25edd6ff..3b927aa4 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -1,7 +1,7 @@ #include "arch/MMU.h" #include "memory/MemoryManager.h" +#include #include -#include #include #pragma GCC push_options diff --git a/kernel/src/arch/x86_64/Thread.cpp b/kernel/src/arch/x86_64/Thread.cpp index 4e1ffe86..b9b76d59 100644 --- a/kernel/src/arch/x86_64/Thread.cpp +++ b/kernel/src/arch/x86_64/Thread.cpp @@ -1,5 +1,5 @@ #include "thread/Thread.h" -#include +#include bool is_in_kernel(Registers* regs) { diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 64605a5b..0aba173e 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -4,8 +4,8 @@ #include "boot/bootboot.h" #include "memory/MemoryManager.h" #include "video/Framebuffer.h" +#include #include -#include extern const BOOTBOOT bootboot; diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index faea101d..90fd79f0 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -6,10 +6,10 @@ #include "memory/MemoryManager.h" #include #include +#include #include #include #include -#include #include namespace std diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 75db28db..6d335717 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -6,8 +6,8 @@ #include "memory/MemoryMap.h" #include #include +#include #include -#include #include #include diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index d3679350..8ef6ad59 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -1,9 +1,9 @@ #include "video/TextConsole.h" #include "boot/bootboot.h" #include "video/Framebuffer.h" +#include #include #include -#include #include extern const BOOTBOOT bootboot; diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 655dc333..53a8a28b 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -3,7 +3,7 @@ set(FREESTANDING_SOURCES src/Format.cpp src/NumberParsing.cpp - src/String.cpp + src/CString.cpp src/Units.cpp src/SystemError.cpp src/Bitmap.cpp diff --git a/luna/include/luna/String.h b/luna/include/luna/CString.h similarity index 100% rename from luna/include/luna/String.h rename to luna/include/luna/CString.h diff --git a/luna/src/Bitmap.cpp b/luna/src/Bitmap.cpp index 7fb5302b..35b2ea8d 100644 --- a/luna/src/Bitmap.cpp +++ b/luna/src/Bitmap.cpp @@ -1,6 +1,6 @@ #include +#include #include -#include Bitmap::Bitmap() { diff --git a/luna/src/String.cpp b/luna/src/CString.cpp similarity index 98% rename from luna/src/String.cpp rename to luna/src/CString.cpp index 70b71d4f..7942501a 100644 --- a/luna/src/String.cpp +++ b/luna/src/CString.cpp @@ -1,5 +1,5 @@ #include -#include +#include extern "C" { diff --git a/luna/src/OwnedStringView.cpp b/luna/src/OwnedStringView.cpp index a904a7ca..8ac2df4b 100644 --- a/luna/src/OwnedStringView.cpp +++ b/luna/src/OwnedStringView.cpp @@ -1,6 +1,6 @@ #include +#include #include -#include OwnedStringView::OwnedStringView() { From da39ba33a9c90a3fb35875b19e20b2afb9d47c20 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 20:48:58 +0100 Subject: [PATCH 247/407] Move OwnedStringView::operator[] out of line --- luna/include/luna/OwnedStringView.h | 6 +----- luna/src/OwnedStringView.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/luna/include/luna/OwnedStringView.h b/luna/include/luna/OwnedStringView.h index b5ce7622..8a47b597 100644 --- a/luna/include/luna/OwnedStringView.h +++ b/luna/include/luna/OwnedStringView.h @@ -22,11 +22,7 @@ class OwnedStringView return m_length; } - const char& operator[](usize index) const - { - expect(index < m_length, "OwnedStringView: index out of range"); - return m_string[index]; - } + const char& operator[](usize) const; private: char* m_string{nullptr}; diff --git a/luna/src/OwnedStringView.cpp b/luna/src/OwnedStringView.cpp index 8ac2df4b..80e42fa7 100644 --- a/luna/src/OwnedStringView.cpp +++ b/luna/src/OwnedStringView.cpp @@ -33,4 +33,10 @@ Result OwnedStringView::clone() const if (!c_str) return err(ENOMEM); return OwnedStringView{c_str}; +} + +const char& OwnedStringView::operator[](usize index) const +{ + expect(index < m_length, "index out of range"); + return m_string[index]; } \ No newline at end of file From b316e3b3b7a9fa9890e66f2b6218b5ba7190fdfe Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 20:49:09 +0100 Subject: [PATCH 248/407] Print stack trace on assertion fail --- kernel/src/Log.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index d26190b1..b9399326 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -118,10 +118,12 @@ static bool g_check_already_failed = false; [[noreturn]] bool __check_failed(const char* file, const char* line, const char* func, const char* expr) { + CPU::disable_interrupts(); if (!g_check_already_failed) { // Avoid endlessly failing when trying to report a failed check. g_check_already_failed = true; kerrorln("ERROR: Check failed at %s:%s, in %s: %s", file, line, func, expr); + CPU::print_stack_trace(); } CPU::efficient_halt(); } \ No newline at end of file From a16f357ab9d07df27df5b712392c985ba1b1cdd8 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 16 Dec 2022 21:15:22 +0100 Subject: [PATCH 249/407] Add an Atomic class --- luna/include/luna/Atomic.h | 108 +++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 luna/include/luna/Atomic.h diff --git a/luna/include/luna/Atomic.h b/luna/include/luna/Atomic.h new file mode 100644 index 00000000..d6be5f93 --- /dev/null +++ b/luna/include/luna/Atomic.h @@ -0,0 +1,108 @@ +#pragma once + +enum class MemoryOrder +{ + Relaxed = __ATOMIC_RELAXED, + Consume = __ATOMIC_CONSUME, + Acquire = __ATOMIC_ACQUIRE, + Release = __ATOMIC_RELEASE, + AcqRel = __ATOMIC_ACQ_REL, + SeqCst = __ATOMIC_SEQ_CST, +}; + +template class Atomic +{ + public: + Atomic() : m_value() + { + } + + Atomic(T value) : m_value(value) + { + } + + T operator=(T other) + { + store(other); + return other; + } + + T load(MemoryOrder order = MemoryOrder::SeqCst) const + { + return __atomic_load_n(&m_value, (int)order); + } + + operator T() const + { + return load(); + } + + void store(T value, MemoryOrder order = MemoryOrder::SeqCst) + { + return __atomic_store_n(&m_value, value, (int)order); + } + + T exchange(T value, MemoryOrder order = MemoryOrder::SeqCst) + { + return __atomic_exchange_n(&m_value, value, (int)order); + } + + bool compare_exchange_strong(T& expected, T desired, MemoryOrder success, MemoryOrder failure) + { + return __atomic_compare_exchange_n(&m_value, &expected, desired, false, (int)success, (int)failure); + } + + bool compare_exchange_strong(T& expected, T desired, MemoryOrder order = MemoryOrder::SeqCst) + { + MemoryOrder failure = (order == MemoryOrder::AcqRel) ? MemoryOrder::Acquire + : (order == MemoryOrder::Release) ? MemoryOrder::Relaxed + : order; + return __atomic_compare_exchange_n(&m_value, &expected, desired, false, (int)order, (int)failure); + } + + bool compare_exchange_weak(T& expected, T desired, MemoryOrder success, MemoryOrder failure) + { + return __atomic_compare_exchange_n(&m_value, &expected, desired, true, (int)success, (int)failure); + } + + bool compare_exchange_weak(T& expected, T desired, MemoryOrder order = MemoryOrder::SeqCst) + { + MemoryOrder failure = (order == MemoryOrder::AcqRel) ? MemoryOrder::Acquire + : (order == MemoryOrder::Release) ? MemoryOrder::Relaxed + : order; + return __atomic_compare_exchange_n(&m_value, &expected, desired, true, (int)order, (int)failure); + } + + T fetch_add(T other, MemoryOrder order = MemoryOrder::SeqCst) + { + return __atomic_fetch_add(&m_value, other, (int)order); + } + + T fetch_sub(T other, MemoryOrder order = MemoryOrder::SeqCst) + { + return __atomic_fetch_sub(&m_value, other, (int)order); + } + + T operator++() + { + return fetch_add(1) + 1; + } + + T operator++(int) + { + return fetch_add(1); + } + + T operator--() + { + return fetch_sub(1) - 1; + } + + T operator--(int) + { + return fetch_sub(1); + } + + private: + T m_value; +}; \ No newline at end of file From 9d6235e1092e57bee39fd5574398dd7184b9f6ed Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 10:45:55 +0100 Subject: [PATCH 250/407] CPU: Add a pause() method --- kernel/src/arch/CPU.h | 2 ++ kernel/src/arch/x86_64/CPU.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index edf51cba..1701057f 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -25,4 +25,6 @@ namespace CPU void print_stack_trace(); void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg); void print_stack_trace_at(Registers* regs); + + void pause(); } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 11043411..dd63b84d 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -506,6 +506,11 @@ namespace CPU }, &frame_index); } + + void pause() + { + asm volatile("pause"); + } } // called by kernel_yield From 14461c6fe8a7d7e8c7fd0b61fd3c4a534dc2cb35 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 10:49:19 +0100 Subject: [PATCH 251/407] Atomic: Add operators += and -= --- luna/include/luna/Atomic.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/luna/include/luna/Atomic.h b/luna/include/luna/Atomic.h index d6be5f93..8f2dd9ff 100644 --- a/luna/include/luna/Atomic.h +++ b/luna/include/luna/Atomic.h @@ -103,6 +103,16 @@ template class Atomic return fetch_sub(1); } + T operator+=(const T& other) + { + return fetch_add(other) + other; + } + + T operator-=(const T& other) + { + return fetch_sub(other) - other; + } + private: T m_value; }; \ No newline at end of file From 6e5d2b5335f6fce15115ff42ce6ca4c3b7beeaf6 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 10:50:49 +0100 Subject: [PATCH 252/407] Thread: Make g_next_id atomic --- kernel/src/main.cpp | 1 + kernel/src/thread/Thread.cpp | 8 +++++++- kernel/src/thread/Thread.h | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 05768089..1a45e8b3 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -49,6 +49,7 @@ Result init() kinfoln("Used memory: %s", to_dynamic_unit(MemoryManager::used()).release_value().chars()); kinfoln("Reserved memory: %s", to_dynamic_unit(MemoryManager::reserved()).release_value().chars()); + Thread::init(); Scheduler::init(); TRY(Scheduler::new_kernel_thread(async_thread)); diff --git a/kernel/src/thread/Thread.cpp b/kernel/src/thread/Thread.cpp index 5f834d6e..48540869 100644 --- a/kernel/src/thread/Thread.cpp +++ b/kernel/src/thread/Thread.cpp @@ -1,10 +1,16 @@ #include "thread/Thread.h" #include +#include -static u64 g_next_id = 1; +static Atomic g_next_id; DoublyLinkedList g_threads; +void Thread::init() +{ + g_next_id = 1; +} + Result new_thread() { Thread* thread = TRY(make()); diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 53e41a21..ad33d895 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -47,6 +47,8 @@ struct Thread : public DoublyLinkedListNode void set_sp(u64 sp); u64 sp(); + + static void init(); }; void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs); From f97515bd7ea7dc439adfc089e6a737ad16a0283e Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 10:52:40 +0100 Subject: [PATCH 253/407] Kernel: Add Spinlock and LockedValue --- kernel/CMakeLists.txt | 1 + kernel/src/thread/Spinlock.cpp | 22 +++++++++ kernel/src/thread/Spinlock.h | 86 ++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 kernel/src/thread/Spinlock.cpp create mode 100644 kernel/src/thread/Spinlock.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index f4a7e678..89c601ee 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -12,6 +12,7 @@ set(SOURCES src/boot/Init.cpp src/arch/Serial.cpp src/arch/Timer.cpp + src/thread/Spinlock.cpp src/thread/Thread.cpp src/thread/Scheduler.cpp ) diff --git a/kernel/src/thread/Spinlock.cpp b/kernel/src/thread/Spinlock.cpp new file mode 100644 index 00000000..7c70e08f --- /dev/null +++ b/kernel/src/thread/Spinlock.cpp @@ -0,0 +1,22 @@ +#include "thread/Spinlock.h" +#include "Log.h" +#include "arch/CPU.h" + +void Spinlock::lock() +{ + int expected = -1; + while (!m_lock.compare_exchange_strong(expected, 0)) + { + expected = -1; + CPU::pause(); + } +} + +void Spinlock::unlock() +{ + int expected = 0; + if (!m_lock.compare_exchange_strong(expected, -1)) + { + kwarnln("Spinlock::unlock() called on an unlocked lock with value %d", expected); + } +} \ No newline at end of file diff --git a/kernel/src/thread/Spinlock.h b/kernel/src/thread/Spinlock.h new file mode 100644 index 00000000..984b6ce3 --- /dev/null +++ b/kernel/src/thread/Spinlock.h @@ -0,0 +1,86 @@ +#pragma once +#include + +class Spinlock +{ + public: + void lock(); + void unlock(); + + bool is_locked() const + { + return m_lock.load() != -1; + } + + // Call this before use if the Spinlock is a global variable. + void init() + { + m_lock = -1; + } + + private: + Atomic m_lock{-1}; +}; + +template class LockedValue +{ + struct LockedValueGuard + { + LockedValueGuard(LockedValue& value_ref) : m_value_ref(value_ref) + { + } + + ~LockedValueGuard() + { + m_value_ref.m_lock.unlock(); + } + + T& ref() + { + return m_value_ref.m_value; + } + + void set(const T& other) + { + ref() = other; + } + + T* operator->() + { + return &ref(); + } + + T& operator*() + { + return ref(); + } + + private: + LockedValue& m_value_ref; + }; + + public: + LockedValue() : m_value() + { + } + + LockedValue(T value) : m_value(value) + { + } + + // Call this before use if the LockedValue is a global variable. + void init() + { + m_lock.init(); + } + + LockedValueGuard lock() + { + m_lock.lock(); + return {*this}; + } + + private: + T m_value; + Spinlock m_lock; +}; \ No newline at end of file From 132963070bafe5cb8167307d0f6e2e2971b8b851 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 10:53:49 +0100 Subject: [PATCH 254/407] MemoryManager: Make some variables atomic and the frame bitmap a LockedValue --- kernel/src/memory/MemoryManager.cpp | 71 +++++++++++++++++------------ 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 6d335717..738df21b 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -4,6 +4,7 @@ #include "arch/MMU.h" #include "memory/KernelVM.h" #include "memory/MemoryMap.h" +#include "thread/Spinlock.h" #include #include #include @@ -16,13 +17,13 @@ extern const u8 end_of_kernel_rodata[1]; extern const u8 start_of_kernel_data[1]; extern const u8 end_of_kernel_data[1]; -static usize free_mem = 0; -static usize used_mem = 0; -static usize reserved_mem = 0; +static Atomic free_mem; +static Atomic used_mem; +static Atomic reserved_mem; -static u64 start_index = 0; +static Atomic start_index; -static Bitmap g_frame_bitmap; +static LockedValue g_frame_bitmap; #define CHECK_PAGE_ALIGNED(address) expect(is_aligned(address), "Address is not page-aligned") @@ -55,6 +56,8 @@ namespace MemoryManager MemoryMapIterator iter; MemoryMapEntry entry; + g_frame_bitmap.init(); + const auto largest_free_entry = iter.largest_free(); expect(largest_free_entry.is_free(), "We were given a largest free memory region that isn't even free!"); @@ -74,20 +77,24 @@ namespace MemoryManager expect(frame_bitmap_size < largest_free_entry.size(), "No single memory region is enough to hold the frame bitmap"); - g_frame_bitmap.initialize(frame_bitmap_addr, frame_bitmap_size); - - g_frame_bitmap.clear(true); // Set all pages to used/reserved by default, then clear out the free ones - - iter.rewind(); - while (iter.next().try_set_value(entry)) { - const u64 index = entry.address() / ARCH_PAGE_SIZE; - const usize pages = entry.size() / ARCH_PAGE_SIZE; - if (!entry.is_free()) { reserved_mem += entry.size(); } - else + auto frame_bitmap = g_frame_bitmap.lock(); + + frame_bitmap->initialize(frame_bitmap_addr, frame_bitmap_size); + + frame_bitmap->clear(true); // Set all pages to used/reserved by default, then clear out the free ones + + iter.rewind(); + while (iter.next().try_set_value(entry)) { - free_mem += entry.size(); - g_frame_bitmap.clear_region(index, pages, false); + const u64 index = entry.address() / ARCH_PAGE_SIZE; + const usize pages = entry.size() / ARCH_PAGE_SIZE; + if (!entry.is_free()) { reserved_mem += entry.size(); } + else + { + free_mem += entry.size(); + frame_bitmap->clear_region(index, pages, false); + } } } @@ -103,23 +110,27 @@ namespace MemoryManager // NOTE: We force these operations to succeed, because if we can't map the frame bitmap to virtual memory // there's no point in continuing. - auto bitmap_pages = g_frame_bitmap.size_in_bytes() / ARCH_PAGE_SIZE; + auto bitmap_pages = g_frame_bitmap.lock()->size_in_bytes() / ARCH_PAGE_SIZE; auto virtual_bitmap_base = KernelVM::alloc_several_pages(bitmap_pages) .expect_value("Unable to allocate virtual memory for the physical frame bitmap, cannot continue"); - map_frames_at(virtual_bitmap_base, (u64)g_frame_bitmap.location(), bitmap_pages, - MMU::ReadWrite | MMU::NoExecute) + + u64 phys = (u64)g_frame_bitmap.lock()->location(); + map_frames_at(virtual_bitmap_base, phys, bitmap_pages, MMU::ReadWrite | MMU::NoExecute) .expect_value("Unable to map the physical frame bitmap to virtual memory, cannot continue"); - g_frame_bitmap.initialize((void*)virtual_bitmap_base, g_frame_bitmap.size_in_bytes()); + auto frame_bitmap = g_frame_bitmap.lock(); + + frame_bitmap->initialize((void*)virtual_bitmap_base, frame_bitmap->size_in_bytes()); } void lock_frame(u64 frame) { const u64 index = frame / ARCH_PAGE_SIZE; - if (g_frame_bitmap.get(index)) return; - g_frame_bitmap.set(index, true); + auto frame_bitmap = g_frame_bitmap.lock(); + if (frame_bitmap->get(index)) return; + frame_bitmap->set(index, true); used_mem += ARCH_PAGE_SIZE; free_mem -= ARCH_PAGE_SIZE; } @@ -131,10 +142,11 @@ namespace MemoryManager Result alloc_frame() { - for (u64 index = start_index; index < g_frame_bitmap.size(); index++) + auto frame_bitmap = g_frame_bitmap.lock(); + for (u64 index = start_index; index < frame_bitmap->size(); index++) { - if (g_frame_bitmap.get(index)) continue; - g_frame_bitmap.set(index, true); + if (frame_bitmap->get(index)) continue; + frame_bitmap->set(index, true); start_index = index + 1; free_mem -= ARCH_PAGE_SIZE; used_mem += ARCH_PAGE_SIZE; @@ -147,9 +159,10 @@ namespace MemoryManager Result free_frame(u64 frame) { const u64 index = frame / ARCH_PAGE_SIZE; - if (index > g_frame_bitmap.size()) return err(EFAULT); - if (!g_frame_bitmap.get(index)) return err(EFAULT); - g_frame_bitmap.set(index, false); + auto frame_bitmap = g_frame_bitmap.lock(); + if (index > frame_bitmap->size()) return err(EFAULT); + if (!frame_bitmap->get(index)) return err(EFAULT); + frame_bitmap->set(index, false); used_mem -= ARCH_PAGE_SIZE; free_mem += ARCH_PAGE_SIZE; if (start_index > index) start_index = index; From df9a13cbfb47fd0b25bfafd4b162ef11ee60966e Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 10:54:09 +0100 Subject: [PATCH 255/407] KernelVM: Make g_used_vm atomic and g_kernelvm_bitmap a LockedValue --- kernel/src/memory/KernelVM.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/kernel/src/memory/KernelVM.cpp b/kernel/src/memory/KernelVM.cpp index dbb4eb85..9506f53d 100644 --- a/kernel/src/memory/KernelVM.cpp +++ b/kernel/src/memory/KernelVM.cpp @@ -1,10 +1,11 @@ #include "memory/KernelVM.h" #include "arch/MMU.h" +#include "thread/Spinlock.h" #include static const u64 KERNEL_VM_RANGE_START = 0xfffffffff0000000; -static Bitmap g_kernelvm_bitmap; +static LockedValue g_kernelvm_bitmap; static u8 bitmap_memory[4096]; @@ -14,22 +15,26 @@ static const u64 KERNEL_VM_RANGE_END = KERNEL_VM_RANGE_SIZE + KERNEL_VM_RANGE_ST static_assert(KERNEL_VM_RANGE_END == 0xfffffffff8000000); -static usize g_used_vm; +static Atomic g_used_vm; namespace KernelVM { void init() { - g_kernelvm_bitmap.initialize(bitmap_memory, sizeof(bitmap_memory)); - g_kernelvm_bitmap.clear(false); + g_kernelvm_bitmap.init(); + + auto kernelvm_bitmap = g_kernelvm_bitmap.lock(); + kernelvm_bitmap->initialize(bitmap_memory, sizeof(bitmap_memory)); + kernelvm_bitmap->clear(false); } Result alloc_one_page() { - for (u64 index = 0; index < g_kernelvm_bitmap.size(); index++) + auto kernelvm_bitmap = g_kernelvm_bitmap.lock(); + for (u64 index = 0; index < kernelvm_bitmap->size(); index++) { - if (g_kernelvm_bitmap.get(index)) continue; - g_kernelvm_bitmap.set(index, true); + if (kernelvm_bitmap->get(index)) continue; + kernelvm_bitmap->set(index, true); g_used_vm += ARCH_PAGE_SIZE; return KERNEL_VM_RANGE_START + (index * ARCH_PAGE_SIZE); } @@ -41,9 +46,10 @@ namespace KernelVM { u64 first_free_index = 0; u64 free_contiguous_pages = 0; - for (u64 index = 0; index < g_kernelvm_bitmap.size(); index++) + auto kernelvm_bitmap = g_kernelvm_bitmap.lock(); + for (u64 index = 0; index < kernelvm_bitmap->size(); index++) { - if (g_kernelvm_bitmap.get(index)) + if (kernelvm_bitmap->get(index)) { free_contiguous_pages = 0; continue; @@ -70,7 +76,7 @@ namespace KernelVM u64 start_index; if (find_several_pages_impl(count, start_index)) { - g_kernelvm_bitmap.clear_region(start_index, count, true); + g_kernelvm_bitmap.lock()->clear_region(start_index, count, true); g_used_vm += ARCH_PAGE_SIZE * count; return KERNEL_VM_RANGE_START + (start_index * ARCH_PAGE_SIZE); } @@ -84,9 +90,11 @@ namespace KernelVM u64 index = (address - KERNEL_VM_RANGE_START) / ARCH_PAGE_SIZE; - if (index >= g_kernelvm_bitmap.size()) return err(EFAULT); + auto kernelvm_bitmap = g_kernelvm_bitmap.lock(); - g_kernelvm_bitmap.set(index, false); + if (index >= kernelvm_bitmap->size()) return err(EFAULT); + + kernelvm_bitmap->set(index, false); g_used_vm -= ARCH_PAGE_SIZE; return {}; @@ -99,7 +107,7 @@ namespace KernelVM u64 index = (address - KERNEL_VM_RANGE_START) / ARCH_PAGE_SIZE; - g_kernelvm_bitmap.clear_region(index, count, false); + g_kernelvm_bitmap.lock()->clear_region(index, count, false); g_used_vm -= ARCH_PAGE_SIZE * count; return {}; From cf3b2176f097d84a31051f33df405ee677bf84d8 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 11:36:16 +0100 Subject: [PATCH 256/407] Implement OwnedStringView::from_string_literal --- luna/include/luna/OwnedStringView.h | 2 ++ luna/src/OwnedStringView.cpp | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/luna/include/luna/OwnedStringView.h b/luna/include/luna/OwnedStringView.h index 8a47b597..ba457b58 100644 --- a/luna/include/luna/OwnedStringView.h +++ b/luna/include/luna/OwnedStringView.h @@ -12,6 +12,8 @@ class OwnedStringView Result clone() const; + static Result from_string_literal(const char* str); + const char* chars() const { return m_string; diff --git a/luna/src/OwnedStringView.cpp b/luna/src/OwnedStringView.cpp index 80e42fa7..0bf41af3 100644 --- a/luna/src/OwnedStringView.cpp +++ b/luna/src/OwnedStringView.cpp @@ -39,4 +39,11 @@ const char& OwnedStringView::operator[](usize index) const { expect(index < m_length, "index out of range"); return m_string[index]; +} + +Result OwnedStringView::from_string_literal(const char* str) +{ + char* dup = strdup(str); + if (!dup) return err(ENOMEM); + return OwnedStringView{dup}; } \ No newline at end of file From 48fcb8734acfd058f9f4a2983950e45bc3fe5bed Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 12:12:58 +0100 Subject: [PATCH 257/407] Give number parsing functions more meaningful names --- luna/include/luna/NumberParsing.h | 8 ++++---- luna/src/Format.cpp | 4 ++-- luna/src/NumberParsing.cpp | 17 +++++++++-------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/luna/include/luna/NumberParsing.h b/luna/include/luna/NumberParsing.h index 774250a1..f4a709aa 100644 --- a/luna/include/luna/NumberParsing.h +++ b/luna/include/luna/NumberParsing.h @@ -1,7 +1,7 @@ #pragma once #include -usize _atou(const char** str); -isize _atos(const char** str); -usize _strtou(const char* str, const char** endptr, int base); -isize _strtoi(const char* str, const char** endptr, int base); +usize scan_unsigned_integer(const char** str); +isize scan_signed_integer(const char** str); +usize parse_unsigned_integer(const char* str, const char** endptr, int base); +isize parse_signed_integer(const char* str, const char** endptr, int base); diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index b10754be..8a6a9c51 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -107,7 +107,7 @@ static usize parse_width(const char** format, flags_t& flags, va_list ap) { usize result = 0; - if (_isdigit(**format)) result = _atou(format); + if (_isdigit(**format)) result = scan_unsigned_integer(format); else if (**format == '*') { const int width = va_arg(ap, int); @@ -132,7 +132,7 @@ static usize parse_precision(const char** format, flags_t& flags, va_list ap) flags |= FLAG_USE_PRECISION; - if (_isdigit(**format)) result = _atou(format); + if (_isdigit(**format)) result = scan_unsigned_integer(format); else if (**format == '*') { const int precision = va_arg(ap, int); diff --git a/luna/src/NumberParsing.cpp b/luna/src/NumberParsing.cpp index dd3d6df7..1f4c7680 100644 --- a/luna/src/NumberParsing.cpp +++ b/luna/src/NumberParsing.cpp @@ -16,7 +16,7 @@ static bool is_valid_digit_for_base(int base, char c) return true; } -usize _strtou(const char* str, const char** endptr, int base) +usize parse_unsigned_integer(const char* str, const char** endptr, int base) { usize val = 0; @@ -47,7 +47,7 @@ usize _strtou(const char* str, const char** endptr, int base) return val; } -isize _strtoi(const char* str, const char** endptr, int base) +isize parse_signed_integer(const char* str, const char** endptr, int base) { bool negative = false; @@ -59,18 +59,19 @@ isize _strtoi(const char* str, const char** endptr, int base) str++; } - usize rc = _strtou(str, endptr, - base); // FIXME: Check for overflow (the unsigned usize value might not fit into a signed isize) + usize rc = parse_unsigned_integer( + str, endptr, + base); // FIXME: Check for overflow (the unsigned usize value might not fit into a signed isize) return negative ? -(isize)rc : (isize)rc; } -usize _atou(const char** str) +usize scan_unsigned_integer(const char** str) { - return _strtou(*str, str, 10); + return parse_unsigned_integer(*str, str, 10); } -isize _atos(const char** str) +isize scan_signed_integer(const char** str) { - return _strtoi(*str, str, 10); + return parse_signed_integer(*str, str, 10); } From abbed13f27d5cb1f310e71d2a44be519efe616aa Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 12:38:22 +0100 Subject: [PATCH 258/407] Add a 'pure' variant of cstyle_format which is infallible If we cannot fail to output, it doesn't make sense to propagate errors. So if you're SURE there are no errors, use pure_cstyle_format(). If, however, output can fail, use cstyle_format(). This has a drawback of adding quite a bit of code duplication to Format.cpp. Some of it is dealt using templates, but some code still remains duplicate. --- kernel/src/Log.cpp | 20 +-- kernel/src/arch/Serial.cpp | 10 +- kernel/src/video/TextConsole.cpp | 10 +- luna/include/luna/Format.h | 2 + luna/src/Format.cpp | 249 +++++++++++++++++++++++++++---- 5 files changed, 226 insertions(+), 65 deletions(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index b9399326..005dcef3 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -26,14 +26,8 @@ static void log_serial(LogLevel level, const char* format, va_list origin) Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000)); - cstyle_format( - format, - [](char c, void*) -> Result { - Serial::putchar((u8)c); - return {}; - }, - nullptr, ap) - .expect_value("Sanity check failed in log_serial: Should never fail"); + pure_cstyle_format( + format, [](char c, void*) { Serial::putchar((u8)c); }, nullptr, ap); Serial::putchar('\n'); @@ -56,14 +50,8 @@ static void log_text_console(LogLevel level, const char* format, va_list origin) else TextConsole::set_foreground(WHITE); - cstyle_format( - format, - [](char c, void*) -> Result { - TextConsole::putchar(c); - return {}; - }, - nullptr, ap) - .expect_value("Sanity check failed in log_text_console: Should never fail"); + pure_cstyle_format( + format, [](char c, void*) { TextConsole::putchar(c); }, nullptr, ap); TextConsole::putchar('\n'); diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index ce12ddae..8bedd13c 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -25,14 +25,8 @@ namespace Serial { va_list ap; va_start(ap, format); - auto rc = cstyle_format( - format, - [](char c, void*) -> Result { - putchar((u8)c); - return {}; - }, - nullptr, ap) - .expect_value("Sanity check failed in Serial::printf: Should never fail"); + auto rc = pure_cstyle_format( + format, [](char c, void*) { putchar((u8)c); }, nullptr, ap); va_end(ap); return rc; } diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index 8ef6ad59..62928c70 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -161,14 +161,8 @@ namespace TextConsole { va_list ap; va_start(ap, format); - auto rc = cstyle_format( - format, - [](char c, void*) -> Result { - putchar(c); - return {}; - }, - nullptr, ap) - .expect_value("Sanity check failed in TextConsole::printf: Should never fail"); + auto rc = pure_cstyle_format( + format, [](char c, void*) { putchar(c); }, nullptr, ap); va_end(ap); return rc; } diff --git a/luna/include/luna/Format.h b/luna/include/luna/Format.h index fc3a4610..c44218d7 100644 --- a/luna/include/luna/Format.h +++ b/luna/include/luna/Format.h @@ -4,7 +4,9 @@ #include typedef Result (*callback_t)(char, void*); +typedef void (*pure_callback_t)(char, void*); Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); +usize pure_cstyle_format(const char* format, pure_callback_t callback, void* arg, va_list ap); usize vstring_format(char* buf, usize max, const char* format, va_list ap); usize string_format(char* buf, usize max, const char* format, ...); \ No newline at end of file diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index 8a6a9c51..ff936a24 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -26,6 +26,13 @@ struct format_state void* arg; }; +struct pure_format_state +{ + usize count; + pure_callback_t callback; + void* arg; +}; + struct conv_state { flags_t flags; @@ -39,6 +46,12 @@ static Result format_putchar(char c, format_state& state) return state.callback(c, state.arg); } +static void pure_format_putchar(char c, pure_format_state& state) +{ + state.count++; + return state.callback(c, state.arg); +} + static Result format_puts(const char* s, format_state& state) { while (*s) @@ -50,6 +63,15 @@ static Result format_puts(const char* s, format_state& state) return {}; } +static void pure_format_puts(const char* s, pure_format_state& state) +{ + while (*s) + { + pure_format_putchar(*s, state); + s++; + } +} + static Result start_pad(const conv_state& vstate, format_state& state, usize start) { if (!(vstate.flags & FLAG_LEFT_ALIGN)) @@ -60,6 +82,14 @@ static Result start_pad(const conv_state& vstate, format_state& state, usi return {}; } +static void pure_start_pad(const conv_state& vstate, pure_format_state& state, usize start) +{ + if (!(vstate.flags & FLAG_LEFT_ALIGN)) + { + while (start++ < vstate.width) pure_format_putchar(' ', state); + } +} + static Result end_pad(const conv_state& vstate, format_state& state, usize start) { if (vstate.flags & FLAG_LEFT_ALIGN) @@ -70,6 +100,14 @@ static Result end_pad(const conv_state& vstate, format_state& state, usize return {}; } +static void pure_end_pad(const conv_state& vstate, pure_format_state& state, usize start) +{ + if (vstate.flags & FLAG_LEFT_ALIGN) + { + while (start++ < vstate.width) pure_format_putchar(' ', state); + } +} + static flags_t parse_flags(const char** format) { flags_t result = 0; @@ -203,7 +241,34 @@ static usize to_string(usize value, usize base, char* buf, usize max, bool upper return i; } -static Result output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) +static Result output_integer_data(conv_state& vstate, format_state& state, char* buf, usize len) +{ + if (!(vstate.flags & FLAG_ZERO_PAD)) TRY(start_pad(vstate, state, len)); + + usize i = len; + + while (i--) TRY(format_putchar(buf[i], state)); + + TRY(end_pad(vstate, state, len)); + + return {}; +} + +static void output_pure_integer_data(conv_state& vstate, pure_format_state& state, char* buf, usize len) +{ + if (!(vstate.flags & FLAG_ZERO_PAD)) pure_start_pad(vstate, state, len); + + usize i = len; + + while (i--) pure_format_putchar(buf[i], state); + + pure_end_pad(vstate, state, len); +} + +template +static ReturnType output_integer_generic(char specifier, conv_state& vstate, FormatStateType& state, usize value, + bool negative, + ReturnType (*output_data)(conv_state&, FormatStateType&, char*, usize)) { usize base = 10; bool uppercase = false; @@ -260,18 +325,27 @@ static Result output_integer(char specifier, conv_state& vstate, format_st buf[buflen++] = ' '; } - if (!(vstate.flags & FLAG_ZERO_PAD)) TRY(start_pad(vstate, state, buflen)); - - usize i = buflen; - - while (i--) TRY(format_putchar(buf[i], state)); - - TRY(end_pad(vstate, state, buflen)); - - return {}; + return output_data(vstate, state, buf, buflen); } -static Result va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) +static Result output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) +{ + return output_integer_generic, format_state>(specifier, vstate, state, value, negative, + output_integer_data); +} + +static void pure_output_integer(char specifier, conv_state& vstate, pure_format_state& state, usize value, + bool negative) +{ + return output_integer_generic(specifier, vstate, state, value, negative, + output_pure_integer_data); +} + +template +static ReturnType va_generic_output_integer(char specifier, conv_state& vstate, FormatStateType& state, + ReturnType (*integer_output)(char, conv_state&, FormatStateType&, usize, + bool), + va_list ap) { bool is_signed = false; bool negative = false; @@ -290,12 +364,12 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, (unsigned char)v, negative); + return integer_output(specifier, vstate, state, (unsigned char)v, negative); } else { const unsigned char v = (unsigned char)va_arg(ap, unsigned int); - return output_integer(specifier, vstate, state, v, false); + return integer_output(specifier, vstate, state, v, false); } } else if (vstate.flags & FLAG_SHORT) @@ -308,12 +382,12 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, (unsigned short)v, negative); + return integer_output(specifier, vstate, state, (unsigned short)v, negative); } else { const unsigned short v = (unsigned short)va_arg(ap, unsigned int); - return output_integer(specifier, vstate, state, v, false); + return integer_output(specifier, vstate, state, v, false); } } else if (vstate.flags & FLAG_LONG_LONG) @@ -326,12 +400,12 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, (unsigned long long)v, negative); + return integer_output(specifier, vstate, state, (unsigned long long)v, negative); } else { const unsigned long long v = va_arg(ap, unsigned long long); - return output_integer(specifier, vstate, state, v, false); + return integer_output(specifier, vstate, state, v, false); } } else if (vstate.flags & FLAG_LONG) @@ -344,12 +418,12 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, (unsigned long)v, negative); + return integer_output(specifier, vstate, state, (unsigned long)v, negative); } else { const unsigned long v = va_arg(ap, unsigned long); - return output_integer(specifier, vstate, state, v, false); + return integer_output(specifier, vstate, state, v, false); } } else @@ -362,16 +436,26 @@ static Result va_output_integer(char specifier, conv_state& vstate, format v = -v; negative = true; } - return output_integer(specifier, vstate, state, (unsigned int)v, negative); + return integer_output(specifier, vstate, state, (unsigned int)v, negative); } else { const unsigned int v = va_arg(ap, unsigned int); - return output_integer(specifier, vstate, state, v, false); + return integer_output(specifier, vstate, state, v, false); } } } +static Result va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) +{ + return va_generic_output_integer, format_state>(specifier, vstate, state, output_integer, ap); +} + +static void va_pure_output_integer(char specifier, conv_state& vstate, pure_format_state& state, va_list ap) +{ + return va_generic_output_integer(specifier, vstate, state, pure_output_integer, ap); +} + Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap) { format_state state; @@ -472,6 +556,106 @@ Result cstyle_format(const char* format, callback_t callback, void* arg, return state.count; } +usize pure_cstyle_format(const char* format, pure_callback_t callback, void* arg, va_list ap) +{ + pure_format_state state; + state.callback = callback; + state.arg = arg; + state.count = 0; + + while (*format) + { + if (*format != '%') + { + pure_format_putchar(*format, state); + format++; + continue; + } + + format++; + + if (*format == '%') + { + pure_format_putchar('%', state); + continue; + } + + // %[flags][width][.precision][length]conversion + + flags_t flags = parse_flags(&format); + const usize width = parse_width(&format, flags, ap); + usize precision = parse_precision(&format, flags, ap); + parse_length(&format, flags); + + conv_state vstate = {flags, width, precision}; + + const char specifier = *format; + format++; + + if (is_integer_format_specifier(specifier)) + { + va_pure_output_integer(specifier, vstate, state, ap); + continue; + } + else if (specifier == 'p') + { + const void* ptr = va_arg(ap, void*); + if (ptr == nullptr) + { + pure_start_pad(vstate, state, 5); + pure_format_puts("(nil)", state); + pure_end_pad(vstate, state, 5); + continue; + } + vstate.width = (sizeof(void*) * 2) + 2; + vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE); + pure_output_integer('p', vstate, state, (usize)ptr, false); + continue; + } + else if (specifier == 'c') + { + const char c = (char)va_arg(ap, int); + + pure_start_pad(vstate, state, 1); + pure_format_putchar(c, state); + pure_end_pad(vstate, state, 1); + + continue; + } + else if (specifier == 's') + { + const char* str = va_arg(ap, const char*); + if (str == nullptr) + { + pure_start_pad(vstate, state, 6); + pure_format_puts("(null)", state); + pure_end_pad(vstate, state, 6); + continue; + } + else + { + usize len = strlen(str); + + bool use_precision = (flags & FLAG_USE_PRECISION); + if (use_precision && len > precision) len = precision; + + pure_start_pad(vstate, state, len); + while (*str && (!use_precision || precision)) + { + pure_format_putchar(*str, state); + precision--; + str++; + } + pure_end_pad(vstate, state, len); + continue; + } + } + else { continue; } + } + + return state.count; +} + struct StringFormatInfo { char* buffer; @@ -482,18 +666,17 @@ usize vstring_format(char* buf, usize max, const char* format, va_list ap) { StringFormatInfo info = {.buffer = buf, .remaining = max - 1}; - usize result = cstyle_format( - format, - [](char c, void* arg) -> Result { - StringFormatInfo* info_arg = (StringFormatInfo*)arg; - if (!info_arg->remaining) return {}; - *(info_arg->buffer) = c; - info_arg->buffer++; - info_arg->remaining--; - return {}; - }, - &info, ap) - .expect_value("Sanity check failed in vstring_format: Should never fail"); + usize result = pure_cstyle_format( + format, + [](char c, void* arg) { + StringFormatInfo* info_arg = (StringFormatInfo*)arg; + if (!info_arg->remaining) return; + *(info_arg->buffer) = c; + info_arg->buffer++; + info_arg->remaining--; + return; + }, + &info, ap); *(info.buffer) = 0; From 16e00bada0feb77fa95e3c8d596ab8131cac633c Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 12:43:29 +0100 Subject: [PATCH 259/407] Add comments to Format.h --- luna/include/luna/Format.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/luna/include/luna/Format.h b/luna/include/luna/Format.h index c44218d7..28ffd1cd 100644 --- a/luna/include/luna/Format.h +++ b/luna/include/luna/Format.h @@ -6,7 +6,14 @@ typedef Result (*callback_t)(char, void*); typedef void (*pure_callback_t)(char, void*); +// Used to format anything that can fail (writing to C FILEs, etc...) Result cstyle_format(const char* format, callback_t callback, void* arg, va_list ap); + +// Used to format anything that cannot fail (formatting to a string, writing to the serial port (kernel-only)) usize pure_cstyle_format(const char* format, pure_callback_t callback, void* arg, va_list ap); + +// Convenience function which outputs into a fixed-size buffer (not unlike vsnprintf) usize vstring_format(char* buf, usize max, const char* format, va_list ap); + +// Convenience function which outputs into a fixed-size buffer (not unlike snprintf) usize string_format(char* buf, usize max, const char* format, ...); \ No newline at end of file From 16954695dd6ebdba379c4d5bdfafa5e67e3c8971 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 12:45:26 +0100 Subject: [PATCH 260/407] Tell the compiler that string_format is a printf-style function --- luna/include/luna/Format.h | 2 +- luna/src/Units.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/luna/include/luna/Format.h b/luna/include/luna/Format.h index 28ffd1cd..6607e4d5 100644 --- a/luna/include/luna/Format.h +++ b/luna/include/luna/Format.h @@ -16,4 +16,4 @@ usize pure_cstyle_format(const char* format, pure_callback_t callback, void* arg usize vstring_format(char* buf, usize max, const char* format, va_list ap); // Convenience function which outputs into a fixed-size buffer (not unlike snprintf) -usize string_format(char* buf, usize max, const char* format, ...); \ No newline at end of file +usize string_format(char* buf, usize max, const char* format, ...) _format(3, 4); \ No newline at end of file diff --git a/luna/src/Units.cpp b/luna/src/Units.cpp index 85a73900..05afd720 100644 --- a/luna/src/Units.cpp +++ b/luna/src/Units.cpp @@ -6,7 +6,7 @@ usize to_dynamic_unit_cstr(usize value, char* buffer, usize max) { - if (value < 1024) { return string_format(buffer, max, "%u bytes", value); } + if (value < 1024) { return string_format(buffer, max, "%zu bytes", value); } const char* unit_prefixes = "KMGTPE"; while (value > (1024 * 1024)) @@ -15,7 +15,7 @@ usize to_dynamic_unit_cstr(usize value, char* buffer, usize max) unit_prefixes++; } - return string_format(buffer, max, "%u.%u %ciB", value / 1024, (value % 1024) / 103, *unit_prefixes); + return string_format(buffer, max, "%zu.%zu %ciB", value / 1024, (value % 1024) / 103, *unit_prefixes); } Result to_dynamic_unit(usize value) From f77126768fd9c992139171043ff48b56773b93a5 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 13:48:22 +0100 Subject: [PATCH 261/407] Improve message --- kernel/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 1a45e8b3..1535bed2 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -30,7 +30,7 @@ void heap_thread() { CPU::disable_interrupts(); dump_heap_usage(); - kdbgln("uses %lu vm pages", KernelVM::used() / ARCH_PAGE_SIZE); + kdbgln("Kernel uses %lu vm pages", KernelVM::used() / ARCH_PAGE_SIZE); while (true) kernel_sleep(UINT64_MAX); } From 2cbc9fa3850a569a0844d92c8b4897646a2c53b3 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 13:48:55 +0100 Subject: [PATCH 262/407] Add some nice TypeTraits --- luna/include/luna/TypeTraits.h | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 luna/include/luna/TypeTraits.h diff --git a/luna/include/luna/TypeTraits.h b/luna/include/luna/TypeTraits.h new file mode 100644 index 00000000..b9c6309c --- /dev/null +++ b/luna/include/luna/TypeTraits.h @@ -0,0 +1,4 @@ +#pragma once + +template inline constexpr bool IsBaseOf = __is_base_of(Base, Derived); +template inline constexpr bool IsPowerOfTwo = (value & (value - 1)) == 0; \ No newline at end of file From ace674e518c18a7a48e0daf5641d4006c8f37dca Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 13:49:47 +0100 Subject: [PATCH 263/407] LinkedList: Make sure the contained type inherits from DoublyLinkedListNode --- luna/include/luna/LinkedList.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 47a07cbf..80c9b240 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -1,5 +1,6 @@ #pragma once #include +#include template inline Option nonnull_or_error(T* ptr) { @@ -57,6 +58,8 @@ template class DoublyLinkedList { using Node = DoublyLinkedListNode; + static_assert(IsBaseOf, T>); + public: void append(T* ptr) { From acb0ab1cd7796457b9d2931dfc32976851dc91a0 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 13:50:27 +0100 Subject: [PATCH 264/407] Use TypeTraits in Alignment.h to make static assertions more readable --- luna/include/luna/Alignment.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/luna/include/luna/Alignment.h b/luna/include/luna/Alignment.h index 90fa632a..02e04d92 100644 --- a/luna/include/luna/Alignment.h +++ b/luna/include/luna/Alignment.h @@ -1,9 +1,10 @@ #pragma once +#include // Must ALWAYS be called with a power of two as alignment. template constexpr T is_aligned(T value) { - static_assert((alignment & (alignment - 1)) == 0); + static_assert(IsPowerOfTwo); return (value % alignment == 0); } @@ -14,7 +15,7 @@ static_assert(is_aligned<4096>(40960u)); // Must ALWAYS be called with a power of two as alignment. template constexpr T align_down(T value) { - static_assert((alignment & (alignment - 1)) == 0); + static_assert(IsPowerOfTwo); return value - value % alignment; } From 59c9d8f1193628c28c1a77588816546c1ddeb9bf Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 14:32:24 +0100 Subject: [PATCH 265/407] asm -> asm volatile --- kernel/src/arch/x86_64/CPU.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index dd63b84d..0338fd96 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -288,7 +288,7 @@ static void setup_idt() static IDTR idtr; idtr.limit = 0x0FFF; idtr.offset = (u64)idt; - asm("lidt %0" : : "m"(idtr)); + asm volatile("lidt %0" : : "m"(idtr)); } // Interrupt handling From 97cb57d52157d76b117a607b45fec03ea41c2dcf Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 14:42:56 +0100 Subject: [PATCH 266/407] Check for overflow/underflow in parse_signed_integer --- luna/src/NumberParsing.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/luna/src/NumberParsing.cpp b/luna/src/NumberParsing.cpp index 1f4c7680..0938c06b 100644 --- a/luna/src/NumberParsing.cpp +++ b/luna/src/NumberParsing.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -47,6 +48,9 @@ usize parse_unsigned_integer(const char* str, const char** endptr, int base) return val; } +#define SSIZE_MAX LONG_MAX +#define SSIZE_MIN (-SSIZE_MAX - (isize)1) + isize parse_signed_integer(const char* str, const char** endptr, int base) { bool negative = false; @@ -59,9 +63,9 @@ isize parse_signed_integer(const char* str, const char** endptr, int base) str++; } - usize rc = parse_unsigned_integer( - str, endptr, - base); // FIXME: Check for overflow (the unsigned usize value might not fit into a signed isize) + usize rc = parse_unsigned_integer(str, endptr, base); + + if (rc > SSIZE_MAX) { return negative ? SSIZE_MIN : SSIZE_MAX; } return negative ? -(isize)rc : (isize)rc; } From ee6387e7b5c99b27a4ce883c437c3da0b6843b5a Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:00:19 +0100 Subject: [PATCH 267/407] Refactor NumberParsing.cpp + a lot of comments --- luna/include/luna/NumberParsing.h | 9 ++++++++- luna/src/NumberParsing.cpp | 27 +++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/luna/include/luna/NumberParsing.h b/luna/include/luna/NumberParsing.h index f4a709aa..e7c94bf5 100644 --- a/luna/include/luna/NumberParsing.h +++ b/luna/include/luna/NumberParsing.h @@ -1,7 +1,14 @@ #pragma once #include +// Parse an unsigned integer and advance *str to point to the first non-digit character after the number. usize scan_unsigned_integer(const char** str); + +// Parse a signed integer and advance *str to point to the first non-digit character after the number. isize scan_signed_integer(const char** str); + +// Parse an unsigned integer, similar to strtoull(). usize parse_unsigned_integer(const char* str, const char** endptr, int base); -isize parse_signed_integer(const char* str, const char** endptr, int base); + +// Parse a signed integer, similar to strtoll(). +isize parse_signed_integer(const char* str, const char** endptr, int base); \ No newline at end of file diff --git a/luna/src/NumberParsing.cpp b/luna/src/NumberParsing.cpp index 0938c06b..b9345452 100644 --- a/luna/src/NumberParsing.cpp +++ b/luna/src/NumberParsing.cpp @@ -17,12 +17,13 @@ static bool is_valid_digit_for_base(int base, char c) return true; } -usize parse_unsigned_integer(const char* str, const char** endptr, int base) +static usize do_unsigned_parse(const char* str, const char** endptr, int base) { usize val = 0; - while (_isspace(*str)) str++; - + // 1. If base is zero or 16, the string may then include a "0x" prefix, and the number will be read in base 16; + // otherwise, a zero base is taken as 10 (decimal) unless the next character is '0', in which case it is taken as + // 8 (octal). if ((base == 0 || base == 16) && *str == '0') { str++; @@ -37,17 +38,32 @@ usize parse_unsigned_integer(const char* str, const char** endptr, int base) else if (base == 0) base = 10; + // 2. The remainder of the string is converted to an unsigned long value in + // the obvious manner, stopping at the first character which is not a + // valid digit in the given base. while (is_valid_digit_for_base(base, *str)) { val = ((usize)base * val) + (usize)parse_digit_unchecked(*str); str++; } + // 3. If endptr is not NULL, this function stores the address of the first invalid character in *endptr. if (endptr) *endptr = str; return val; } +usize parse_unsigned_integer(const char* str, const char** endptr, int base) +{ + // The string may begin with an arbitrary amount of white space (as determined by isspace(3)), + while (_isspace(*str)) str++; + + // followed by a single optional '+' or '-' sign. + if (*str == '-' || *str == '+') str++; + + return do_unsigned_parse(str, endptr, base); +} + #define SSIZE_MAX LONG_MAX #define SSIZE_MIN (-SSIZE_MAX - (isize)1) @@ -55,16 +71,19 @@ isize parse_signed_integer(const char* str, const char** endptr, int base) { bool negative = false; + // The string may begin with an arbitrary amount of white space (as determined by isspace(3)), while (_isspace(*str)) str++; + // followed by a single optional '+' or '-' sign. if (*str == '-' || *str == '+') { if (*str == '-') negative = true; str++; } - usize rc = parse_unsigned_integer(str, endptr, base); + usize rc = do_unsigned_parse(str, endptr, base); + // If an underflow occurs, this function returns SSIZE_MIN. If an overflow occurs, this function returns SSIZE_MAX. if (rc > SSIZE_MAX) { return negative ? SSIZE_MIN : SSIZE_MAX; } return negative ? -(isize)rc : (isize)rc; From 90bd4a83c096ce530232c0f29ff61e8728de7041 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:14:27 +0100 Subject: [PATCH 268/407] Result, Option: Move member initialization to constructors --- luna/include/luna/Option.h | 20 +++++------- luna/include/luna/Result.h | 62 ++++++++------------------------------ 2 files changed, 20 insertions(+), 62 deletions(-) diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index 9ef4a58d..c4be03be 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -6,34 +6,29 @@ template class Option { public: - Option(const T& value) + Option(const T& value) : m_has_value(true) { m_storage.store_reference(value); - m_has_value = true; } - Option(T&& value) + Option(T&& value) : m_has_value(true) { m_storage.store_moved_reference(move(value)); - m_has_value = true; } - Option(const Option& other) + Option(const Option& other) : m_has_value(other.m_has_value) { - m_has_value = other.has_value(); if (m_has_value) { m_storage.store_reference(other.m_storage.fetch_reference()); } } - Option(Option&& other) + Option(Option&& other) : m_has_value(other.m_has_value) { - m_has_value = other.has_value(); other.m_has_value = false; if (m_has_value) { m_storage.store_moved_reference(move(other.m_storage.fetch_reference())); } } - Option() + Option() : m_has_value(false) { - m_has_value = false; } bool has_value() const @@ -72,6 +67,7 @@ template class Option if (has_value()) m_storage.destroy(); } + // For compatibility with TRY() struct ErrorHandle { private: @@ -80,12 +76,10 @@ template class Option } }; - Option(ErrorHandle) + Option(const ErrorHandle&) : m_has_value(false) { - m_has_value = false; } - // For compatibility with TRY() ErrorHandle release_error() { expect(!has_value(), "Option::release_error called on a non-empty Option"); diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index b8ac716e..4179728a 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -19,58 +19,30 @@ struct Error template class Result { public: - Result(const T& value) : m_value(value) + Result(const T& value) : m_value(value), m_has_value(true) { - m_has_value = true; - m_has_error = false; } - Result(T&& value) : m_value(move(value)) + Result(T&& value) : m_value(move(value)), m_has_value(true) { - m_has_value = true; - m_has_error = false; } - Result(const Result& other) : m_value(other.m_value) + Result(const Result& other) : m_value(other.m_value), m_has_value(other.m_has_value), m_error(other.m_error) { - if (!other.m_has_error) - { - m_has_value = true; - m_has_error = false; - } - else - { - m_has_error = true; - m_has_value = false; - m_error = other.m_error; - } } - Result(Result&& other) : m_value(move(other.m_value)) + Result(Result&& other) : m_value(move(other.m_value)), m_has_value(other.m_has_value), m_error(other.m_error) { - if (!other.m_has_error) - { - m_has_value = true; - m_has_error = false; - } - else - { - m_has_error = true; - m_has_value = false; - m_error = other.m_error; - } + other.m_has_value = false; } - Result(const Error& err) : m_value() + Result(const Error& err) : m_value(), m_has_value(false), m_error(err.error) { - m_error = err.error; - m_has_error = true; - m_has_value = false; } bool has_error() { - return m_has_error; + return !m_has_value; } bool has_value() @@ -132,35 +104,27 @@ template class Result private: Option m_value; - int m_error; - bool m_has_error; bool m_has_value; + int m_error; }; template <> class Result { public: - Result() + Result() : m_has_error(false) { - m_has_error = false; } - Result(const Result& other) + Result(const Result& other) : m_has_error(other.m_has_error), m_error(other.m_error) { - m_has_error = other.m_has_error; - m_error = other.m_error; } - Result(Result&& other) + Result(Result&& other) : m_has_error(other.m_has_error), m_error(other.m_error) { - m_has_error = other.m_has_error; - m_error = other.m_error; } - Result(const Error& err) + Result(const Error& err) : m_has_error(true), m_error(err.error) { - m_error = err.error; - m_has_error = true; } bool has_error() @@ -216,8 +180,8 @@ template <> class Result } private: - int m_error; bool m_has_error; + int m_error; }; // clang-format off From 34c738116c2cccff2c7f2a8c1b6ed6a15cc95d50 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:15:00 +0100 Subject: [PATCH 269/407] Result: Make some member functions const --- luna/include/luna/Result.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index 4179728a..4a8d2baf 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -40,52 +40,52 @@ template class Result { } - bool has_error() + bool has_error() const { return !m_has_value; } - bool has_value() + bool has_value() const { return m_has_value; } - int error() + int error() const { expect(has_error(), "Result::error() called on a Result that holds a value"); return m_error; } - Error release_error() + Error release_error() const { expect(has_error(), "Result::release_error() called on a Result that holds a value"); return {m_error}; } - const char* error_string() + const char* error_string() const { expect(has_error(), "Result::error_string() called on a Result that holds a value"); return ::error_string(m_error); } - T value() + T value() const { expect(has_value(), "Result::value() called on a Result that holds an error"); return m_value.value(); } - T expect_value(const char* reason) + T expect_value(const char* reason) const { expect(has_value(), reason); return m_value.value(); } - T value_or(const T& other) + T value_or(const T& other) const { return m_value.value_or(other); } - bool try_set_value(T& ref) + bool try_set_value(T& ref) const { return m_value.try_set_value(ref); } @@ -127,53 +127,53 @@ template <> class Result { } - bool has_error() + bool has_error() const { return m_has_error; } - bool has_value() + bool has_value() const { return !m_has_error; } - int error() + int error() const { expect(has_error(), "Result::error() called on a Result that holds a value"); return m_error; } - Error release_error() + Error release_error() const { expect(has_error(), "Result::release_error() called on a Result that holds a value"); return {m_error}; } - const char* error_string() + const char* error_string() const { expect(has_error(), "Result::error_string() called on a Result that holds a value"); return ::error_string(m_error); } - void value() + void value() const { expect(has_value(), "Result::value() called on a Result that holds an error"); return; } - void expect_value(const char* reason) + void expect_value(const char* reason) const { expect(has_value(), reason); return; } - void release_value() + void release_value() const { expect(has_value(), "Result::release_value() called on a Result that holds an error"); return; } - void expect_release_value(const char* reason) + void expect_release_value(const char* reason) const { expect(has_value(), reason); return; From 2bc6398d3edbe820dd26b1bc1c8360822cee794a Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:15:27 +0100 Subject: [PATCH 270/407] TRY(): Call release_value() instead of expect_release_value() --- luna/include/luna/Result.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index 4a8d2baf..b012ffab 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -192,5 +192,5 @@ template <> class Result ({ \ auto _expr_rc = (expr); \ if (!_expr_rc.has_value()) return _expr_rc.release_error(); \ - _expr_rc.expect_release_value("sanity check failed: has_error() returned false, yet result has no value"); \ + _expr_rc.release_value(); \ }) From c5220cbf64c7a2fb18d0db5fdcaa2c9010773347 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:27:00 +0100 Subject: [PATCH 271/407] LinkedList: Rename append_after to add_after --- kernel/src/memory/Heap.cpp | 2 +- luna/include/luna/LinkedList.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 90fd79f0..aa9d219d 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -113,7 +113,7 @@ static Option split(HeapBlock* block, usize size) new_block->magic = BLOCK_MAGIC; new_block->status = (block->status & BLOCK_END_MEM) ? BLOCK_END_MEM : 0; new_block->full_size = old_size - (offset + sizeof(HeapBlock)); - heap.append_after(block, new_block); + heap.add_after(block, new_block); block->status &= ~BLOCK_END_MEM; // this block is no longer the last block in its memory range diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 80c9b240..6f93d697 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -76,7 +76,7 @@ template class DoublyLinkedList m_count++; } - void append_after(T* base, T* ptr) + void add_after(T* base, T* ptr) { Node* const new_node = extract_node(ptr); Node* const base_node = extract_node(base); From f5de9c5589b7ce8556dd9424961529613a497336 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:27:16 +0100 Subject: [PATCH 272/407] LinkedList: Add a prepend() method --- luna/include/luna/LinkedList.h | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 6f93d697..aeb5a695 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -45,12 +45,18 @@ template class DoublyLinkedListNode m_last_node->m_next_node = m_next_node; } - void add_to_list(SelfType* end_node) + void append_to_list(SelfType* end_node) { end_node->m_next_node = this; this->m_last_node = end_node; } + void prepend_to_list(SelfType* start_node) + { + start_node->m_last_node = this; + this->m_next_node = start_node; + } + friend class DoublyLinkedList; }; @@ -65,7 +71,7 @@ template class DoublyLinkedList { Node* const node = extract_node(ptr); if (!m_start_node) m_start_node = node; - if (m_end_node) node->add_to_list(m_end_node); + if (m_end_node) node->append_to_list(m_end_node); else { node->set_next(nullptr); @@ -76,6 +82,20 @@ template class DoublyLinkedList m_count++; } + void prepend(T* ptr) + { + Node* const node = extract_node(ptr); + if (m_start_node) node->prepend_to_list(m_start_node); + else + { + node->set_next(nullptr); + node->set_last(nullptr); + } + m_start_node = node; + + m_count++; + } + void add_after(T* base, T* ptr) { Node* const new_node = extract_node(ptr); From e4b971f09c8c3dd965c12aff5913e907a85b7685 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:28:18 +0100 Subject: [PATCH 273/407] Make LinkedList::prepend() also set the element as the last one if we have no elements --- luna/include/luna/LinkedList.h | 1 + 1 file changed, 1 insertion(+) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index aeb5a695..50615134 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -85,6 +85,7 @@ template class DoublyLinkedList void prepend(T* ptr) { Node* const node = extract_node(ptr); + if (!m_end_node) m_end_node = node; if (m_start_node) node->prepend_to_list(m_start_node); else { From d5b9ff1569e2461007d4ebc1b2812153cfef30be Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:30:57 +0100 Subject: [PATCH 274/407] Remove unused function definition --- kernel/src/thread/Thread.h | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index ad33d895..760060e3 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -56,6 +56,5 @@ void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs); bool is_in_kernel(Registers* regs); Result new_thread(); -Result create_idle_thread(); extern DoublyLinkedList g_threads; \ No newline at end of file From 799a02c8839fa6506533a36465ad4a4da72e8a21 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:33:47 +0100 Subject: [PATCH 275/407] Remove unnecessary std:: prefix from inside std --- kernel/src/memory/Heap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index aa9d219d..77e5ac24 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -14,7 +14,7 @@ namespace std { - const std::nothrow_t nothrow; + const nothrow_t nothrow; } static constexpr int BLOCK_USED = 1 << 0; From 95b0091622e854dad276851267b67ffdb136950e Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:45:06 +0100 Subject: [PATCH 276/407] Split off arch/x86_64/CPU.cpp into various files --- kernel/CMakeLists.txt | 3 + kernel/src/arch/x86_64/CPU.cpp | 281 +--------------------------- kernel/src/arch/x86_64/CPU.h | 17 +- kernel/src/arch/x86_64/init/GDT.cpp | 94 ++++++++++ kernel/src/arch/x86_64/init/IDT.cpp | 116 ++++++++++++ kernel/src/arch/x86_64/init/PIC.cpp | 54 ++++++ 6 files changed, 288 insertions(+), 277 deletions(-) create mode 100644 kernel/src/arch/x86_64/init/GDT.cpp create mode 100644 kernel/src/arch/x86_64/init/IDT.cpp create mode 100644 kernel/src/arch/x86_64/init/PIC.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 89c601ee..9cf0febf 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -26,6 +26,9 @@ if("${ARCH}" MATCHES "x86_64") src/arch/x86_64/CPU.cpp src/arch/x86_64/Timer.cpp src/arch/x86_64/Thread.cpp + src/arch/x86_64/init/GDT.cpp + src/arch/x86_64/init/IDT.cpp + src/arch/x86_64/init/PIC.cpp ) endif() diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 0338fd96..56606059 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -2,12 +2,10 @@ #include "Log.h" #include "arch/Timer.h" #include "arch/x86_64/CPU.h" -#include "arch/x86_64/IO.h" #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include #include -#include #include #include #include @@ -16,280 +14,11 @@ extern "C" void enable_sse(); extern "C" void enable_write_protect(); extern "C" void enable_nx(); -// FIXME: Split this into separate files? - -// GDT code and definitions - -struct [[gnu::packed]] GDTR -{ - u16 size; - u64 offset; -}; - -static_assert(sizeof(GDTR) == 10UL); - -struct [[gnu::packed]] GDTEntry -{ - u16 limit0; - u16 base0; - u8 base1; - u8 access; - u8 limit1_flags; - u8 base2; -}; - -static_assert(sizeof(GDTEntry) == 8UL); - -struct [[gnu::packed]] HighGDTEntry -{ - u32 base_high; - u32 reserved; -}; - -static_assert(sizeof(HighGDTEntry) == 8UL); - -struct [[gnu::packed]] TSS -{ - u32 reserved0; - u64 rsp[3]; - u64 reserved1; - u64 ist[7]; - u64 reserved2; - u16 reserved3; - u16 iomap_base; -}; - -static_assert(sizeof(TSS) == 104UL); - -struct [[gnu::packed]] alignas(4096) GlobalDescriptorTable -{ - GDTEntry null; - GDTEntry kernel_code; - GDTEntry kernel_data; - GDTEntry user_code; - GDTEntry user_data; - GDTEntry tss; - HighGDTEntry tss2; -}; - -static TSS task_state_segment; - -static GlobalDescriptorTable gdt = {{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00}, - {0xffff, 0x0000, 0x00, 0x9a, 0xaf, 0x00}, - {0xffff, 0x0000, 0x00, 0x92, 0xcf, 0x00}, - {0xffff, 0x0000, 0x00, 0xfa, 0xaf, 0x00}, - {0xffff, 0x0000, 0x00, 0xf2, 0xcf, 0x00}, - {0x0000, 0x0000, 0x00, 0xe9, 0x0f, 0x00}, - {0x00000000, 0x00000000}}; - -extern "C" void load_gdt(GDTR* gdtr); -extern "C" void load_tr(int segment); - -static void set_base(GDTEntry* entry, u32 base) -{ - entry->base0 = (base & 0xFFFF); - entry->base1 = (base >> 16) & 0xFF; - entry->base2 = (u8)((base >> 24) & 0xFF); -} - -static void set_limit(GDTEntry* entry, u32 limit) -{ - expect(limit <= 0xFFFFF, "Limit too big for a GDT entry"); - entry->limit0 = limit & 0xFFFF; - entry->limit1_flags = (entry->limit1_flags & 0xF0) | ((limit >> 16) & 0xF); -} - -static void set_tss_base(GDTEntry* tss1, HighGDTEntry* tss2, u64 addr) -{ - set_base(tss1, addr & 0xffffffff); - tss2->base_high = (u32)(addr >> 32); -} - -static void setup_tss() -{ - memset(&task_state_segment, 0, sizeof(TSS)); - task_state_segment.iomap_base = sizeof(TSS); - set_tss_base(&gdt.tss, &gdt.tss2, (u64)&task_state_segment); - set_limit(&gdt.tss, sizeof(TSS) - 1); -} - -static void setup_gdt() -{ - static GDTR gdtr; - gdtr.offset = (u64)&gdt; - gdtr.size = sizeof(GlobalDescriptorTable); - setup_tss(); - load_gdt(&gdtr); - load_tr(0x2b); -} - -// PIC code - -#define PIC1_COMMAND 0x20 -#define PIC1_DATA 0x21 -#define PIC2_COMMAND 0xA0 -#define PIC2_DATA 0xA1 -#define PIC_EOI 0x20 - -#define ICW1_INIT 0x10 -#define ICW1_ICW4 0x01 -#define ICW4_8086 0x01 - -#define io_delay() IO::outb(0x80, 0) - -static void remap_pic() -{ - IO::outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); - io_delay(); - IO::outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); - io_delay(); - - IO::outb(PIC1_DATA, 0x20); - io_delay(); - - IO::outb(PIC2_DATA, 0x28); - io_delay(); - - IO::outb(PIC1_DATA, 4); - io_delay(); - IO::outb(PIC2_DATA, 2); - io_delay(); - - IO::outb(PIC1_DATA, ICW4_8086); - io_delay(); - IO::outb(PIC2_DATA, ICW4_8086); - io_delay(); - - IO::outb(PIC1_DATA, 0b11111110); - io_delay(); - IO::outb(PIC2_DATA, 0b11111111); -} - -static void pic_eoi(unsigned char irq) -{ - if (irq >= 8) IO::outb(PIC2_COMMAND, PIC_EOI); - IO::outb(PIC1_COMMAND, PIC_EOI); -} - -static void pic_eoi(Registers* regs) -{ - pic_eoi((unsigned char)(regs->error)); // On IRQs, the error code is the IRQ number -} - -// IDT code and definitions - -struct IDTEntry -{ - u16 offset0; - u16 selector; - u8 ist; - u8 type_attr; - u16 offset1; - u32 offset2; - u32 ignore; - void set_offset(u64 offset); - u64 get_offset() const; -}; - -static_assert(sizeof(IDTEntry) == 16UL); - -void IDTEntry::set_offset(u64 offset) -{ - offset0 = (u16)(offset & 0x000000000000ffff); - offset1 = (u16)((offset & 0x00000000ffff0000) >> 16); - offset2 = (u32)((offset & 0xffffffff00000000) >> 32); -} - -u64 IDTEntry::get_offset() const -{ - u64 offset = 0; - offset |= (u64)offset0; - offset |= (u64)offset1 << 16; - offset |= (u64)offset2 << 32; - return offset; -} - -static IDTEntry idt[256]; - -#define IDT_TA_InterruptGate 0b10001110 -#define IDT_TA_UserInterruptGate 0b11101110 -#define IDT_TA_TrapGate 0b10001111 - -struct [[gnu::packed]] IDTR -{ - u16 limit; - u64 offset; -}; - -static_assert(sizeof(IDTR) == 10UL); - -static void idt_add_handler(short num, void* handler, u8 type_attr) -{ - check(handler != nullptr); - expect(num < 256, "IDT can only hold up to 256 entries"); - IDTEntry* const entry_for_handler = &idt[num]; - entry_for_handler->selector = 0x08; - entry_for_handler->type_attr = type_attr; - entry_for_handler->set_offset((u64)handler); -} - -#define INT(x) extern "C" void _isr##x() -#define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) -#define IRQ(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_InterruptGate) - -INT(0); -INT(1); -INT(2); -INT(3); -INT(4); -INT(5); -INT(6); -INT(7); -INT(8); -INT(10); -INT(11); -INT(12); -INT(13); -INT(14); -INT(16); -INT(17); -INT(18); -INT(19); -INT(20); -INT(21); -INT(32); - -static void setup_idt() -{ - memset(idt, 0, sizeof(idt)); - - TRAP(0); - TRAP(1); - TRAP(2); - TRAP(3); - TRAP(4); - TRAP(5); - TRAP(6); - TRAP(7); - TRAP(8); - TRAP(10); - TRAP(11); - TRAP(12); - TRAP(13); - TRAP(14); - TRAP(16); - TRAP(17); - TRAP(18); - TRAP(19); - TRAP(20); - TRAP(21); - IRQ(32); - - static IDTR idtr; - idtr.limit = 0x0FFF; - idtr.offset = (u64)idt; - asm volatile("lidt %0" : : "m"(idtr)); -} +extern void setup_gdt(); +extern void remap_pic(); +extern void pic_eoi(unsigned char irq); +extern void pic_eoi(Registers* regs); +extern void setup_idt(); // Interrupt handling diff --git a/kernel/src/arch/x86_64/CPU.h b/kernel/src/arch/x86_64/CPU.h index a06de7b9..c5747521 100644 --- a/kernel/src/arch/x86_64/CPU.h +++ b/kernel/src/arch/x86_64/CPU.h @@ -7,4 +7,19 @@ struct Registers // Saved CPU registers for x86-64 u64 rbp, rdi, rsi, rdx, rcx, rbx, rax; u64 isr, error; u64 rip, cs, rflags, rsp, ss; -}; \ No newline at end of file +}; + +struct [[gnu::packed]] TSS +{ + u32 reserved0; + u64 rsp[3]; + u64 reserved1; + u64 ist[7]; + u64 reserved2; + u16 reserved3; + u16 iomap_base; +}; + +static_assert(sizeof(TSS) == 104UL); + +extern TSS task_state_segment; \ No newline at end of file diff --git a/kernel/src/arch/x86_64/init/GDT.cpp b/kernel/src/arch/x86_64/init/GDT.cpp new file mode 100644 index 00000000..ca48ef5c --- /dev/null +++ b/kernel/src/arch/x86_64/init/GDT.cpp @@ -0,0 +1,94 @@ +#include "arch/x86_64/CPU.h" +#include +#include +#include + +struct [[gnu::packed]] GDTR +{ + u16 size; + u64 offset; +}; + +static_assert(sizeof(GDTR) == 10UL); + +struct [[gnu::packed]] GDTEntry +{ + u16 limit0; + u16 base0; + u8 base1; + u8 access; + u8 limit1_flags; + u8 base2; +}; + +static_assert(sizeof(GDTEntry) == 8UL); + +struct [[gnu::packed]] HighGDTEntry +{ + u32 base_high; + u32 reserved; +}; + +static_assert(sizeof(HighGDTEntry) == 8UL); + +struct [[gnu::packed]] alignas(4096) GlobalDescriptorTable +{ + GDTEntry null; + GDTEntry kernel_code; + GDTEntry kernel_data; + GDTEntry user_code; + GDTEntry user_data; + GDTEntry tss; + HighGDTEntry tss2; +}; + +TSS task_state_segment; + +static GlobalDescriptorTable gdt = {{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00}, + {0xffff, 0x0000, 0x00, 0x9a, 0xaf, 0x00}, + {0xffff, 0x0000, 0x00, 0x92, 0xcf, 0x00}, + {0xffff, 0x0000, 0x00, 0xfa, 0xaf, 0x00}, + {0xffff, 0x0000, 0x00, 0xf2, 0xcf, 0x00}, + {0x0000, 0x0000, 0x00, 0xe9, 0x0f, 0x00}, + {0x00000000, 0x00000000}}; + +extern "C" void load_gdt(GDTR* gdtr); +extern "C" void load_tr(int segment); + +static void set_base(GDTEntry* entry, u32 base) +{ + entry->base0 = (base & 0xFFFF); + entry->base1 = (base >> 16) & 0xFF; + entry->base2 = (u8)((base >> 24) & 0xFF); +} + +static void set_limit(GDTEntry* entry, u32 limit) +{ + expect(limit <= 0xFFFFF, "Limit too big for a GDT entry"); + entry->limit0 = limit & 0xFFFF; + entry->limit1_flags = (entry->limit1_flags & 0xF0) | ((limit >> 16) & 0xF); +} + +static void set_tss_base(GDTEntry* tss1, HighGDTEntry* tss2, u64 addr) +{ + set_base(tss1, addr & 0xffffffff); + tss2->base_high = (u32)(addr >> 32); +} + +static void setup_tss() +{ + memset(&task_state_segment, 0, sizeof(TSS)); + task_state_segment.iomap_base = sizeof(TSS); + set_tss_base(&gdt.tss, &gdt.tss2, (u64)&task_state_segment); + set_limit(&gdt.tss, sizeof(TSS) - 1); +} + +void setup_gdt() +{ + static GDTR gdtr; + gdtr.offset = (u64)&gdt; + gdtr.size = sizeof(GlobalDescriptorTable); + setup_tss(); + load_gdt(&gdtr); + load_tr(0x2b); +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/init/IDT.cpp b/kernel/src/arch/x86_64/init/IDT.cpp new file mode 100644 index 00000000..eb1d01e6 --- /dev/null +++ b/kernel/src/arch/x86_64/init/IDT.cpp @@ -0,0 +1,116 @@ +#include +#include +#include + +struct IDTEntry +{ + u16 offset0; + u16 selector; + u8 ist; + u8 type_attr; + u16 offset1; + u32 offset2; + u32 ignore; + void set_offset(u64 offset); + u64 get_offset() const; +}; + +static_assert(sizeof(IDTEntry) == 16UL); + +void IDTEntry::set_offset(u64 offset) +{ + offset0 = (u16)(offset & 0x000000000000ffff); + offset1 = (u16)((offset & 0x00000000ffff0000) >> 16); + offset2 = (u32)((offset & 0xffffffff00000000) >> 32); +} + +u64 IDTEntry::get_offset() const +{ + u64 offset = 0; + offset |= (u64)offset0; + offset |= (u64)offset1 << 16; + offset |= (u64)offset2 << 32; + return offset; +} + +static IDTEntry idt[256]; + +#define IDT_TA_InterruptGate 0b10001110 +#define IDT_TA_UserInterruptGate 0b11101110 +#define IDT_TA_TrapGate 0b10001111 + +struct [[gnu::packed]] IDTR +{ + u16 limit; + u64 offset; +}; + +static_assert(sizeof(IDTR) == 10UL); + +static void idt_add_handler(short num, void* handler, u8 type_attr) +{ + check(handler != nullptr); + expect(num < 256, "IDT can only hold up to 256 entries"); + IDTEntry* const entry_for_handler = &idt[num]; + entry_for_handler->selector = 0x08; + entry_for_handler->type_attr = type_attr; + entry_for_handler->set_offset((u64)handler); +} + +#define INT(x) extern "C" void _isr##x() +#define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) +#define IRQ(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_InterruptGate) + +INT(0); +INT(1); +INT(2); +INT(3); +INT(4); +INT(5); +INT(6); +INT(7); +INT(8); +INT(10); +INT(11); +INT(12); +INT(13); +INT(14); +INT(16); +INT(17); +INT(18); +INT(19); +INT(20); +INT(21); +INT(32); + +void setup_idt() +{ + memset(idt, 0, sizeof(idt)); + + TRAP(0); + TRAP(1); + TRAP(2); + TRAP(3); + TRAP(4); + TRAP(5); + TRAP(6); + TRAP(7); + TRAP(8); + TRAP(10); + TRAP(11); + TRAP(12); + TRAP(13); + TRAP(14); + TRAP(16); + TRAP(17); + TRAP(18); + TRAP(19); + TRAP(20); + TRAP(21); + IRQ(32); + + static IDTR idtr; + idtr.limit = 0x0FFF; + idtr.offset = (u64)idt; + asm volatile("lidt %0" : : "m"(idtr)); +} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/init/PIC.cpp b/kernel/src/arch/x86_64/init/PIC.cpp new file mode 100644 index 00000000..c7fd1068 --- /dev/null +++ b/kernel/src/arch/x86_64/init/PIC.cpp @@ -0,0 +1,54 @@ +#include "arch/x86_64/CPU.h" +#include "arch/x86_64/IO.h" +#include + +#define PIC1_COMMAND 0x20 +#define PIC1_DATA 0x21 +#define PIC2_COMMAND 0xA0 +#define PIC2_DATA 0xA1 +#define PIC_EOI 0x20 + +#define ICW1_INIT 0x10 +#define ICW1_ICW4 0x01 +#define ICW4_8086 0x01 + +#define io_delay() IO::outb(0x80, 0) + +void remap_pic() +{ + IO::outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); + io_delay(); + IO::outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); + io_delay(); + + IO::outb(PIC1_DATA, 0x20); + io_delay(); + + IO::outb(PIC2_DATA, 0x28); + io_delay(); + + IO::outb(PIC1_DATA, 4); + io_delay(); + IO::outb(PIC2_DATA, 2); + io_delay(); + + IO::outb(PIC1_DATA, ICW4_8086); + io_delay(); + IO::outb(PIC2_DATA, ICW4_8086); + io_delay(); + + IO::outb(PIC1_DATA, 0b11111110); + io_delay(); + IO::outb(PIC2_DATA, 0b11111111); +} + +void pic_eoi(unsigned char irq) +{ + if (irq >= 8) IO::outb(PIC2_COMMAND, PIC_EOI); + IO::outb(PIC1_COMMAND, PIC_EOI); +} + +void pic_eoi(Registers* regs) +{ + pic_eoi((unsigned char)(regs->error)); // On IRQs, the error code is the IRQ number +} \ No newline at end of file From 1b867151bdf85523e84d60379f3d57c3f7ba9625 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:47:35 +0100 Subject: [PATCH 277/407] MemoryManager: Run include-what-you-use --- kernel/src/memory/MemoryManager.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 738df21b..f31194d6 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -1,13 +1,10 @@ #include "memory/MemoryManager.h" -#include "Log.h" -#include "arch/CPU.h" #include "arch/MMU.h" #include "memory/KernelVM.h" #include "memory/MemoryMap.h" #include "thread/Spinlock.h" #include #include -#include #include #include #include From a89ae9bed7ee246666d22e14ac69342f6d600c4c Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 17 Dec 2022 15:51:19 +0100 Subject: [PATCH 278/407] Run include-what-you-use --- kernel/src/arch/x86_64/init/PIC.cpp | 1 - kernel/src/thread/Scheduler.cpp | 1 - kernel/src/thread/Thread.h | 1 - 3 files changed, 3 deletions(-) diff --git a/kernel/src/arch/x86_64/init/PIC.cpp b/kernel/src/arch/x86_64/init/PIC.cpp index c7fd1068..a3af5be2 100644 --- a/kernel/src/arch/x86_64/init/PIC.cpp +++ b/kernel/src/arch/x86_64/init/PIC.cpp @@ -1,6 +1,5 @@ #include "arch/x86_64/CPU.h" #include "arch/x86_64/IO.h" -#include #define PIC1_COMMAND 0x20 #define PIC1_DATA 0x21 diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 36f2692e..225a9505 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -2,7 +2,6 @@ #include "Log.h" #include "arch/CPU.h" #include "arch/MMU.h" -#include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include #include diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 760060e3..514d51ba 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -1,6 +1,5 @@ #pragma once -#include "arch/CPU.h" #include #include From 23d405bbda0a1fda6152a1d5d660841820060aeb Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 12:40:28 +0100 Subject: [PATCH 279/407] Add an unreachable() macro function that panics if reached --- luna/include/luna/Check.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/luna/include/luna/Check.h b/luna/include/luna/Check.h index 37c3b13f..faf75bd7 100644 --- a/luna/include/luna/Check.h +++ b/luna/include/luna/Check.h @@ -1,5 +1,4 @@ #pragma once -#include [[noreturn]] extern bool __check_failed(const char* file, const char* line, const char* func, const char* expr); @@ -23,3 +22,6 @@ __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, #expr); \ } \ } while (0) + +#define unreachable() \ + __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, "Reached unreachable code") From 75ba14a3adacdeaf240e034656f2e7bd74d78a30 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 13:04:40 +0100 Subject: [PATCH 280/407] Add UTF-8 decoder support!! --- luna/CMakeLists.txt | 1 + luna/include/luna/Utf8.h | 38 ++++++++++++ luna/src/Utf8.cpp | 131 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 luna/include/luna/Utf8.h create mode 100644 luna/src/Utf8.cpp diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 53a8a28b..77f51628 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -10,6 +10,7 @@ set(FREESTANDING_SOURCES src/Stack.cpp src/Alloc.cpp src/OwnedStringView.cpp + src/Utf8.cpp ) set(SOURCES diff --git a/luna/include/luna/Utf8.h b/luna/include/luna/Utf8.h new file mode 100644 index 00000000..2361c918 --- /dev/null +++ b/luna/include/luna/Utf8.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include +#include + +class Utf8StringDecoder +{ + public: + Utf8StringDecoder(const char* str); + + usize byte_length() const + { + return m_byte_length; + } + + Result code_points() const; + + // The caller must ensure that 'buf' is at least wide_length() + a NULL wide. + Result decode(wchar_t* buf) const; + + private: + const char* m_str; + usize m_byte_length; +}; + +class Utf8StateDecoder +{ + public: + Utf8StateDecoder(); + + Result> feed(char c); + void reset(); + + private: + char m_state[4]; + usize m_state_len = 0; + usize m_state_index = 0; +}; \ No newline at end of file diff --git a/luna/src/Utf8.cpp b/luna/src/Utf8.cpp new file mode 100644 index 00000000..f1c9c666 --- /dev/null +++ b/luna/src/Utf8.cpp @@ -0,0 +1,131 @@ +#include +#include + +static Result utf8_char_length(char c) +{ + if ((c & 0b11111000) == 0b11110000) return 4; + if ((c & 0b11110000) == 0b11100000) return 3; + if ((c & 0b11100000) == 0b11000000) return 2; + if ((c & 0b10000000) == 0b00000000) return 1; + return err(EILSEQ); +} + +static Result encode_utf8_char_into_wide_char(const char* beg, usize& len) +{ + usize utf8_len = TRY(utf8_char_length(*beg)); + if (utf8_len > len) return err(EILSEQ); // Unterminated sequence + len = utf8_len; // Enough space for the sequence, let's return the resulting length + + if (len == 1) { return beg[0] & 0x7f; } + if (len == 2) + { + if ((beg[1] & 0b11000000) != 0b10000000) return err(EILSEQ); + wchar_t c = beg[0] & 0x1f; + c <<= 6; + c |= beg[1] & 0x3f; + return c; + } + if (len == 3) + { + if ((beg[1] & 0b11000000) != 0b10000000) return err(EILSEQ); + if ((beg[2] & 0b11000000) != 0b10000000) return err(EILSEQ); + wchar_t c = beg[0] & 0x0f; + c <<= 6; + c |= beg[1] & 0x3f; + c <<= 6; + c |= beg[2] & 0x3f; + return c; + } + if (len == 4) + { + if ((beg[1] & 0b11000000) != 0b10000000) return err(EILSEQ); + if ((beg[2] & 0b11000000) != 0b10000000) return err(EILSEQ); + if ((beg[3] & 0b11000000) != 0b10000000) return err(EILSEQ); + wchar_t c = beg[0] & 0x07; + c <<= 6; + c |= beg[1] & 0x3f; + c <<= 6; + c |= beg[2] & 0x3f; + c <<= 6; + c |= beg[3] & 0x3f; + if (c > 0x10ffff) return err(EILSEQ); + return c; + } + + unreachable(); +} + +Utf8StringDecoder::Utf8StringDecoder(const char* str) : m_str(str), m_byte_length(strlen(str)) +{ +} + +Result Utf8StringDecoder::code_points() const +{ + const char* it = m_str; + usize len = 0; + + while ((usize)(it - m_str) < m_byte_length) + { + usize utf8_len = TRY(utf8_char_length(*it)); + if ((usize)(it - m_str) + utf8_len > m_byte_length) return err(EILSEQ); + it += utf8_len; + len++; + } + + return len; +} + +Result Utf8StringDecoder::decode(wchar_t* buf) const +{ + const char* it = m_str; + + while ((usize)(it - m_str) < m_byte_length) + { + usize len = m_byte_length - (usize)(it - m_str); // Remaining space + *buf = TRY(encode_utf8_char_into_wide_char(it, len)); + it += len; + buf++; + } + + *buf = 0; + + return {}; +} + +Utf8StateDecoder::Utf8StateDecoder() : m_state_len(0), m_state_index(0) +{ +} + +Result> Utf8StateDecoder::feed(char c) +{ + if (m_state_len == 0) + { + m_state_len = TRY(utf8_char_length(c)); + if (m_state_len == 1) + { + m_state_len = 0; + return Option{c & 0x7f}; + } + m_state_index = 0; + m_state[m_state_index] = c; + return {{}}; + } + + m_state_index++; + m_state[m_state_index] = c; + + if (m_state_index == m_state_len - 1) + { + usize len = m_state_len; + wchar_t wc = TRY(encode_utf8_char_into_wide_char(m_state, len)); + m_state_len = 0; + return Option{wc}; + } + + return {{}}; +} + +void Utf8StateDecoder::reset() +{ + m_state_index = m_state_len = 0; +} \ No newline at end of file From 36179155e181ed35875abd9d59470deb3ca0ec1f Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 13:09:37 +0100 Subject: [PATCH 281/407] Add UTF-8 support to TextConsole!! Not much support, since the font only covers codepoints from U+0000 to U+00FF, (Basic Latin & Latin Extended-A), but unprintable code-points are rendered as ONE box per code-point, instead of multiple garbage characters. So it's Unicode-aware, even if it can't print most characters. --- kernel/src/video/BuiltinFont.h | 771 ++++++++++++++++++++----------- kernel/src/video/TextConsole.cpp | 32 +- kernel/src/video/TextConsole.h | 1 + 3 files changed, 541 insertions(+), 263 deletions(-) diff --git a/kernel/src/video/BuiltinFont.h b/kernel/src/video/BuiltinFont.h index cadd6908..72912bab 100644 --- a/kernel/src/video/BuiltinFont.h +++ b/kernel/src/video/BuiltinFont.h @@ -3,260 +3,517 @@ // FIXME: Load a font from disk/initrd. -u8 font[] = {0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, /* 2 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 */ - 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 11 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 12 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 13 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 14 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 15 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 17 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 21 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 22 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 24 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 25 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 26 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 27 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 29 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 30 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32 */ - 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 33 */ - 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 34 */ - 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, /* 35 */ - 0x00, 0x00, 0x08, 0x08, 0x1e, 0x20, 0x20, 0x1c, 0x02, 0x02, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 36 */ - 0x00, 0x00, 0x00, 0x30, 0x49, 0x4a, 0x34, 0x08, 0x16, 0x29, 0x49, 0x06, 0x00, 0x00, 0x00, 0x00, /* 37 */ - 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x31, 0x49, 0x46, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, /* 38 */ - 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ - 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, /* 40 */ - 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, /* 41 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 */ - 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 43 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 44 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 45 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 46 */ - 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, /* 47 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 48 */ - 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 49 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 50 */ - 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x1c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 51 */ - 0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* 52 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 53 */ - 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 54 */ - 0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 55 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 56 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* 57 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 58 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 59 */ - 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, /* 60 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 61 */ - 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, /* 62 */ - 0x00, 0x00, 0x3c, 0x42, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 63 */ - 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4f, 0x51, 0x51, 0x51, 0x53, 0x4d, 0x40, 0x20, 0x1f, 0x00, 0x00, /* 64 */ - 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 65 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 66 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 67 */ - 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x00, /* 68 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 69 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 70 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x46, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 71 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 72 */ - 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 73 */ - 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 74 */ - 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 75 */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 76 */ - 0x00, 0x00, 0x00, 0x41, 0x63, 0x55, 0x49, 0x49, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 77 */ - 0x00, 0x00, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 78 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 79 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 80 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x04, 0x02, 0x00, 0x00, /* 81 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 82 */ - 0x00, 0x00, 0x00, 0x3e, 0x40, 0x40, 0x20, 0x18, 0x04, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 83 */ - 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 84 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 85 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 86 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x41, 0x49, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 87 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 88 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 89 */ - 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 90 */ - 0x00, 0x00, 0x1e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x00, 0x00, /* 91 */ - 0x00, 0x00, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* 92 */ - 0x00, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, 0x00, /* 93 */ - 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 94 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, /* 95 */ - 0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 96 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 97 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 98 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 99 */ - 0x00, 0x00, 0x02, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 100 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 101 */ - 0x00, 0x00, 0x0e, 0x10, 0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 102 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 103 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 104 */ - 0x00, 0x00, 0x08, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 105 */ - 0x00, 0x00, 0x04, 0x04, 0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x00, /* 106 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 107 */ - 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 108 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, /* 109 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 110 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 111 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, /* 112 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, /* 113 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, /* 114 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 115 */ - 0x00, 0x00, 0x00, 0x10, 0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 116 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 117 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 118 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 119 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, /* 120 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 121 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 122 */ - 0x00, 0x0e, 0x10, 0x10, 0x10, 0x10, 0x10, 0xe0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, /* 123 */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 124 */ - 0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, /* 125 */ - 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 126 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 127 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 129 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 130 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 131 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 132 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 133 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 134 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 135 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 136 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 137 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 138 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 139 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 140 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 141 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 142 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 143 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 144 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 145 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 146 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 147 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 148 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 149 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 150 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 151 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 152 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 153 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 154 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 155 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 156 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 157 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 158 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 159 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 160 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /* 161 */ - 0x00, 0x00, 0x08, 0x08, 0x1c, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 162 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 163 */ - 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x24, 0x24, 0x3c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* 164 */ - 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x3e, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 165 */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 166 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 167 */ - 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 168 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4d, 0x51, 0x51, 0x4d, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 169 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 170 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x12, 0x24, 0x48, 0x24, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, /* 171 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 172 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 173 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 174 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 175 */ - 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 176 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 177 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 178 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 179 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 180 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 181 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 182 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 183 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x30, 0x00, /* 184 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 185 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 186 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x09, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, /* 187 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 189 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 190 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x42, 0x3c, 0x00, /* 191 */ - 0x20, 0x10, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 192 */ - 0x04, 0x08, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 193 */ - 0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 194 */ - 0x32, 0x4c, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 195 */ - 0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 196 */ - 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 197 */ - 0x00, 0x00, 0x00, 0x0f, 0x14, 0x14, 0x24, 0x27, 0x3c, 0x44, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00, /* 198 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e, 0x08, 0x08, 0x30, 0x00, /* 199 */ - 0x20, 0x10, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 200 */ - 0x04, 0x08, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 201 */ - 0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 202 */ - 0x24, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 203 */ - 0x10, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 204 */ - 0x04, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 205 */ - 0x18, 0x24, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 206 */ - 0x22, 0x22, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 207 */ - 0x00, 0x00, 0x00, 0x3c, 0x22, 0x21, 0x21, 0x79, 0x21, 0x21, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 208 */ - 0x32, 0x4c, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 209 */ - 0x10, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 210 */ - 0x04, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 211 */ - 0x18, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 212 */ - 0x32, 0x4c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 213 */ - 0x24, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 214 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 215 */ - 0x00, 0x00, 0x02, 0x3c, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 216 */ - 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 217 */ - 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 218 */ - 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 219 */ - 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 220 */ - 0x04, 0x08, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 221 */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 222 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x44, 0x4c, 0x42, 0x42, 0x42, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* 223 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 224 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 225 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 226 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 227 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 228 */ - 0x18, 0x24, 0x24, 0x18, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 229 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09, 0x39, 0x4f, 0x48, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, /* 230 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, /* 231 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 232 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 233 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 234 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 235 */ - 0x00, 0x00, 0x10, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 236 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 237 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 238 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 239 */ - 0x00, 0x09, 0x06, 0x1a, 0x01, 0x1d, 0x23, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 240 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 241 */ - 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 242 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 243 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 244 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 245 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 246 */ - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 247 */ - 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 248 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 249 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 250 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 251 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 252 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 253 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x00, /* 254 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, - /* 255 */}; \ No newline at end of file +u8 font[] = {0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, /* 2 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 */ + 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 11 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 12 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 13 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 14 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 15 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 17 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 21 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 22 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 24 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 25 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 26 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 29 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, + 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 30 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32 */ + 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 33 */ + 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 34 */ + 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x24, + 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, /* 35 */ + 0x00, 0x00, 0x08, 0x08, 0x1e, 0x20, 0x20, 0x1c, + 0x02, 0x02, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 36 */ + 0x00, 0x00, 0x00, 0x30, 0x49, 0x4a, 0x34, 0x08, + 0x16, 0x29, 0x49, 0x06, 0x00, 0x00, 0x00, 0x00, /* 37 */ + 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x31, + 0x49, 0x46, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, /* 38 */ + 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ + 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, /* 40 */ + 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, /* 41 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, + 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 */ + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, + 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 43 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 44 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 45 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 46 */ + 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, + 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, /* 47 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x46, 0x4a, 0x52, + 0x62, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 48 */ + 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 49 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 50 */ + 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x1c, 0x02, + 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 51 */ + 0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, + 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* 52 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, + 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 53 */ + 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 54 */ + 0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x04, 0x08, + 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 55 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 56 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, + 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* 57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 58 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 59 */ + 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, + 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, /* 60 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 61 */ + 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, /* 62 */ + 0x00, 0x00, 0x3c, 0x42, 0x02, 0x04, 0x08, 0x10, + 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 63 */ + 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4f, 0x51, 0x51, + 0x51, 0x53, 0x4d, 0x40, 0x20, 0x1f, 0x00, 0x00, /* 64 */ + 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 65 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, + 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 66 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 67 */ + 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x00, /* 68 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 69 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 70 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x46, + 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 71 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 72 */ + 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 73 */ + 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 74 */ + 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, + 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 75 */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 76 */ + 0x00, 0x00, 0x00, 0x41, 0x63, 0x55, 0x49, 0x49, + 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 77 */ + 0x00, 0x00, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 78 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 79 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, + 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 80 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x04, 0x02, 0x00, 0x00, /* 81 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, + 0x48, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 82 */ + 0x00, 0x00, 0x00, 0x3e, 0x40, 0x40, 0x20, 0x18, + 0x04, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 83 */ + 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 84 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 85 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 86 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x41, 0x49, + 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 87 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, + 0x14, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 88 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 89 */ + 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x08, 0x10, + 0x10, 0x20, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 90 */ + 0x00, 0x00, 0x1e, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x00, 0x00, /* 91 */ + 0x00, 0x00, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, + 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* 92 */ + 0x00, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, 0x00, /* 93 */ + 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 94 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, /* 95 */ + 0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 96 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 97 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 98 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, + 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 99 */ + 0x00, 0x00, 0x02, 0x02, 0x02, 0x3e, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 100 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 101 */ + 0x00, 0x00, 0x0e, 0x10, 0x10, 0x7e, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 102 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 103 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 104 */ + 0x00, 0x00, 0x08, 0x08, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 105 */ + 0x00, 0x00, 0x04, 0x04, 0x00, 0x1c, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x00, /* 106 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, + 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 107 */ + 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 108 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x49, 0x49, + 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, /* 109 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 110 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 111 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, /* 112 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, /* 113 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x30, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, /* 114 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x20, + 0x18, 0x04, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 115 */ + 0x00, 0x00, 0x00, 0x10, 0x10, 0x7e, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 116 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 117 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, + 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 118 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, + 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 119 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, + 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, /* 120 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 121 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, + 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 122 */ + 0x00, 0x0e, 0x10, 0x10, 0x10, 0x10, 0x10, 0xe0, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, /* 123 */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 124 */ + 0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, /* 125 */ + 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 126 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 127 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 129 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 130 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 131 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 132 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 133 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 134 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 135 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 136 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 137 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 138 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 139 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 140 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 141 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 142 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 143 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 144 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 145 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 146 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 147 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 148 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 149 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 150 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 151 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 152 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 153 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 154 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 155 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 156 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 157 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 158 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 159 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 160 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, + 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /* 161 */ + 0x00, 0x00, 0x08, 0x08, 0x1c, 0x22, 0x40, 0x40, + 0x40, 0x22, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 162 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, + 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 163 */ + 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x24, + 0x24, 0x3c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* 164 */ + 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x3e, + 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 165 */ + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, + 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 166 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 167 */ + 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 168 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4d, 0x51, + 0x51, 0x4d, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 169 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 170 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x12, 0x24, + 0x48, 0x24, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, /* 171 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 172 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 173 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 174 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 175 */ + 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 176 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 177 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 178 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 179 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 180 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 181 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 182 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 183 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x30, 0x00, /* 184 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 185 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 186 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, + 0x09, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, /* 187 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 189 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 190 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, + 0x00, 0x08, 0x10, 0x20, 0x40, 0x42, 0x3c, 0x00, /* 191 */ + 0x20, 0x10, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 192 */ + 0x04, 0x08, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 193 */ + 0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 194 */ + 0x32, 0x4c, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 195 */ + 0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 196 */ + 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 197 */ + 0x00, 0x00, 0x00, 0x0f, 0x14, 0x14, 0x24, 0x27, + 0x3c, 0x44, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00, /* 198 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x1e, 0x08, 0x08, 0x30, 0x00, /* 199 */ + 0x20, 0x10, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 200 */ + 0x04, 0x08, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 201 */ + 0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 202 */ + 0x24, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 203 */ + 0x10, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 204 */ + 0x04, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 205 */ + 0x18, 0x24, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 206 */ + 0x22, 0x22, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 207 */ + 0x00, 0x00, 0x00, 0x3c, 0x22, 0x21, 0x21, 0x79, + 0x21, 0x21, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 208 */ + 0x32, 0x4c, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 209 */ + 0x10, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 210 */ + 0x04, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 211 */ + 0x18, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 212 */ + 0x32, 0x4c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 213 */ + 0x24, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 214 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, + 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 215 */ + 0x00, 0x00, 0x02, 0x3c, 0x42, 0x46, 0x4a, 0x52, + 0x62, 0x42, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 216 */ + 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 217 */ + 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 218 */ + 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 219 */ + 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 220 */ + 0x04, 0x08, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 221 */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x7c, 0x42, 0x42, + 0x42, 0x7c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 222 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x44, 0x4c, 0x42, + 0x42, 0x42, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* 223 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 224 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 225 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 226 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 227 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 228 */ + 0x18, 0x24, 0x24, 0x18, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 229 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09, 0x39, + 0x4f, 0x48, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, /* 230 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, + 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, /* 231 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 232 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 233 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 234 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 235 */ + 0x00, 0x00, 0x10, 0x08, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 236 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 237 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 238 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 239 */ + 0x00, 0x09, 0x06, 0x1a, 0x01, 0x1d, 0x23, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 240 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 241 */ + 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 242 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 243 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 244 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 245 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 246 */ + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 247 */ + 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, + 0x52, 0x62, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 248 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 249 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 250 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 251 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 252 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 253 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x41, + 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x00, /* 254 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 255 */ + 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00 /* Special box character, 256 */}; \ No newline at end of file diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index 62928c70..a8932acc 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include extern const BOOTBOOT bootboot; @@ -22,7 +23,9 @@ static constexpr u32 FONT_WIDTH = 8; static u32 g_x_position = 0; static u32 g_y_position = 0; -static void putchar_at(char c, u32 x, u32 y) +static Utf8StateDecoder decoder; + +static void putwchar_at(wchar_t c, u32 x, u32 y) { const u8* glyph = &font[c * 16]; for (u32 i = 0; i < FONT_HEIGHT; i++) @@ -84,17 +87,20 @@ static bool at_end_of_screen() namespace TextConsole { - void putchar(char c) + void putwchar(wchar_t c) { + // Unprintable (not in the built-in font) characters get represented as a box + if (c > (wchar_t)255) c = (wchar_t)256; + switch (c) { - case '\n': { + case L'\n': { next_line(); if (should_scroll()) scroll(); break; } - case '\r': g_x_position = 0; break; - case '\b': + case L'\r': g_x_position = 0; break; + case L'\b': if (g_x_position != 0) { prev_char(); @@ -102,7 +108,7 @@ namespace TextConsole } break; default: { - putchar_at(c, g_x_position, g_y_position); + putwchar_at(c, g_x_position, g_y_position); next_char(); if (at_end_of_screen()) { @@ -114,6 +120,20 @@ namespace TextConsole } } + // FIXME: Should this function propagate errors? + void putchar(char c) + { + auto rc = decoder.feed(c); + if (rc.has_error()) + { + decoder.reset(); + return; + } + + auto maybe_wchar = rc.value(); + if (maybe_wchar.has_value()) putwchar(maybe_wchar.value()); + } + void set_foreground(u32 color) { g_foreground_color = color; diff --git a/kernel/src/video/TextConsole.h b/kernel/src/video/TextConsole.h index 73ae96b5..2c884262 100644 --- a/kernel/src/video/TextConsole.h +++ b/kernel/src/video/TextConsole.h @@ -7,6 +7,7 @@ namespace TextConsole { void clear(); void putchar(char c); + void putwchar(wchar_t c); void set_foreground(u32 color); void set_background(u32 color); u32 foreground(); From 9c1c6bb3205dca4f1776f0e95e42188e4d4efcd1 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 14:33:13 +0100 Subject: [PATCH 282/407] Add wcslen() I think this can go in CString.h, no need to create a separate CWChar.h or something --- luna/include/luna/CString.h | 2 ++ luna/src/CString.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/luna/include/luna/CString.h b/luna/include/luna/CString.h index 0eca451c..b1026be3 100644 --- a/luna/include/luna/CString.h +++ b/luna/include/luna/CString.h @@ -9,5 +9,7 @@ extern "C" void* memmove(void* dest, const void* src, usize n); usize strlen(const char* str); + usize wcslen(const wchar_t* str); + char* strdup(const char* str); } \ No newline at end of file diff --git a/luna/src/CString.cpp b/luna/src/CString.cpp index 7942501a..79580e6f 100644 --- a/luna/src/CString.cpp +++ b/luna/src/CString.cpp @@ -46,6 +46,14 @@ extern "C" return (usize)(i - str); } + usize wcslen(const wchar_t* str) + { + const wchar_t* i = str; + for (; *i; ++i) + ; + return (usize)(i - str); + } + char* strdup(const char* str) { const usize len = strlen(str); From 6389099808f35242fba49035f0fdc467a883c176 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 14:34:50 +0100 Subject: [PATCH 283/407] UTF-8 part 2: Encoding wide-character strings into UTF-8 We now have Utf8StringEncoder and Utf8Encoder (no state this time) --- luna/include/luna/Utf8.h | 29 +++++++++++- luna/src/Utf8.cpp | 95 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/luna/include/luna/Utf8.h b/luna/include/luna/Utf8.h index 2361c918..25509b73 100644 --- a/luna/include/luna/Utf8.h +++ b/luna/include/luna/Utf8.h @@ -15,7 +15,7 @@ class Utf8StringDecoder Result code_points() const; - // The caller must ensure that 'buf' is at least wide_length() + a NULL wide. + // The caller must ensure that 'buf' is at least code_points() + a NULL wide. Result decode(wchar_t* buf) const; private: @@ -23,6 +23,26 @@ class Utf8StringDecoder usize m_byte_length; }; +class Utf8StringEncoder +{ + public: + Utf8StringEncoder(const wchar_t* str); + + usize code_points() const + { + return m_code_points; + } + + Result byte_length() const; + + // The caller must ensure that 'buf' is at least byte_length() + a NULL wide. + Result encode(char* buf) const; + + private: + const wchar_t* m_str; + usize m_code_points; +}; + class Utf8StateDecoder { public: @@ -35,4 +55,11 @@ class Utf8StateDecoder char m_state[4]; usize m_state_len = 0; usize m_state_index = 0; +}; + +class Utf8Encoder +{ + public: + // Does not null-terminate. Returns the number of bytes written. + Result encode(wchar_t c, char buf[4]); }; \ No newline at end of file diff --git a/luna/src/Utf8.cpp b/luna/src/Utf8.cpp index f1c9c666..4445c355 100644 --- a/luna/src/Utf8.cpp +++ b/luna/src/Utf8.cpp @@ -10,7 +10,52 @@ static Result utf8_char_length(char c) return err(EILSEQ); } -static Result encode_utf8_char_into_wide_char(const char* beg, usize& len) +static Result wide_char_length_as_utf8(wchar_t c) +{ + if (c <= 0x7f) return 1; + if (c <= 0x7ff) return 2; + if (c <= 0xffff) return 3; + if (c <= 0x10ffff) return 4; + return err(EILSEQ); +} + +static Result encode_wide_char_as_utf8(wchar_t c, char* result, usize& len) +{ + len = TRY(wide_char_length_as_utf8(c)); + + u8* buf = (u8*)result; + + if (len == 1) + { + buf[0] = c & 0x7f; + return {}; + } + if (len == 2) + { + buf[0] = 0b11000000 | ((c & 0x7c0) >> 6); + buf[1] = 0b10000000 | (c & 0x3f); + return {}; + } + if (len == 3) + { + buf[0] = 0b11100000 | ((c & 0xf000) >> 12); + buf[1] = 0b10000000 | ((c & 0xfc0) >> 6); + buf[2] = 0b10000000 | (c & 0x3f); + return {}; + } + if (len == 4) + { + buf[0] = 0b11110000 | ((c & 0x1c0000) >> 18); + buf[1] = 0b10000000 | ((c & 0x3f000) >> 12); + buf[2] = 0b10000000 | ((c & 0xfc0) >> 6); + buf[3] = 0b10000000 | (c & 0x3f); + return {}; + } + + unreachable(); +} + +static Result encode_utf8_as_wide_char(const char* beg, usize& len) { usize utf8_len = TRY(utf8_char_length(*beg)); if (utf8_len > len) return err(EILSEQ); // Unterminated sequence @@ -82,7 +127,7 @@ Result Utf8StringDecoder::decode(wchar_t* buf) const while ((usize)(it - m_str) < m_byte_length) { usize len = m_byte_length - (usize)(it - m_str); // Remaining space - *buf = TRY(encode_utf8_char_into_wide_char(it, len)); + *buf = TRY(encode_utf8_as_wide_char(it, len)); it += len; buf++; } @@ -92,6 +137,41 @@ Result Utf8StringDecoder::decode(wchar_t* buf) const return {}; } +Utf8StringEncoder::Utf8StringEncoder(const wchar_t* str) : m_str(str), m_code_points(wcslen(str)) +{ +} + +Result Utf8StringEncoder::byte_length() const +{ + const wchar_t* it = m_str; + usize len = 0; + + while (*it) + { + len += TRY(wide_char_length_as_utf8(*it)); + it++; + } + + return len; +} + +Result Utf8StringEncoder::encode(char* buf) const +{ + const wchar_t* it = m_str; + + while (*it) + { + usize len = 0; + TRY(encode_wide_char_as_utf8(*it, buf, len)); + buf += len; + it++; + } + + *buf = 0; + + return {}; +} + Utf8StateDecoder::Utf8StateDecoder() : m_state_len(0), m_state_index(0) { } @@ -117,7 +197,7 @@ Result> Utf8StateDecoder::feed(char c) if (m_state_index == m_state_len - 1) { usize len = m_state_len; - wchar_t wc = TRY(encode_utf8_char_into_wide_char(m_state, len)); + wchar_t wc = TRY(encode_utf8_as_wide_char(m_state, len)); m_state_len = 0; return Option{wc}; } @@ -128,4 +208,13 @@ Result> Utf8StateDecoder::feed(char c) void Utf8StateDecoder::reset() { m_state_index = m_state_len = 0; +} + +Result Utf8Encoder::encode(wchar_t c, char buf[4]) +{ + usize len = 0; + + TRY(encode_wide_char_as_utf8(c, buf, len)); + + return len; } \ No newline at end of file From ffd3385d0d525f92d121ecebfa3c5533de0249cd Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 14:42:53 +0100 Subject: [PATCH 284/407] TextConsole: decoder -> utf8_decoder --- kernel/src/video/TextConsole.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index a8932acc..7d124a06 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -23,7 +23,7 @@ static constexpr u32 FONT_WIDTH = 8; static u32 g_x_position = 0; static u32 g_y_position = 0; -static Utf8StateDecoder decoder; +static Utf8StateDecoder utf8_decoder; static void putwchar_at(wchar_t c, u32 x, u32 y) { @@ -123,10 +123,10 @@ namespace TextConsole // FIXME: Should this function propagate errors? void putchar(char c) { - auto rc = decoder.feed(c); + auto rc = utf8_decoder.feed(c); if (rc.has_error()) { - decoder.reset(); + utf8_decoder.reset(); return; } From b01878cd3ca1ad710c970d1ab19897091332f78a Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 14:55:04 +0100 Subject: [PATCH 285/407] Update README.md --- README.md | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2def0b6c..6c4f7b82 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,25 @@ A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C. [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg?ref=refs/heads/restart)](https://drone.cloudapio.eu/apio/Luna) (rewrite, listed features are currently mostly from the old version) ## Features -- x86_64-compatible [kernel](kernel/). -- Keeps track of which [memory](kernel/src/memory/) is used and which memory is free, and can allocate memory for itself and [user programs](kernel/src/sys/mem.cpp). -- Can read, write and execute files from a [virtual file system](kernel/src/fs/) supporting an initial ramdisk, device pseudo-filesystems... but no hard disks yet. -- Preemptive multitasking, with a round-robin [scheduler](kernel/src/thread/) that can switch between tasks. -- Can [load ELF programs](kernel/src/sys/elf/) from the file system as userspace tasks. -- [System call](kernel/src/sys/) interface and [C Library](libs/libc/), aiming to be mostly POSIX-compatible. -- UNIX-like [multitasking primitives](kernel/src/sys/exec.cpp), which allow user tasks to spawn other tasks. -- Some simple [userspace programs](apps/src/), written in C. -- Simple [command-line shell](apps/src/sh.c), allowing for interactive use of the system. -- Basic multi-user system with [a password file](initrd/etc/passwd) and utilities for [logging in](apps/src/session.c) and [switching users](apps/src/su.c). +- x86_64-compatible [kernel](kernel/). (Rewritten) +- Keeps track of [memory](kernel/src/memory/). (Rewritten) +- Can read, write and execute files from a [virtual file system](kernel/src/fs/) supporting an initial ramdisk, device pseudo-filesystems... but no hard disks yet. (Not there yet) +- Preemptive multitasking, with a round-robin [scheduler](kernel/src/thread/) that can switch between tasks. (Rewritten) +- Can [load ELF programs](kernel/src/sys/elf/) from the file system as userspace tasks. (Not there yet) +- [System call](kernel/src/sys/) interface and [C Library](libs/libc/), aiming to be mostly POSIX-compatible. (Not there yet) +- UNIX-like [multitasking primitives](kernel/src/sys/exec.cpp), which allow user tasks to spawn other tasks. (Not there yet) +- Some simple [userspace programs](apps/src/), written in C. (Not there yet) +- Simple [command-line shell](apps/src/sh.c), allowing for interactive use of the system. (Not there yet) +- Basic multi-user system with [a password file](initrd/etc/passwd) and utilities for [logging in](apps/src/session.c) and [switching users](apps/src/su.c). (Not there yet) + +## New features (in the rewrite) +- Easier [portability](kernel/src/arch), no need to be restricted to x86_64. +- Fully [UTF-8 aware](luna/include/luna/Utf8.h), **everywhere**. +- More [thread](luna/include/luna/Atomic.h) [safety](kernel/src/thread/Spinlock.h). +- Environment-agnostic [utility library](luna/), which can be used in both kernel and userspace. +- Improved [error propagation](luna/include/luna/Result.h), inspired by Rust and SerenityOS. +- Better code quality and readability. +- Build system now uses [CMake](CMakeLists.txt), which makes everything a lot easier. ## Notes - The default user is named 'selene' and you can log into it with the password 'moon'. @@ -34,8 +43,6 @@ This script will check whether you have the required versions of the toolchain a Please beware that building GCC and Binutils can take some time, depending on your machine. ## Building -Yes, there is a Makefile sitting on the top level of the repository. It's tempting. But do not use it directly, since it depends on environment variables set by the build scripts. - There are a variety of scripts for building Luna. `tools/build.sh` will build the kernel, libc and binaries. @@ -52,7 +59,7 @@ There are a variety of scripts for building Luna. `tools/rebuild-iso.sh` will do a clean rebuild, install, and make an ISO disk image. -In most cases, you should just use `build-iso.sh`. +In most cases, you should just use `run.sh`, but if you want to build without running, `build-iso.sh`. ## Running @@ -60,13 +67,13 @@ You should have [QEMU](https://www.qemu.org/) installed. You can choose between 3 run scripts: -`tools/run.sh` is the one you should use in most cases. It will build (only files that have changed since last build), install, make an ISO image, and run Luna in QEMU. +`tools/run.sh` is the one you should use in most cases. It will build changed files, install, make an ISO image, and run Luna in QEMU. `tools/rebuild-and-run.sh` will rebuild, install, make an ISO, and run Luna in QEMU. `tools/debug.sh` will run Luna in QEMU with a port open for GDB to connect to. (run `tools/build-debug.sh`, `tools/gdb.sh`, and then `tools/debug.sh` in a separate terminal for an optimal debugging experience) -Beware that running with optimizations disabled may cause the kernel to behave differently, which is why I don't use it that often. +Beware that running without hardware acceleration does some weird stuff with the memory map, which is why I don't use it that often. Essentially, since `run.sh` builds the toolchain if it hasn't been built, builds Luna if it hasn't been built, and runs it, you could just checkout this repo, run `run.sh`, and you're done. No need for the other scripts. Those are included for more fine-grained control/building step-by-step. @@ -82,8 +89,14 @@ Every hour, my server pulls the latest commits on `main` and builds an hourly IS These images do reflect the latest changes on the `main` branch, but are obviously less stable. Additionally, an hourly image will be skipped if building the latest commit of the project fails. +Until the `restart` branch gets merged, you'll have to build an ISO yourself. + ## Is there third-party software I can use on Luna? +No, not on this branch. + +**ORIGINAL ANSWER** + Yes, actually! Check out the [ports](ports/) directory. Right now, there are very few ports, because our C Library is a bit primitive and doesn't support complex projects. From 730d0682eea4359fa3027bca5077561c6c825ca0 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 16:30:09 +0100 Subject: [PATCH 286/407] Result: Add try_set_value_with_specific_error() --- luna/include/luna/Result.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index b012ffab..38143c7e 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -90,6 +90,13 @@ template class Result return m_value.try_set_value(ref); } + Result try_set_value_with_specific_error(T& ref, int error) + { + if (has_error() && m_error != error) return release_error(); + + return m_value.try_set_value(ref); + } + T release_value() { expect(has_value(), "Result::release_value() called on a Result that holds an error"); From 0d65f188f05d4d712d6437c80cc4aff8b6e5faeb Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 16:30:27 +0100 Subject: [PATCH 287/407] Alignment.h: Include the Types --- luna/include/luna/Alignment.h | 1 + 1 file changed, 1 insertion(+) diff --git a/luna/include/luna/Alignment.h b/luna/include/luna/Alignment.h index 02e04d92..f6f127dc 100644 --- a/luna/include/luna/Alignment.h +++ b/luna/include/luna/Alignment.h @@ -1,5 +1,6 @@ #pragma once #include +#include // Must ALWAYS be called with a power of two as alignment. template constexpr T is_aligned(T value) From eadca3d25bb2763202a7a0ce6bc9706893e2eb96 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 16:31:02 +0100 Subject: [PATCH 288/407] Add nullcpy() Invented function to memcpy() with a specific size, but add a null terminator. --- luna/include/luna/CString.h | 3 +++ luna/src/CString.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/luna/include/luna/CString.h b/luna/include/luna/CString.h index b1026be3..d677104a 100644 --- a/luna/include/luna/CString.h +++ b/luna/include/luna/CString.h @@ -12,4 +12,7 @@ extern "C" usize wcslen(const wchar_t* str); char* strdup(const char* str); + + // Copies len bytes from src into dest and adds a null terminator. + void nullcpy(char* dest, const char* src, usize len); } \ No newline at end of file diff --git a/luna/src/CString.cpp b/luna/src/CString.cpp index 79580e6f..7bb47ee7 100644 --- a/luna/src/CString.cpp +++ b/luna/src/CString.cpp @@ -65,4 +65,10 @@ extern "C" return dest; } + + void nullcpy(char* dest, const char* src, usize len) + { + memcpy(dest, src, len); + dest[len] = 0; + } } \ No newline at end of file From 1d6092341a81e56069af7336138cbc376926193b Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 16:38:47 +0100 Subject: [PATCH 289/407] Add a generic TarStream class As long as it's in memory, we can use it :) --- luna/CMakeLists.txt | 1 + luna/include/luna/TarStream.h | 66 ++++++++++++++++++++++++ luna/src/TarStream.cpp | 96 +++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 luna/include/luna/TarStream.h create mode 100644 luna/src/TarStream.cpp diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 77f51628..54b55b97 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -11,6 +11,7 @@ set(FREESTANDING_SOURCES src/Alloc.cpp src/OwnedStringView.cpp src/Utf8.cpp + src/TarStream.cpp ) set(SOURCES diff --git a/luna/include/luna/TarStream.h b/luna/include/luna/TarStream.h new file mode 100644 index 00000000..baf8322d --- /dev/null +++ b/luna/include/luna/TarStream.h @@ -0,0 +1,66 @@ +#pragma once +#include +#include + +class TarStream +{ + public: + enum class EntryType + { + RegularFile, + Directory + }; + + struct Entry + { + char name[257]; + usize size; + EntryType type; + + private: + usize pos; + + friend class TarStream; + }; + + TarStream(void* base, usize size); + + void initialize(void* base, usize size); + + Result read_next_entry(); + + void rewind(); + + usize read_contents(const Entry& entry, char* buf, usize offset, usize length); + + private: + struct [[gnu::packed]] TarHeader + { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char typeflag; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; + }; + + Result find_valid_header(TarHeader* out, bool& success); + + Result read_header(TarHeader* out); + Result parse_header(const TarHeader* hdr); + + void* m_base; + void* m_pos; + usize m_size; + usize m_offset = 0; +}; \ No newline at end of file diff --git a/luna/src/TarStream.cpp b/luna/src/TarStream.cpp new file mode 100644 index 00000000..70093ac3 --- /dev/null +++ b/luna/src/TarStream.cpp @@ -0,0 +1,96 @@ +#include +#include +#include +#include + +TarStream::TarStream(void* base, usize size) : m_base(base), m_pos(base), m_size(size) +{ +} + +void TarStream::initialize(void* base, usize size) +{ + m_base = m_pos = base; + m_size = size; + m_offset = 0; +} + +void TarStream::rewind() +{ + m_pos = m_base; + m_offset = 0; +} + +Result TarStream::read_header(TarHeader* out) +{ + if ((m_offset + 512) > m_size) return err(0); + memcpy(out, m_pos, sizeof(TarHeader)); + m_pos = offset_ptr(m_pos, 512); + m_offset += 512; + return {}; +} + +Result TarStream::parse_header(const TarStream::TarHeader* hdr) +{ + Entry entry; + + char size[13]; + nullcpy(size, hdr->size, 12); + entry.size = parse_unsigned_integer(size, nullptr, 8); + + entry.pos = m_offset; + + switch (hdr->typeflag) + { + case '\0': + case '0': entry.type = EntryType::RegularFile; break; + case '5': entry.type = EntryType::Directory; break; + default: return err(EFIXME); + } + + if (!strlen(hdr->prefix)) { nullcpy(entry.name, hdr->name, 100); } + else { return err(EFIXME); } + + if (entry.size) + { + m_pos = offset_ptr(m_pos, align_up<512ul>(entry.size)); + m_offset += align_up<512ul>(entry.size); + } + + return entry; +} + +Result TarStream::find_valid_header(TarStream::TarHeader* out, bool& success) +{ + success = false; + while (true) + { + TRY(read_header(out)); + if (!memcmp(out->magic, "ustar", 5)) + { + success = true; + return {}; + } + } +} + +// FIXME: How do we know whether an error is an error or just EOF? Returning an error code of 0 as EOF seems a bit +// clunky to me... +Result TarStream::read_next_entry() +{ + bool success; + TarHeader header; + auto rc = find_valid_header(&header, success); + if (!success) return rc.release_error(); + + return parse_header(&header); +} + +usize TarStream::read_contents(const Entry& entry, char* buf, usize offset, usize length) +{ + if (offset >= entry.size) return 0; + if ((length + offset) > entry.size) length = entry.size - offset; + + memcpy(buf, offset_ptr(m_base, entry.pos + offset), length); + + return length; +} \ No newline at end of file From 6c3b7672a02692da1bc4dca39f271a5c025eaaf7 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 16:39:35 +0100 Subject: [PATCH 290/407] Kernel: Demo the initrd using TarStream Yes, we're using the physical address. Not optimal, this is only for demo purposes. --- kernel/src/main.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 1535bed2..7592b85f 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,14 +4,18 @@ #include "arch/Serial.h" #include "arch/Timer.h" #include "boot/Init.h" +#include "boot/bootboot.h" #include "config.h" #include "memory/Heap.h" #include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include +#include #include +extern const BOOTBOOT bootboot; + void async_thread() { while (true) @@ -49,6 +53,15 @@ Result init() kinfoln("Used memory: %s", to_dynamic_unit(MemoryManager::used()).release_value().chars()); kinfoln("Reserved memory: %s", to_dynamic_unit(MemoryManager::reserved()).release_value().chars()); + TarStream stream((void*)bootboot.initrd_ptr, bootboot.initrd_size); + TarStream::Entry entry; + while (TRY(stream.read_next_entry().try_set_value_with_specific_error(entry, 0))) + { + if (entry.type == TarStream::EntryType::RegularFile) + kinfoln("Found file %s in initial ramdisk, of size %s", entry.name, + to_dynamic_unit(entry.size).release_value().chars()); + } + Thread::init(); Scheduler::init(); From 4a7e48ed5d7d27ba7187a6aad88c4d26fb733916 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 17:14:12 +0100 Subject: [PATCH 291/407] Make sure wchar_t is wide enough to hold all Unicode code-points Too bad if it isn't. --- luna/src/Utf8.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/luna/src/Utf8.cpp b/luna/src/Utf8.cpp index 4445c355..0e543381 100644 --- a/luna/src/Utf8.cpp +++ b/luna/src/Utf8.cpp @@ -1,6 +1,8 @@ #include #include +static_assert(__WCHAR_MAX__ > 0x10ffff); + static Result utf8_char_length(char c) { if ((c & 0b11111000) == 0b11110000) return 4; From cda0d49a4e009c527e1740828a02ab77d7d23cd5 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 17:15:42 +0100 Subject: [PATCH 292/407] Add todo() --- luna/include/luna/Check.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/luna/include/luna/Check.h b/luna/include/luna/Check.h index faf75bd7..897c4486 100644 --- a/luna/include/luna/Check.h +++ b/luna/include/luna/Check.h @@ -25,3 +25,5 @@ #define unreachable() \ __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, "Reached unreachable code") + +#define todo() __check_failed(__FILE__, STRINGIZE_VALUE_OF(__LINE__), __PRETTY_FUNCTION__, "Reached a TODO!") From a08310ff5e1a873c3c29d4eee107e4e8b47749df Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 18:09:52 +0100 Subject: [PATCH 293/407] Add some more errno definitions --- luna/include/luna/SystemError.h | 2 ++ luna/src/SystemError.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/luna/include/luna/SystemError.h b/luna/include/luna/SystemError.h index 0c952b57..4c93724b 100644 --- a/luna/include/luna/SystemError.h +++ b/luna/include/luna/SystemError.h @@ -15,6 +15,7 @@ #define ENOMEM 12 // Cannot allocate memory #define EACCES 13 // Permission denied #define EFAULT 14 // Bad address +#define ENOTBLK 15 // Block device required #define EBUSY 16 // Device or resource busy #define EEXIST 17 // File exists #define EXDEV 18 // Invalid cross-device link @@ -25,6 +26,7 @@ #define ENFILE 23 // Too many open files in system #define EMFILE 24 // Too many open files #define ENOTTY 25 // Inappropriate ioctl for device +#define ETXTBSY 26 // Text file busy #define EFBIG 27 // File too large #define ENOSPC 28 // No space left on device #define ESPIPE 29 // Illegal seek diff --git a/luna/src/SystemError.cpp b/luna/src/SystemError.cpp index 2e1f63ad..79279044 100644 --- a/luna/src/SystemError.cpp +++ b/luna/src/SystemError.cpp @@ -19,6 +19,7 @@ const char* error_string(int error) case ENOMEM: return "Cannot allocate memory"; case EACCES: return "Permission denied"; case EFAULT: return "Bad address"; + case ENOTBLK: return "Block device required"; case EBUSY: return "Device or resource busy"; case EEXIST: return "File exists"; case EXDEV: return "Invalid cross-device link"; @@ -29,6 +30,7 @@ const char* error_string(int error) case ENFILE: return "Too many open files in system"; case EMFILE: return "Too many open files"; case ENOTTY: return "Inappropriate ioctl for device"; + case ETXTBSY: return "Text file busy"; case EFBIG: return "File too large"; case ENOSPC: return "No space left on device"; case ESPIPE: return "Illegal seek"; From 00cf267ac7dadf73cd5d65583d401413a18ade93 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 18:14:48 +0100 Subject: [PATCH 294/407] Lock EFIXME and error_string() behind a #define --- luna/include/luna/Result.h | 1 + luna/include/luna/SystemError.h | 5 ++++- luna/src/TarStream.cpp | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index 38143c7e..ed2935e3 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -1,4 +1,5 @@ #pragma once +#define _LUNA_SYSTEM_ERROR_EXTENSIONS #include #include #include diff --git a/luna/include/luna/SystemError.h b/luna/include/luna/SystemError.h index 4c93724b..a6aba0c3 100644 --- a/luna/include/luna/SystemError.h +++ b/luna/include/luna/SystemError.h @@ -54,7 +54,10 @@ #define ETIMEDOUT 110 // Connection timed out #define EALREADY 114 // Operation already in progress +#if defined(IN_MOON) || defined(USE_FREESTANDING) || defined(_LUNA_SYSTEM_ERROR_EXTENSIONS) // This one is Luna-specific. #define EFIXME 342 // Functionality not yet implemented -const char* error_string(int error); \ No newline at end of file +const char* error_string(int error); + +#endif \ No newline at end of file diff --git a/luna/src/TarStream.cpp b/luna/src/TarStream.cpp index 70093ac3..ecc85e80 100644 --- a/luna/src/TarStream.cpp +++ b/luna/src/TarStream.cpp @@ -1,3 +1,4 @@ +#define _LUNA_SYSTEM_ERROR_EXTENSIONS #include #include #include From 1b92fe36b4140b56b05fb3873b2fb02875c1a981 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 18:43:17 +0100 Subject: [PATCH 295/407] Store the stack inside a thread --- kernel/src/thread/Scheduler.cpp | 4 ++++ kernel/src/thread/Thread.h | 3 +++ luna/include/luna/Stack.h | 1 + 3 files changed, 8 insertions(+) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 225a9505..bba4f6d9 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -29,6 +29,8 @@ namespace Scheduler Stack idle_stack{idle_stack_vm, ARCH_PAGE_SIZE}; g_idle.set_sp(idle_stack.top()); + g_idle.stack = idle_stack; + kinfoln("CREATED IDLE THREAD: id %lu with ip %lx and sp %lx", g_idle.id, g_idle.ip(), g_idle.sp()); g_current = &g_idle; @@ -56,6 +58,8 @@ namespace Scheduler Stack thread_stack{thread_stack_vm, ARCH_PAGE_SIZE * 4}; thread->set_sp(thread_stack.top()); + thread->stack = thread_stack; + g_threads.append(thread); kinfoln("CREATED THREAD: id %lu with ip %lx and sp %lx", thread->id, thread->ip(), thread->sp()); diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 514d51ba..43d40007 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -2,6 +2,7 @@ #include #include +#include #ifdef ARCH_X86_64 #include "arch/x86_64/CPU.h" @@ -29,6 +30,8 @@ struct Thread : public DoublyLinkedListNode u64 ticks_left; u64 sleep_ticks_left; + Stack stack; + ThreadState state = ThreadState::Runnable; bool is_idle() diff --git a/luna/include/luna/Stack.h b/luna/include/luna/Stack.h index 7870402c..d1a73f0d 100644 --- a/luna/include/luna/Stack.h +++ b/luna/include/luna/Stack.h @@ -3,6 +3,7 @@ struct Stack { + Stack() = default; Stack(u64 base, usize bytes); u64 bottom() From 751377de0a99595b7ee8cf8b7f5bd0e4c862e2d8 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 18:43:34 +0100 Subject: [PATCH 296/407] Scheduler: Make it possible for a thread to stop existing --- kernel/src/main.cpp | 32 +++++++++++++++++++++++++++++++- kernel/src/thread/Scheduler.cpp | 33 +++++++++++++++++++++++++++++++++ kernel/src/thread/Scheduler.h | 5 ++++- kernel/src/thread/Thread.h | 3 ++- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 7592b85f..a9ebfe4e 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -35,7 +35,36 @@ void heap_thread() CPU::disable_interrupts(); dump_heap_usage(); kdbgln("Kernel uses %lu vm pages", KernelVM::used() / ARCH_PAGE_SIZE); - while (true) kernel_sleep(UINT64_MAX); + kernel_exit(); +} + +void reap_thread() +{ + while (true) + { + CPU::disable_interrupts(); + auto dying_threads = Scheduler::check_for_dying_threads(); + CPU::enable_interrupts(); + + if (dying_threads.count()) + { + Thread* thread_to_reap = dying_threads.expect_first(); + Thread* next_thread = thread_to_reap; + + while (thread_to_reap) + { + next_thread = dying_threads.next(thread_to_reap).value_or(nullptr); + kinfoln("reap: reaping thread with id %zu", thread_to_reap->id); + auto stack = thread_to_reap->stack; + kinfoln("deleting thread stack @ %#lx, has %zu bytes of stack", stack.bottom(), stack.bytes()); + MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value(); + delete thread_to_reap; + thread_to_reap = next_thread; + } + } + + kernel_sleep(250); + } } Result init() @@ -67,6 +96,7 @@ Result init() TRY(Scheduler::new_kernel_thread(async_thread)); TRY(Scheduler::new_kernel_thread(heap_thread)); + TRY(Scheduler::new_kernel_thread(reap_thread)); CPU::platform_finish_init(); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index bba4f6d9..fc43f6c1 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -167,6 +167,32 @@ namespace Scheduler if (!g_current->ticks_left) switch_task(regs); } + + DoublyLinkedList check_for_dying_threads() + { + DoublyLinkedList result; + + Thread* thread_to_remove = nullptr; + + g_threads.for_each([&](Thread* thread) { + if (thread_to_remove) + { + g_threads.remove(thread_to_remove); + result.append(thread_to_remove); + } + + if (thread->state == ThreadState::Dying) { thread_to_remove = thread; } + else { thread_to_remove = nullptr; } + }); + + if (thread_to_remove) + { + g_threads.remove(thread_to_remove); + result.append(thread_to_remove); + } + + return result; + } } void kernel_sleep(u64 ms) @@ -174,4 +200,11 @@ void kernel_sleep(u64 ms) g_current->sleep_ticks_left = ms; g_current->state = ThreadState::Sleeping; kernel_yield(); +} + +[[noreturn]] void kernel_exit() +{ + g_current->state = ThreadState::Dying; + kernel_yield(); + unreachable(); } \ No newline at end of file diff --git a/kernel/src/thread/Scheduler.h b/kernel/src/thread/Scheduler.h index 57bb85ad..e0f71973 100644 --- a/kernel/src/thread/Scheduler.h +++ b/kernel/src/thread/Scheduler.h @@ -17,7 +17,10 @@ namespace Scheduler void switch_task(Registers* regs); void invoke(Registers* regs); + + DoublyLinkedList check_for_dying_threads(); } extern "C" void kernel_yield(); -void kernel_sleep(u64 ms); \ No newline at end of file +void kernel_sleep(u64 ms); +[[noreturn]] void kernel_exit(); \ No newline at end of file diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 43d40007..aac36c41 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -14,7 +14,8 @@ enum class ThreadState { Idle, Runnable, - Sleeping + Sleeping, + Dying }; struct Thread : public DoublyLinkedListNode From a63146a798733387ddbb6ddb9d06e694637b0207 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 18:51:25 +0100 Subject: [PATCH 297/407] Show the date and time of build :) --- kernel/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index a9ebfe4e..9d82a61c 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -69,7 +69,7 @@ void reap_thread() Result init() { - kinfoln("Starting Moon %s", MOON_VERSION); + kinfoln("Starting Moon %s, built on %s at %s", MOON_VERSION, __DATE__, __TIME__); kinfoln("Current platform: %s", CPU::platform_string()); From 283e641eceeed376f3b6d7760b4fe9d872cc8dac Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 20:36:15 +0100 Subject: [PATCH 298/407] Spinlock+LockedValue: Remove init() functions Let's set the default (unlocked) value of Spinlock's underlying atomic to 0, so even if the constructor is not called it stays like that. --- kernel/src/memory/KernelVM.cpp | 2 -- kernel/src/memory/MemoryManager.cpp | 2 -- kernel/src/thread/Spinlock.cpp | 10 +++++----- kernel/src/thread/Spinlock.h | 16 ++-------------- 4 files changed, 7 insertions(+), 23 deletions(-) diff --git a/kernel/src/memory/KernelVM.cpp b/kernel/src/memory/KernelVM.cpp index 9506f53d..74bbfa37 100644 --- a/kernel/src/memory/KernelVM.cpp +++ b/kernel/src/memory/KernelVM.cpp @@ -21,8 +21,6 @@ namespace KernelVM { void init() { - g_kernelvm_bitmap.init(); - auto kernelvm_bitmap = g_kernelvm_bitmap.lock(); kernelvm_bitmap->initialize(bitmap_memory, sizeof(bitmap_memory)); kernelvm_bitmap->clear(false); diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index f31194d6..b23c8f17 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -53,8 +53,6 @@ namespace MemoryManager MemoryMapIterator iter; MemoryMapEntry entry; - g_frame_bitmap.init(); - const auto largest_free_entry = iter.largest_free(); expect(largest_free_entry.is_free(), "We were given a largest free memory region that isn't even free!"); diff --git a/kernel/src/thread/Spinlock.cpp b/kernel/src/thread/Spinlock.cpp index 7c70e08f..8184a029 100644 --- a/kernel/src/thread/Spinlock.cpp +++ b/kernel/src/thread/Spinlock.cpp @@ -4,18 +4,18 @@ void Spinlock::lock() { - int expected = -1; - while (!m_lock.compare_exchange_strong(expected, 0)) + int expected = 0; + while (!m_lock.compare_exchange_strong(expected, 1)) { - expected = -1; + expected = 0; CPU::pause(); } } void Spinlock::unlock() { - int expected = 0; - if (!m_lock.compare_exchange_strong(expected, -1)) + int expected = 1; + if (!m_lock.compare_exchange_strong(expected, 0)) { kwarnln("Spinlock::unlock() called on an unlocked lock with value %d", expected); } diff --git a/kernel/src/thread/Spinlock.h b/kernel/src/thread/Spinlock.h index 984b6ce3..3553752c 100644 --- a/kernel/src/thread/Spinlock.h +++ b/kernel/src/thread/Spinlock.h @@ -9,17 +9,11 @@ class Spinlock bool is_locked() const { - return m_lock.load() != -1; - } - - // Call this before use if the Spinlock is a global variable. - void init() - { - m_lock = -1; + return m_lock.load() != 0; } private: - Atomic m_lock{-1}; + Atomic m_lock{0}; }; template class LockedValue @@ -68,12 +62,6 @@ template class LockedValue { } - // Call this before use if the LockedValue is a global variable. - void init() - { - m_lock.init(); - } - LockedValueGuard lock() { m_lock.lock(); From 0bdbffe0ca423304e13a479c1563c444557fba1c Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 18 Dec 2022 20:37:26 +0100 Subject: [PATCH 299/407] Spinlock+LockedValue: Add try_lock() methods For when you want to lock a resource if possible but not get blocked if it is locked by another thread. --- kernel/src/thread/Spinlock.cpp | 6 ++++++ kernel/src/thread/Spinlock.h | 25 +++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/kernel/src/thread/Spinlock.cpp b/kernel/src/thread/Spinlock.cpp index 8184a029..45cde161 100644 --- a/kernel/src/thread/Spinlock.cpp +++ b/kernel/src/thread/Spinlock.cpp @@ -12,6 +12,12 @@ void Spinlock::lock() } } +bool Spinlock::try_lock() +{ + int expected = 0; + return m_lock.compare_exchange_strong(expected, 1); +} + void Spinlock::unlock() { int expected = 1; diff --git a/kernel/src/thread/Spinlock.h b/kernel/src/thread/Spinlock.h index 3553752c..28cd0e57 100644 --- a/kernel/src/thread/Spinlock.h +++ b/kernel/src/thread/Spinlock.h @@ -1,5 +1,6 @@ #pragma once #include +#include class Spinlock { @@ -7,6 +8,8 @@ class Spinlock void lock(); void unlock(); + bool try_lock(); + bool is_locked() const { return m_lock.load() != 0; @@ -20,18 +23,26 @@ template class LockedValue { struct LockedValueGuard { - LockedValueGuard(LockedValue& value_ref) : m_value_ref(value_ref) + LockedValueGuard(LockedValue& value_ref) : m_value_ref(&value_ref) { } + LockedValueGuard(const LockedValueGuard& other) = delete; + LockedValueGuard(LockedValueGuard&& other) + { + m_value_ref = other.m_value_ref; + other.m_value_ref = nullptr; + } + ~LockedValueGuard() { - m_value_ref.m_lock.unlock(); + if (m_value_ref) m_value_ref->m_lock.unlock(); } T& ref() { - return m_value_ref.m_value; + expect(m_value_ref, "LockedValueGuard::ref() called on a moved LockedValueGuard"); + return m_value_ref->m_value; } void set(const T& other) @@ -50,7 +61,7 @@ template class LockedValue } private: - LockedValue& m_value_ref; + LockedValue* m_value_ref; }; public: @@ -68,6 +79,12 @@ template class LockedValue return {*this}; } + Option try_lock() + { + if (m_lock.try_lock()) { return {*this}; } + return {}; + } + private: T m_value; Spinlock m_lock; From 60520dff4cb55568f392bd2da519d0e14fcbab93 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 11:55:53 +0100 Subject: [PATCH 300/407] Make MemoryManager's scope guards more robust --- kernel/src/memory/MemoryManager.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index b23c8f17..33935d26 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -182,14 +182,17 @@ namespace MemoryManager CHECK_PAGE_ALIGNED(virt); CHECK_PAGE_ALIGNED(phys); - // Let's clean up after ourselves if we fail. - auto guard = make_scope_guard([=] { unmap_weak(virt, count); }); + usize pages_mapped = 0; - while (count--) + // Let's clean up after ourselves if we fail. + auto guard = make_scope_guard([=, &pages_mapped] { unmap_weak(virt, pages_mapped); }); + + while (pages_mapped < count) { TRY(MMU::map(virt, phys, flags)); virt += ARCH_PAGE_SIZE; phys += ARCH_PAGE_SIZE; + pages_mapped++; } guard.deactivate(); @@ -202,14 +205,16 @@ namespace MemoryManager CHECK_PAGE_ALIGNED(virt); u64 start = virt; + usize pages_mapped = 0; - auto guard = make_scope_guard([=] { unmap_owned(start, count); }); + auto guard = make_scope_guard([=, &pages_mapped] { unmap_owned(start, pages_mapped); }); - while (count--) + while (pages_mapped < count) { u64 frame = TRY(alloc_frame()); TRY(MMU::map(virt, frame, flags)); virt += ARCH_PAGE_SIZE; + pages_mapped++; } guard.deactivate(); @@ -220,20 +225,21 @@ namespace MemoryManager Result alloc_for_kernel(usize count, int flags) { u64 start = TRY(KernelVM::alloc_several_pages(count)); + usize pages_mapped = 0; - auto guard = make_scope_guard([=] { - KernelVM::free_several_pages(start, count); - // unmap_owned will fail as soon as we reach the end of the mapped range. That's fine, exactly what we want. - unmap_owned(start, count); + auto guard = make_scope_guard([=, &pages_mapped] { + KernelVM::free_several_pages(start, pages_mapped); + unmap_owned(start, pages_mapped); }); u64 virt = start; - while (count--) + while (pages_mapped < count) { u64 frame = TRY(alloc_frame()); TRY(MMU::map(virt, frame, flags)); virt += ARCH_PAGE_SIZE; + pages_mapped++; } guard.deactivate(); From 9eb829f3a27cc535100a573b01bf93732f96894c Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 12:20:56 +0100 Subject: [PATCH 301/407] CString: Add strcmp() --- luna/include/luna/CString.h | 1 + luna/src/CString.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/luna/include/luna/CString.h b/luna/include/luna/CString.h index d677104a..8b606af7 100644 --- a/luna/include/luna/CString.h +++ b/luna/include/luna/CString.h @@ -8,6 +8,7 @@ extern "C" int memcmp(const void* a, const void* b, usize n); void* memmove(void* dest, const void* src, usize n); usize strlen(const char* str); + int strcmp(const char* a, const char* b); usize wcslen(const wchar_t* str); diff --git a/luna/src/CString.cpp b/luna/src/CString.cpp index 7bb47ee7..83d15661 100644 --- a/luna/src/CString.cpp +++ b/luna/src/CString.cpp @@ -46,6 +46,16 @@ extern "C" return (usize)(i - str); } + int strcmp(const char* a, const char* b) + { + while (*a && (*a == *b)) + { + a++; + b++; + } + return *(const u8*)a - *(const u8*)b; + } + usize wcslen(const wchar_t* str) { const wchar_t* i = str; From 31ee901e01eccdc503d9bfa06260cb78871209a1 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 12:21:17 +0100 Subject: [PATCH 302/407] TarStream: Add a variant of read_contents() returning an OwnedStringView --- luna/include/luna/TarStream.h | 3 +++ luna/src/TarStream.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/luna/include/luna/TarStream.h b/luna/include/luna/TarStream.h index baf8322d..b4f62402 100644 --- a/luna/include/luna/TarStream.h +++ b/luna/include/luna/TarStream.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include @@ -33,6 +34,8 @@ class TarStream usize read_contents(const Entry& entry, char* buf, usize offset, usize length); + Result read_contents_as_string(const Entry& entry, usize offset, usize max); + private: struct [[gnu::packed]] TarHeader { diff --git a/luna/src/TarStream.cpp b/luna/src/TarStream.cpp index ecc85e80..1dee4edd 100644 --- a/luna/src/TarStream.cpp +++ b/luna/src/TarStream.cpp @@ -1,5 +1,6 @@ #define _LUNA_SYSTEM_ERROR_EXTENSIONS #include +#include #include #include #include @@ -94,4 +95,15 @@ usize TarStream::read_contents(const Entry& entry, char* buf, usize offset, usiz memcpy(buf, offset_ptr(m_base, entry.pos + offset), length); return length; +} + +Result TarStream::read_contents_as_string(const Entry& entry, usize offset, usize max) +{ + char* buf = TRY(make_array(max + 1)); + + usize nread = read_contents(entry, buf, offset, max); + + buf[nread] = 0; + + return OwnedStringView{buf}; } \ No newline at end of file From 92a7004c2fbbdc1bcc31c0ffb6e53ca62a65f06e Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 12:24:15 +0100 Subject: [PATCH 303/407] Move the reaping logic to Scheduler --- kernel/src/main.cpp | 17 +++++++++++------ kernel/src/thread/Scheduler.cpp | 10 ++++++++++ kernel/src/thread/Scheduler.h | 2 ++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9d82a61c..dc8a367b 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,7 +1,6 @@ #include "Log.h" #include "arch/CPU.h" #include "arch/MMU.h" -#include "arch/Serial.h" #include "arch/Timer.h" #include "boot/Init.h" #include "boot/bootboot.h" @@ -10,6 +9,7 @@ #include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include "thread/Scheduler.h" +#include #include #include #include @@ -54,11 +54,7 @@ void reap_thread() while (thread_to_reap) { next_thread = dying_threads.next(thread_to_reap).value_or(nullptr); - kinfoln("reap: reaping thread with id %zu", thread_to_reap->id); - auto stack = thread_to_reap->stack; - kinfoln("deleting thread stack @ %#lx, has %zu bytes of stack", stack.bottom(), stack.bytes()); - MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value(); - delete thread_to_reap; + Scheduler::reap_thread(thread_to_reap); thread_to_reap = next_thread; } } @@ -87,8 +83,17 @@ Result init() while (TRY(stream.read_next_entry().try_set_value_with_specific_error(entry, 0))) { if (entry.type == TarStream::EntryType::RegularFile) + { kinfoln("Found file %s in initial ramdisk, of size %s", entry.name, to_dynamic_unit(entry.size).release_value().chars()); + + if (!strcmp(entry.name, "sys/config")) + { + auto contents = TRY(stream.read_contents_as_string(entry, 0, entry.size)); + + kinfoln("%s", contents.chars()); + } + } } Thread::init(); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index fc43f6c1..31e556ed 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -95,6 +95,16 @@ namespace Scheduler return new_kernel_thread_impl(thread); } + void reap_thread(Thread* thread) + { + kinfoln("reap: reaping thread with id %zu", thread->id); + auto stack = thread->stack; + kinfoln("deleting thread stack @ %#lx, has %zu bytes of stack", stack.bottom(), stack.bytes()); + // FIXME: Propagate errors I guess? + MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value(); + delete thread; + } + Thread* pick_task() { Thread* old = g_current; diff --git a/kernel/src/thread/Scheduler.h b/kernel/src/thread/Scheduler.h index e0f71973..b0c686ac 100644 --- a/kernel/src/thread/Scheduler.h +++ b/kernel/src/thread/Scheduler.h @@ -14,6 +14,8 @@ namespace Scheduler Thread* pick_task(); + void reap_thread(Thread* thread); + void switch_task(Registers* regs); void invoke(Registers* regs); From 5b72144fac518345331380684f9380a007078f4b Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 12:35:08 +0100 Subject: [PATCH 304/407] Add a handy consume() method to LinkedList --- kernel/src/main.cpp | 13 +------------ luna/include/luna/LinkedList.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index dc8a367b..a8e8622d 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -46,18 +46,7 @@ void reap_thread() auto dying_threads = Scheduler::check_for_dying_threads(); CPU::enable_interrupts(); - if (dying_threads.count()) - { - Thread* thread_to_reap = dying_threads.expect_first(); - Thread* next_thread = thread_to_reap; - - while (thread_to_reap) - { - next_thread = dying_threads.next(thread_to_reap).value_or(nullptr); - Scheduler::reap_thread(thread_to_reap); - thread_to_reap = next_thread; - } - } + dying_threads.consume([](Thread* thread) { Scheduler::reap_thread(thread); }); kernel_sleep(250); } diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 50615134..65a55b91 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -155,26 +155,45 @@ template class DoublyLinkedList return nonnull_or_error((T*)extract_node(item)->get_last()); } + // Iterates over the elements of the DoublyLinkedList from start to end, calling callback for every element. template void for_each(Callback callback) { for (Node* node = m_start_node; node; node = node->get_next()) { callback((T*)node); } } + // Iterates over the elements of the DoublyLinkedList from end to start, calling callback for every element. template void for_each_reversed(Callback callback) { for (Node* node = m_end_node; node; node = node->get_last()) { callback((T*)node); } } + // Iterates over the elements of the DoublyLinkedList from the element after 'start' to end, calling callback for + // every element. template void for_each_after(T* start, Callback callback) { for (Node* node = extract_node(start)->m_next_node; node; node = node->get_next()) { callback((T*)node); } } + // Iterates over the elements of the DoublyLinkedList from the element before 'end' to start, calling callback for + // every element. template void for_each_before(T* end, Callback callback) { for (Node* node = extract_node(end)->m_last_node; node; node = node->get_last()) { callback((T*)node); } } + // Iterates over the elements of the DoublyLinkedList from start to end, removing each element before passing it to + // the callback. + template void consume(Callback callback) + { + for (Node* node = m_start_node; node;) + { + T* current = (T*)node; + node = node->get_next(); + remove(current); + callback(current); + } + } + usize count() { return m_count; From 1269a045bd8ea81266195856e5e0271edf411f07 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 12:41:25 +0100 Subject: [PATCH 305/407] LinkedList: Add a convenience delayed_for_each() method. This is a special way of iterating over the list which permits removing items while iterating. --- kernel/src/thread/Scheduler.cpp | 19 ++++--------------- luna/include/luna/LinkedList.h | 12 ++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 31e556ed..d961edf0 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -182,25 +182,14 @@ namespace Scheduler { DoublyLinkedList result; - Thread* thread_to_remove = nullptr; - - g_threads.for_each([&](Thread* thread) { - if (thread_to_remove) + g_threads.delayed_for_each([&](Thread* thread) { + if (thread->state == ThreadState::Dying) { - g_threads.remove(thread_to_remove); - result.append(thread_to_remove); + g_threads.remove(thread); + result.append(thread); } - - if (thread->state == ThreadState::Dying) { thread_to_remove = thread; } - else { thread_to_remove = nullptr; } }); - if (thread_to_remove) - { - g_threads.remove(thread_to_remove); - result.append(thread_to_remove); - } - return result; } } diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 65a55b91..0ea2ecc3 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -161,6 +161,18 @@ template class DoublyLinkedList for (Node* node = m_start_node; node; node = node->get_next()) { callback((T*)node); } } + // Iterates over the elements of the DoublyLinkedList from start to end, calling callback for every element. This + // for_each is implemented in such a way that elements can be removed while iterating over it. + template void delayed_for_each(Callback callback) + { + for (Node* node = m_start_node; node;) + { + T* current = (T*)node; + node = node->get_next(); + callback(current); + } + } + // Iterates over the elements of the DoublyLinkedList from end to start, calling callback for every element. template void for_each_reversed(Callback callback) { From a11a5dec1fbf9fba939b65033ae88d9e8ac20c6c Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 12:43:23 +0100 Subject: [PATCH 306/407] DoublyLinkedList -> LinkedList --- kernel/src/memory/Heap.cpp | 4 ++-- kernel/src/thread/Scheduler.cpp | 4 ++-- kernel/src/thread/Scheduler.h | 2 +- kernel/src/thread/Thread.cpp | 2 +- kernel/src/thread/Thread.h | 4 ++-- luna/include/luna/LinkedList.h | 26 +++++++++++++------------- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 77e5ac24..e0abe5c8 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -26,7 +26,7 @@ static constexpr usize BLOCK_DEAD = 0xdeaddeaddeaddead; static constexpr usize MINIMUM_PAGES_PER_ALLOCATION = 4; -struct HeapBlock : DoublyLinkedListNode +struct HeapBlock : LinkedListNode { usize req_size; usize full_size; @@ -38,7 +38,7 @@ static_assert(sizeof(HeapBlock) == 48UL); static const isize HEAP_BLOCK_SIZE = 48; -static DoublyLinkedList heap; +static LinkedList heap; static Result allocate_pages(usize count) { diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index d961edf0..7e0f7acd 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -178,9 +178,9 @@ namespace Scheduler if (!g_current->ticks_left) switch_task(regs); } - DoublyLinkedList check_for_dying_threads() + LinkedList check_for_dying_threads() { - DoublyLinkedList result; + LinkedList result; g_threads.delayed_for_each([&](Thread* thread) { if (thread->state == ThreadState::Dying) diff --git a/kernel/src/thread/Scheduler.h b/kernel/src/thread/Scheduler.h index b0c686ac..10a47534 100644 --- a/kernel/src/thread/Scheduler.h +++ b/kernel/src/thread/Scheduler.h @@ -20,7 +20,7 @@ namespace Scheduler void invoke(Registers* regs); - DoublyLinkedList check_for_dying_threads(); + LinkedList check_for_dying_threads(); } extern "C" void kernel_yield(); diff --git a/kernel/src/thread/Thread.cpp b/kernel/src/thread/Thread.cpp index 48540869..22cdebac 100644 --- a/kernel/src/thread/Thread.cpp +++ b/kernel/src/thread/Thread.cpp @@ -4,7 +4,7 @@ static Atomic g_next_id; -DoublyLinkedList g_threads; +LinkedList g_threads; void Thread::init() { diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index aac36c41..6e8cc628 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -18,7 +18,7 @@ enum class ThreadState Dying }; -struct Thread : public DoublyLinkedListNode +struct Thread : public LinkedListNode { Registers regs; @@ -60,4 +60,4 @@ bool is_in_kernel(Registers* regs); Result new_thread(); -extern DoublyLinkedList g_threads; \ No newline at end of file +extern LinkedList g_threads; \ No newline at end of file diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 0ea2ecc3..63b858b8 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -9,11 +9,11 @@ template inline Option nonnull_or_error(T* ptr) return ptr; } -template class DoublyLinkedList; +template class LinkedList; -template class DoublyLinkedListNode +template class LinkedListNode { - using SelfType = DoublyLinkedListNode; + using SelfType = LinkedListNode; private: SelfType* m_next_node; @@ -57,14 +57,14 @@ template class DoublyLinkedListNode this->m_next_node = start_node; } - friend class DoublyLinkedList; + friend class LinkedList; }; -template class DoublyLinkedList +template class LinkedList { - using Node = DoublyLinkedListNode; + using Node = LinkedListNode; - static_assert(IsBaseOf, T>); + static_assert(IsBaseOf, T>); public: void append(T* ptr) @@ -155,13 +155,13 @@ template class DoublyLinkedList return nonnull_or_error((T*)extract_node(item)->get_last()); } - // Iterates over the elements of the DoublyLinkedList from start to end, calling callback for every element. + // Iterates over the elements of the LinkedList from start to end, calling callback for every element. template void for_each(Callback callback) { for (Node* node = m_start_node; node; node = node->get_next()) { callback((T*)node); } } - // Iterates over the elements of the DoublyLinkedList from start to end, calling callback for every element. This + // Iterates over the elements of the LinkedList from start to end, calling callback for every element. This // for_each is implemented in such a way that elements can be removed while iterating over it. template void delayed_for_each(Callback callback) { @@ -173,27 +173,27 @@ template class DoublyLinkedList } } - // Iterates over the elements of the DoublyLinkedList from end to start, calling callback for every element. + // Iterates over the elements of the LinkedList from end to start, calling callback for every element. template void for_each_reversed(Callback callback) { for (Node* node = m_end_node; node; node = node->get_last()) { callback((T*)node); } } - // Iterates over the elements of the DoublyLinkedList from the element after 'start' to end, calling callback for + // Iterates over the elements of the LinkedList from the element after 'start' to end, calling callback for // every element. template void for_each_after(T* start, Callback callback) { for (Node* node = extract_node(start)->m_next_node; node; node = node->get_next()) { callback((T*)node); } } - // Iterates over the elements of the DoublyLinkedList from the element before 'end' to start, calling callback for + // Iterates over the elements of the LinkedList from the element before 'end' to start, calling callback for // every element. template void for_each_before(T* end, Callback callback) { for (Node* node = extract_node(end)->m_last_node; node; node = node->get_last()) { callback((T*)node); } } - // Iterates over the elements of the DoublyLinkedList from start to end, removing each element before passing it to + // Iterates over the elements of the LinkedList from start to end, removing each element before passing it to // the callback. template void consume(Callback callback) { From 042f9996770174dbb4ccc4eaa4053b561ea8f8fa Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 13:20:38 +0100 Subject: [PATCH 307/407] Heap: SCRUB IT ALL If your memory is all 0xacacacac there is a big probability you haven't initialized it. --- kernel/src/memory/Heap.cpp | 20 ++++++++++++++++---- kernel/src/memory/Heap.h | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index e0abe5c8..ec590d74 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -24,6 +24,9 @@ static constexpr int BLOCK_END_MEM = 1 << 2; static constexpr usize BLOCK_MAGIC = 0x6d616c6c6f63210a; // echo 'malloc!' | hexdump -C (includes a newline) static constexpr usize BLOCK_DEAD = 0xdeaddeaddeaddead; +static constexpr u8 KMALLOC_SCRUB_BYTE = 0xac; +static constexpr u8 KFREE_SCRUB_BYTE = 0xde; + static constexpr usize MINIMUM_PAGES_PER_ALLOCATION = 4; struct HeapBlock : LinkedListNode @@ -166,7 +169,7 @@ static Result combine_backward(HeapBlock* block) return last; } -Result kmalloc(usize size) +Result kmalloc(usize size, bool should_scrub) { if (!size) return (void*)BLOCK_MAGIC; @@ -219,6 +222,8 @@ Result kmalloc(usize size) block->req_size = size; block->status |= BLOCK_USED; + if (should_scrub) { memset(get_pointer_from_heap_block(block), KMALLOC_SCRUB_BYTE, size); } + return get_pointer_from_heap_block(block); } @@ -249,6 +254,8 @@ Result kfree(void* ptr) else block->status &= ~BLOCK_USED; + memset(ptr, KFREE_SCRUB_BYTE, block->req_size); + auto maybe_next = heap.next(block); if (maybe_next.has_value() && is_block_free(maybe_next.value())) { @@ -307,21 +314,26 @@ Result krealloc(void* ptr, usize size) if (block->full_size >= size) { // This block is already large enough! + // FIXME: Scrub this if necessary. block->req_size = size; return ptr; } - void* const new_ptr = TRY(kmalloc(size)); - memcpy(new_ptr, ptr, block->req_size > size ? size : block->req_size); + usize old_size = block->req_size; + + void* const new_ptr = TRY(kmalloc(size, false)); + memcpy(new_ptr, ptr, old_size > size ? size : old_size); TRY(kfree(ptr)); + if (old_size < size) { memset(offset_ptr(new_ptr, old_size), KMALLOC_SCRUB_BYTE, size - old_size); } + return new_ptr; } Result kcalloc(usize nmemb, usize size) { const usize realsize = TRY(safe_mul(nmemb, size)); - void* const ptr = TRY(kmalloc(realsize)); + void* const ptr = TRY(kmalloc(realsize, false)); return memset(ptr, 0, realsize); } diff --git a/kernel/src/memory/Heap.h b/kernel/src/memory/Heap.h index 6e57f744..7d13d69a 100644 --- a/kernel/src/memory/Heap.h +++ b/kernel/src/memory/Heap.h @@ -2,7 +2,7 @@ #include #include -Result kmalloc(usize size); +Result kmalloc(usize size, bool should_scrub = true); Result kcalloc(usize nmemb, usize size); Result krealloc(void* ptr, usize size); Result kfree(void* ptr); From 703c3f44fb6a12045517a0b88454e5c2003c1f68 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 21:41:27 +0100 Subject: [PATCH 308/407] Add two FIXMEs --- kernel/src/Log.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 005dcef3..ec884832 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -26,6 +26,7 @@ static void log_serial(LogLevel level, const char* format, va_list origin) Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000)); + // FIXME: We do this manually because of a lack of vprintf() in both Serial and TextConsole. pure_cstyle_format( format, [](char c, void*) { Serial::putchar((u8)c); }, nullptr, ap); @@ -50,6 +51,7 @@ static void log_text_console(LogLevel level, const char* format, va_list origin) else TextConsole::set_foreground(WHITE); + // FIXME: Same as above. pure_cstyle_format( format, [](char c, void*) { TextConsole::putchar(c); }, nullptr, ap); From e2a6cba3c6f46e9e1f88fe723554f66a5fc9a7c2 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 19 Dec 2022 21:42:53 +0100 Subject: [PATCH 309/407] Log: Update formatting to make ANSI weirdness more sensible --- kernel/src/Log.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index ec884832..7342419c 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -22,7 +22,10 @@ static void log_serial(LogLevel level, const char* format, va_list origin) va_list ap; va_copy(ap, origin); - Serial::printf("\x1b[%sm%c\x1b[0m ", ansi_color_codes_per_log_level[(int)level], log_level_letters[(int)level]); + Serial::printf("\x1b[%sm" + "%c" + "\x1b[0m ", + ansi_color_codes_per_log_level[(int)level], log_level_letters[(int)level]); Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000)); From 7a2cb284751daeae6649084706181696e74f2b01 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 20 Dec 2022 17:12:44 +0100 Subject: [PATCH 310/407] Make sure isize matches ssize_t on most cases --- luna/include/luna/Types.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/luna/include/luna/Types.h b/luna/include/luna/Types.h index 0abcefa7..f75bb652 100644 --- a/luna/include/luna/Types.h +++ b/luna/include/luna/Types.h @@ -10,7 +10,7 @@ typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; typedef size_t usize; -typedef int64_t isize; +typedef intptr_t isize; static_assert(sizeof(u8) == 1UL); static_assert(sizeof(u16) == 2UL); @@ -21,5 +21,5 @@ static_assert(sizeof(i16) == 2UL); static_assert(sizeof(i32) == 4UL); static_assert(sizeof(i64) == 8UL); -static_assert(sizeof(usize) == 8UL); -static_assert(sizeof(isize) == 8UL); \ No newline at end of file +static_assert(sizeof(usize) == sizeof(void*)); +static_assert(sizeof(isize) == sizeof(void*)); \ No newline at end of file From 2e8ea724a0acd3ba834ef37d7b21c5acef496a5b Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 21 Dec 2022 17:21:01 +0100 Subject: [PATCH 311/407] arch/x86_64: Refactor the stack tracing code to remove duplicate code --- kernel/src/arch/x86_64/CPU.cpp | 36 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 56606059..5a725e88 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -184,11 +184,9 @@ namespace CPU u64 instruction; }; - void get_stack_trace(void (*callback)(u64, void*), void* arg) + static void backtrace_impl(u64 base_pointer, void (*callback)(u64, void*), void* arg) { - u64 rbp; - asm volatile("mov %%rbp, %0" : "=r"(rbp)); - StackFrame* current_frame = (StackFrame*)rbp; + StackFrame* current_frame = (StackFrame*)base_pointer; // FIXME: Validate that the frame itself is readable, might span across multiple pages while (current_frame && MemoryManager::validate_readable_page((u64)current_frame)) { @@ -197,30 +195,32 @@ namespace CPU } } + void get_stack_trace(void (*callback)(u64, void*), void* arg) + { + u64 rbp; + asm volatile("mov %%rbp, %0" : "=r"(rbp)); + return backtrace_impl(rbp, callback, arg); + } + void print_stack_trace() { u64 rbp; int frame_index = 0; asm volatile("mov %%rbp, %0" : "=r"(rbp)); - StackFrame* current_frame = (StackFrame*)rbp; - // FIXME: Validate that the frame itself is readable, might span across multiple pages - while (current_frame && MemoryManager::validate_readable_page((u64)current_frame)) - { - kinfoln("#%d at %p", frame_index++, (void*)current_frame->instruction); - current_frame = current_frame->next; - } + return backtrace_impl( + rbp, + [](u64 instruction, void* arg) { + int* ptr = (int*)arg; + kinfoln("#%d at %p", *ptr, (void*)instruction); + (*ptr)++; + }, + &frame_index); } void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg) { callback(regs->rip, arg); - StackFrame* current_frame = (StackFrame*)regs->rbp; - // FIXME: Validate that the frame itself is readable, might span across multiple pages - while (current_frame && MemoryManager::validate_readable_page((u64)current_frame)) - { - callback(current_frame->instruction, arg); - current_frame = current_frame->next; - } + return backtrace_impl(regs->rbp, callback, arg); } void print_stack_trace_at(Registers* regs) From 293b7b0f11052f3b0f5ff78e01299831dfb690cd Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 21 Dec 2022 17:38:19 +0100 Subject: [PATCH 312/407] TextConsole: Propagate UTF-8 decoding errors --- kernel/src/Log.cpp | 17 ++++++++++++--- kernel/src/video/TextConsole.cpp | 36 +++++++++++++++++--------------- kernel/src/video/TextConsole.h | 8 +++---- 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 7342419c..d13d9e0e 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -55,10 +55,21 @@ static void log_text_console(LogLevel level, const char* format, va_list origin) TextConsole::set_foreground(WHITE); // FIXME: Same as above. - pure_cstyle_format( - format, [](char c, void*) { TextConsole::putchar(c); }, nullptr, ap); + auto rc = cstyle_format( + format, [](char c, void*) -> Result { return TextConsole::putchar(c); }, nullptr, ap); - TextConsole::putchar('\n'); + if (rc.has_error()) + { + // FIXME: Find a way to do this in a simpler way (TextConsole::wprint maybe?) + const wchar_t* s = L"Invalid UTF-8 in log message"; + while (*s) + { + TextConsole::putwchar(*s); + s++; + } + } + + TextConsole::putwchar(L'\n'); TextConsole::set_background(original_background); diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index 7d124a06..abd1c139 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -120,18 +121,17 @@ namespace TextConsole } } - // FIXME: Should this function propagate errors? - void putchar(char c) + Result putchar(char c) { - auto rc = utf8_decoder.feed(c); - if (rc.has_error()) - { - utf8_decoder.reset(); - return; - } + auto guard = make_scope_guard([] { utf8_decoder.reset(); }); + + auto maybe_wchar = TRY(utf8_decoder.feed(c)); + + guard.deactivate(); - auto maybe_wchar = rc.value(); if (maybe_wchar.has_value()) putwchar(maybe_wchar.value()); + + return {}; } void set_foreground(u32 color) @@ -166,23 +166,25 @@ namespace TextConsole Framebuffer::rect(0, 0, Framebuffer::width(), Framebuffer::height(), BLACK); } - void print(const char* str) + Result print(const char* str) { - while (*str) putchar(*str++); + while (*str) TRY(putchar(*str++)); + return {}; } - void println(const char* str) + Result println(const char* str) { - print(str); - putchar('\n'); + TRY(print(str)); + putwchar(L'\n'); + return {}; } - usize printf(const char* format, ...) + Result printf(const char* format, ...) { va_list ap; va_start(ap, format); - auto rc = pure_cstyle_format( - format, [](char c, void*) { putchar(c); }, nullptr, ap); + auto rc = TRY(cstyle_format( + format, [](char c, void*) -> Result { return putchar(c); }, nullptr, ap)); va_end(ap); return rc; } diff --git a/kernel/src/video/TextConsole.h b/kernel/src/video/TextConsole.h index 2c884262..464f34d9 100644 --- a/kernel/src/video/TextConsole.h +++ b/kernel/src/video/TextConsole.h @@ -6,14 +6,14 @@ namespace TextConsole { void clear(); - void putchar(char c); + Result putchar(char c); void putwchar(wchar_t c); void set_foreground(u32 color); void set_background(u32 color); u32 foreground(); u32 background(); void move_to(u32 x, u32 y); - void print(const char* str); - void println(const char* str); - usize printf(const char* format, ...) _format(1, 2); + Result print(const char* str); + Result println(const char* str); + Result printf(const char* format, ...) _format(1, 2); } \ No newline at end of file From fcefab4383935d318f5a7b77601992c72fd32504 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 21 Dec 2022 19:41:13 +0100 Subject: [PATCH 313/407] TextConsole: Add wide-character overloads for print() and println() These can't fail from UTF-8 decoding errors. --- kernel/src/Log.cpp | 11 +---------- kernel/src/video/TextConsole.cpp | 11 +++++++++++ kernel/src/video/TextConsole.h | 2 ++ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index d13d9e0e..713666fa 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -58,16 +58,7 @@ static void log_text_console(LogLevel level, const char* format, va_list origin) auto rc = cstyle_format( format, [](char c, void*) -> Result { return TextConsole::putchar(c); }, nullptr, ap); - if (rc.has_error()) - { - // FIXME: Find a way to do this in a simpler way (TextConsole::wprint maybe?) - const wchar_t* s = L"Invalid UTF-8 in log message"; - while (*s) - { - TextConsole::putwchar(*s); - s++; - } - } + if (rc.has_error()) { TextConsole::wprint(L"Invalid UTF-8 in log message"); } TextConsole::putwchar(L'\n'); diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index abd1c139..8ccea5cf 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -172,6 +172,11 @@ namespace TextConsole return {}; } + void wprint(const wchar_t* str) + { + while (*str) putwchar(*str++); + } + Result println(const char* str) { TRY(print(str)); @@ -179,6 +184,12 @@ namespace TextConsole return {}; } + void wprintln(const wchar_t* str) + { + wprint(str); + putwchar(L'\n'); + } + Result printf(const char* format, ...) { va_list ap; diff --git a/kernel/src/video/TextConsole.h b/kernel/src/video/TextConsole.h index 464f34d9..6614108e 100644 --- a/kernel/src/video/TextConsole.h +++ b/kernel/src/video/TextConsole.h @@ -14,6 +14,8 @@ namespace TextConsole u32 background(); void move_to(u32 x, u32 y); Result print(const char* str); + void wprint(const wchar_t* str); Result println(const char* str); + void wprintln(const wchar_t* str); Result printf(const char* format, ...) _format(1, 2); } \ No newline at end of file From 16bf8b38ea536ca4cc1b7ccc2d90f6bc3fbfd804 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 21 Dec 2022 20:08:43 +0100 Subject: [PATCH 314/407] UTF-8 decoder: Error out on overlong encodings --- luna/src/Utf8.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/luna/src/Utf8.cpp b/luna/src/Utf8.cpp index 0e543381..7ebc0c51 100644 --- a/luna/src/Utf8.cpp +++ b/luna/src/Utf8.cpp @@ -21,6 +21,14 @@ static Result wide_char_length_as_utf8(wchar_t c) return err(EILSEQ); } +static inline usize wide_char_length_as_utf8_unchecked(wchar_t c) +{ + if (c <= 0x7f) return 1; + if (c <= 0x7ff) return 2; + if (c <= 0xffff) return 3; + return 4; +} + static Result encode_wide_char_as_utf8(wchar_t c, char* result, usize& len) { len = TRY(wide_char_length_as_utf8(c)); @@ -57,7 +65,7 @@ static Result encode_wide_char_as_utf8(wchar_t c, char* result, usize& len unreachable(); } -static Result encode_utf8_as_wide_char(const char* beg, usize& len) +static Result encode_utf8_as_wide_char_impl(const char* beg, usize& len) { usize utf8_len = TRY(utf8_char_length(*beg)); if (utf8_len > len) return err(EILSEQ); // Unterminated sequence @@ -102,6 +110,19 @@ static Result encode_utf8_as_wide_char(const char* beg, usize& len) unreachable(); } +static Result encode_utf8_as_wide_char(const char* beg, usize& len) +{ + wchar_t result = TRY(encode_utf8_as_wide_char_impl(beg, len)); + // NOTE: We already know this is a valid code-point, since we constructed it ourselves and already checked the + // range. + if (len != wide_char_length_as_utf8_unchecked(result)) + { + // OVERLONG ENCODING!! This is nasty, error out. + return err(EILSEQ); + } + return result; +} + Utf8StringDecoder::Utf8StringDecoder(const char* str) : m_str(str), m_byte_length(strlen(str)) { } From 96135ff808e4f8cfda047eb27c59f677ef28e3e7 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 21 Dec 2022 20:11:00 +0100 Subject: [PATCH 315/407] Use limits.h for the standard definition of WCHAR_MAX --- luna/src/Utf8.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/luna/src/Utf8.cpp b/luna/src/Utf8.cpp index 7ebc0c51..15930c2a 100644 --- a/luna/src/Utf8.cpp +++ b/luna/src/Utf8.cpp @@ -1,7 +1,8 @@ +#include #include #include -static_assert(__WCHAR_MAX__ > 0x10ffff); +static_assert(WCHAR_MAX > 0x10ffff); static Result utf8_char_length(char c) { From a3595e71a998e39944d99b753a8ec45ffa0c3c48 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 21 Dec 2022 20:22:44 +0100 Subject: [PATCH 316/407] Update .clang-format --- .clang-format | 4 +- kernel/src/Log.cpp | 4 +- kernel/src/arch/Timer.cpp | 2 +- kernel/src/arch/x86_64/init/GDT.cpp | 14 +- kernel/src/memory/MemoryMap.cpp | 2 +- kernel/src/thread/Scheduler.cpp | 4 +- kernel/src/thread/Spinlock.h | 6 +- kernel/src/video/BuiltinFont.h | 1028 +++++++++++++-------------- luna/include/luna/Option.h | 4 +- luna/include/luna/OwnedStringView.h | 4 +- luna/include/luna/Result.h | 4 +- luna/include/luna/ScopeGuard.h | 4 +- luna/src/Format.cpp | 6 +- luna/src/OwnedStringView.cpp | 4 +- luna/src/TarStream.cpp | 2 +- luna/src/Units.cpp | 2 +- luna/src/Utf8.cpp | 8 +- 17 files changed, 552 insertions(+), 550 deletions(-) diff --git a/.clang-format b/.clang-format index 0dc2c5dc..2d9d8e87 100644 --- a/.clang-format +++ b/.clang-format @@ -9,4 +9,6 @@ AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Always AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: 'true' -PointerAlignment: Left \ No newline at end of file +PointerAlignment: Left +Cpp11BracedListStyle: 'false' +SpaceBeforeCpp11BracedList: 'true' \ No newline at end of file diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index 713666fa..ae3db02e 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -14,8 +14,8 @@ static constexpr u32 WHITE = 0xffffffff; static constexpr u32 YELLOW = 0xffffff00; static constexpr u32 RED = 0xffff0000; -static char log_level_letters[] = {'D', 'I', 'W', 'E'}; // D for debug, I for info, W for warning, E for error -static const char* ansi_color_codes_per_log_level[] = {"37", "37", "33", "31"}; // 37 is white, 33 yellow, 31 red +static char log_level_letters[] = { 'D', 'I', 'W', 'E' }; // D for debug, I for info, W for warning, E for error +static const char* ansi_color_codes_per_log_level[] = { "37", "37", "33", "31" }; // 37 is white, 33 yellow, 31 red static void log_serial(LogLevel level, const char* format, va_list origin) { diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 09500356..0bed7394 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -13,7 +13,7 @@ static inline constexpr bool isleap(u32 year) static constexpr u32 make_yday(u32 year, u32 month) { - constexpr u16 upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + constexpr u16 upto[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; u32 yd = upto[month - 1]; if (month > 2 && isleap(year)) yd++; diff --git a/kernel/src/arch/x86_64/init/GDT.cpp b/kernel/src/arch/x86_64/init/GDT.cpp index ca48ef5c..77317c00 100644 --- a/kernel/src/arch/x86_64/init/GDT.cpp +++ b/kernel/src/arch/x86_64/init/GDT.cpp @@ -44,13 +44,13 @@ struct [[gnu::packed]] alignas(4096) GlobalDescriptorTable TSS task_state_segment; -static GlobalDescriptorTable gdt = {{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00}, - {0xffff, 0x0000, 0x00, 0x9a, 0xaf, 0x00}, - {0xffff, 0x0000, 0x00, 0x92, 0xcf, 0x00}, - {0xffff, 0x0000, 0x00, 0xfa, 0xaf, 0x00}, - {0xffff, 0x0000, 0x00, 0xf2, 0xcf, 0x00}, - {0x0000, 0x0000, 0x00, 0xe9, 0x0f, 0x00}, - {0x00000000, 0x00000000}}; +static GlobalDescriptorTable gdt = { { 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00 }, + { 0xffff, 0x0000, 0x00, 0x9a, 0xaf, 0x00 }, + { 0xffff, 0x0000, 0x00, 0x92, 0xcf, 0x00 }, + { 0xffff, 0x0000, 0x00, 0xfa, 0xaf, 0x00 }, + { 0xffff, 0x0000, 0x00, 0xf2, 0xcf, 0x00 }, + { 0x0000, 0x0000, 0x00, 0xe9, 0x0f, 0x00 }, + { 0x00000000, 0x00000000 } }; extern "C" void load_gdt(GDTR* gdtr); extern "C" void load_tr(int segment); diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index 8743e83c..fa2d13e2 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -22,7 +22,7 @@ MemoryMapEntry& MemoryMapEntry::operator=(const MemoryMapEntry& other) static MemoryMapEntry memory_map_entry_from_mmapent(const MMapEnt* ent) { - return {MMapEnt_Ptr(ent), MMapEnt_Size(ent), MMapEnt_IsFree(ent)}; + return { MMapEnt_Ptr(ent), MMapEnt_Size(ent), MMapEnt_IsFree(ent) }; } MemoryMapIterator::MemoryMapIterator() : m_mmap_entries((bootboot.size - 128) / 16), m_base_ent(&bootboot.mmap) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 7e0f7acd..f84c98c5 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -26,7 +26,7 @@ namespace Scheduler u64 idle_stack_vm = MemoryManager::alloc_for_kernel(1, MMU::NoExecute | MMU::ReadWrite) .expect_value("Error while setting up the idle task, cannot continue"); - Stack idle_stack{idle_stack_vm, ARCH_PAGE_SIZE}; + Stack idle_stack { idle_stack_vm, ARCH_PAGE_SIZE }; g_idle.set_sp(idle_stack.top()); g_idle.stack = idle_stack; @@ -55,7 +55,7 @@ namespace Scheduler guard.deactivate(); - Stack thread_stack{thread_stack_vm, ARCH_PAGE_SIZE * 4}; + Stack thread_stack { thread_stack_vm, ARCH_PAGE_SIZE * 4 }; thread->set_sp(thread_stack.top()); thread->stack = thread_stack; diff --git a/kernel/src/thread/Spinlock.h b/kernel/src/thread/Spinlock.h index 28cd0e57..453327d7 100644 --- a/kernel/src/thread/Spinlock.h +++ b/kernel/src/thread/Spinlock.h @@ -16,7 +16,7 @@ class Spinlock } private: - Atomic m_lock{0}; + Atomic m_lock { 0 }; }; template class LockedValue @@ -76,12 +76,12 @@ template class LockedValue LockedValueGuard lock() { m_lock.lock(); - return {*this}; + return { *this }; } Option try_lock() { - if (m_lock.try_lock()) { return {*this}; } + if (m_lock.try_lock()) { return { *this }; } return {}; } diff --git a/kernel/src/video/BuiltinFont.h b/kernel/src/video/BuiltinFont.h index 72912bab..ee55a00a 100644 --- a/kernel/src/video/BuiltinFont.h +++ b/kernel/src/video/BuiltinFont.h @@ -3,517 +3,517 @@ // FIXME: Load a font from disk/initrd. -u8 font[] = {0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, /* 2 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 */ - 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 11 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 12 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 13 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 14 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 15 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 17 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 21 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 22 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 24 */ - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 25 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 26 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 27 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 29 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, - 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 30 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32 */ - 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 33 */ - 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 34 */ - 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x24, - 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, /* 35 */ - 0x00, 0x00, 0x08, 0x08, 0x1e, 0x20, 0x20, 0x1c, - 0x02, 0x02, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 36 */ - 0x00, 0x00, 0x00, 0x30, 0x49, 0x4a, 0x34, 0x08, - 0x16, 0x29, 0x49, 0x06, 0x00, 0x00, 0x00, 0x00, /* 37 */ - 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x31, - 0x49, 0x46, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, /* 38 */ - 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ - 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, /* 40 */ - 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, /* 41 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, - 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 */ - 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, - 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 43 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 44 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 45 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 46 */ - 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, - 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, /* 47 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x46, 0x4a, 0x52, - 0x62, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 48 */ - 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 49 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x04, - 0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 50 */ - 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x1c, 0x02, - 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 51 */ - 0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, - 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* 52 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, - 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 53 */ - 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 54 */ - 0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x04, 0x08, - 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 55 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 56 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, - 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* 57 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 58 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 59 */ - 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, - 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, /* 60 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, - 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 61 */ - 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, - 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, /* 62 */ - 0x00, 0x00, 0x3c, 0x42, 0x02, 0x04, 0x08, 0x10, - 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 63 */ - 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4f, 0x51, 0x51, - 0x51, 0x53, 0x4d, 0x40, 0x20, 0x1f, 0x00, 0x00, /* 64 */ - 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, - 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 65 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, - 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 66 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 67 */ - 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x00, /* 68 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, - 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 69 */ - 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, - 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 70 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x46, - 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 71 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 72 */ - 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 73 */ - 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 74 */ - 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, - 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 75 */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 76 */ - 0x00, 0x00, 0x00, 0x41, 0x63, 0x55, 0x49, 0x49, - 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 77 */ - 0x00, 0x00, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 78 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 79 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, - 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 80 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x04, 0x02, 0x00, 0x00, /* 81 */ - 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, - 0x48, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 82 */ - 0x00, 0x00, 0x00, 0x3e, 0x40, 0x40, 0x20, 0x18, - 0x04, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 83 */ - 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 84 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 85 */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 86 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x41, 0x49, - 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 87 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, - 0x14, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 88 */ - 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 89 */ - 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x08, 0x10, - 0x10, 0x20, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 90 */ - 0x00, 0x00, 0x1e, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x00, 0x00, /* 91 */ - 0x00, 0x00, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, - 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* 92 */ - 0x00, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, 0x00, /* 93 */ - 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 94 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, /* 95 */ - 0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 96 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, - 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 97 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 98 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, - 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 99 */ - 0x00, 0x00, 0x02, 0x02, 0x02, 0x3e, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 100 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, - 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 101 */ - 0x00, 0x00, 0x0e, 0x10, 0x10, 0x7e, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 102 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 103 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 104 */ - 0x00, 0x00, 0x08, 0x08, 0x00, 0x38, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 105 */ - 0x00, 0x00, 0x04, 0x04, 0x00, 0x1c, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x00, /* 106 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, - 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 107 */ - 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 108 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, /* 109 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 110 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 111 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, /* 112 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, /* 113 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x30, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, /* 114 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x20, - 0x18, 0x04, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 115 */ - 0x00, 0x00, 0x00, 0x10, 0x10, 0x7e, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 116 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 117 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, - 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 118 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, - 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 119 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, - 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, /* 120 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 121 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, - 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 122 */ - 0x00, 0x0e, 0x10, 0x10, 0x10, 0x10, 0x10, 0xe0, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, /* 123 */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 124 */ - 0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, /* 125 */ - 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 126 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 127 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 129 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 130 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 131 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 132 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 133 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 134 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 135 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 136 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 137 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 138 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 139 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 140 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 141 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 142 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 143 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 144 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 145 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 146 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 147 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 148 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 149 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 150 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 151 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 152 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 153 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 154 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 155 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 156 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 157 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 158 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 159 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 160 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, - 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /* 161 */ - 0x00, 0x00, 0x08, 0x08, 0x1c, 0x22, 0x40, 0x40, - 0x40, 0x22, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 162 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, - 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 163 */ - 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x24, - 0x24, 0x3c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* 164 */ - 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x3e, - 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 165 */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, - 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 166 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 167 */ - 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 168 */ - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4d, 0x51, - 0x51, 0x4d, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 169 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 170 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x12, 0x24, - 0x48, 0x24, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, /* 171 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 172 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 173 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 174 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 175 */ - 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 176 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 177 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 178 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 179 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 180 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 181 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 182 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 183 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x30, 0x00, /* 184 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 185 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 186 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, - 0x09, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, /* 187 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 189 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 190 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, - 0x00, 0x08, 0x10, 0x20, 0x40, 0x42, 0x3c, 0x00, /* 191 */ - 0x20, 0x10, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, - 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 192 */ - 0x04, 0x08, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, - 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 193 */ - 0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, - 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 194 */ - 0x32, 0x4c, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, - 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 195 */ - 0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, - 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 196 */ - 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x24, - 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 197 */ - 0x00, 0x00, 0x00, 0x0f, 0x14, 0x14, 0x24, 0x27, - 0x3c, 0x44, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00, /* 198 */ - 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x20, 0x1e, 0x08, 0x08, 0x30, 0x00, /* 199 */ - 0x20, 0x10, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, - 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 200 */ - 0x04, 0x08, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, - 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 201 */ - 0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, - 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 202 */ - 0x24, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, - 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 203 */ - 0x10, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 204 */ - 0x04, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 205 */ - 0x18, 0x24, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 206 */ - 0x22, 0x22, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 207 */ - 0x00, 0x00, 0x00, 0x3c, 0x22, 0x21, 0x21, 0x79, - 0x21, 0x21, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 208 */ - 0x32, 0x4c, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 209 */ - 0x10, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 210 */ - 0x04, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 211 */ - 0x18, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 212 */ - 0x32, 0x4c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 213 */ - 0x24, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 214 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, - 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 215 */ - 0x00, 0x00, 0x02, 0x3c, 0x42, 0x46, 0x4a, 0x52, - 0x62, 0x42, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 216 */ - 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 217 */ - 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 218 */ - 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 219 */ - 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 220 */ - 0x04, 0x08, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 221 */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x7c, 0x42, 0x42, - 0x42, 0x7c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 222 */ - 0x00, 0x00, 0x00, 0x3c, 0x42, 0x44, 0x4c, 0x42, - 0x42, 0x42, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* 223 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x02, 0x02, - 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 224 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x02, 0x02, - 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 225 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x02, 0x02, - 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 226 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x02, 0x02, - 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 227 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x02, 0x02, - 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 228 */ - 0x18, 0x24, 0x24, 0x18, 0x00, 0x3c, 0x02, 0x02, - 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 229 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09, 0x39, - 0x4f, 0x48, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, /* 230 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, - 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, /* 231 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x42, - 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 232 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, - 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 233 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, - 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 234 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, - 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 235 */ - 0x00, 0x00, 0x10, 0x08, 0x00, 0x38, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 236 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x38, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 237 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x38, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 238 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x38, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 239 */ - 0x00, 0x09, 0x06, 0x1a, 0x01, 0x1d, 0x23, 0x41, - 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 240 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x7c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 241 */ - 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 242 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 243 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 244 */ - 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 245 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 246 */ - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 247 */ - 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, - 0x52, 0x62, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 248 */ - 0x00, 0x00, 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 249 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 250 */ - 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 251 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 252 */ - 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 253 */ - 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x41, - 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x00, /* 254 */ - 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 255 */ - 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, - 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00 /* Special box character, 256 */}; \ No newline at end of file +u8 font[] = { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, /* 2 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 */ + 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 11 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 12 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 13 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 14 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 15 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 17 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 21 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 22 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 24 */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 25 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 26 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 29 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, + 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 30 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32 */ + 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 33 */ + 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 34 */ + 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x24, + 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, /* 35 */ + 0x00, 0x00, 0x08, 0x08, 0x1e, 0x20, 0x20, 0x1c, + 0x02, 0x02, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 36 */ + 0x00, 0x00, 0x00, 0x30, 0x49, 0x4a, 0x34, 0x08, + 0x16, 0x29, 0x49, 0x06, 0x00, 0x00, 0x00, 0x00, /* 37 */ + 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x31, + 0x49, 0x46, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, /* 38 */ + 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ + 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, /* 40 */ + 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, /* 41 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, + 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 */ + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, + 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 43 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 44 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 45 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 46 */ + 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, + 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, /* 47 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x46, 0x4a, 0x52, + 0x62, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 48 */ + 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 49 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 50 */ + 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x1c, 0x02, + 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 51 */ + 0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, + 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* 52 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, + 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 53 */ + 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 54 */ + 0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x04, 0x08, + 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 55 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 56 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, + 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* 57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 58 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 59 */ + 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, + 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, /* 60 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 61 */ + 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, /* 62 */ + 0x00, 0x00, 0x3c, 0x42, 0x02, 0x04, 0x08, 0x10, + 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 63 */ + 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4f, 0x51, 0x51, + 0x51, 0x53, 0x4d, 0x40, 0x20, 0x1f, 0x00, 0x00, /* 64 */ + 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 65 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, + 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 66 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 67 */ + 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x00, /* 68 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 69 */ + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 70 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x46, + 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 71 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 72 */ + 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 73 */ + 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 74 */ + 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, + 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 75 */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 76 */ + 0x00, 0x00, 0x00, 0x41, 0x63, 0x55, 0x49, 0x49, + 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 77 */ + 0x00, 0x00, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 78 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 79 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, + 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 80 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x04, 0x02, 0x00, 0x00, /* 81 */ + 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, + 0x48, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 82 */ + 0x00, 0x00, 0x00, 0x3e, 0x40, 0x40, 0x20, 0x18, + 0x04, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 83 */ + 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 84 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 85 */ + 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 86 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x41, 0x49, + 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 87 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, + 0x14, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 88 */ + 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 89 */ + 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x08, 0x10, + 0x10, 0x20, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 90 */ + 0x00, 0x00, 0x1e, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x00, 0x00, /* 91 */ + 0x00, 0x00, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, + 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* 92 */ + 0x00, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, 0x00, /* 93 */ + 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 94 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, /* 95 */ + 0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 96 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 97 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 98 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, + 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 99 */ + 0x00, 0x00, 0x02, 0x02, 0x02, 0x3e, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 100 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 101 */ + 0x00, 0x00, 0x0e, 0x10, 0x10, 0x7e, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 102 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 103 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 104 */ + 0x00, 0x00, 0x08, 0x08, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 105 */ + 0x00, 0x00, 0x04, 0x04, 0x00, 0x1c, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x00, /* 106 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, + 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 107 */ + 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 108 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x49, 0x49, + 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, /* 109 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 110 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 111 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, /* 112 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, /* 113 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x30, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, /* 114 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x20, + 0x18, 0x04, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 115 */ + 0x00, 0x00, 0x00, 0x10, 0x10, 0x7e, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 116 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 117 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, + 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 118 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, + 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 119 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, + 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, /* 120 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 121 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, + 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 122 */ + 0x00, 0x0e, 0x10, 0x10, 0x10, 0x10, 0x10, 0xe0, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, /* 123 */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 124 */ + 0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, /* 125 */ + 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 126 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 127 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 129 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 130 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 131 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 132 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 133 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 134 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 135 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 136 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 137 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 138 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 139 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 140 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 141 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 142 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 143 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 144 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 145 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 146 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 147 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 148 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 149 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 150 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 151 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 152 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 153 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 154 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 155 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 156 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 157 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 158 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 159 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 160 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, + 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /* 161 */ + 0x00, 0x00, 0x08, 0x08, 0x1c, 0x22, 0x40, 0x40, + 0x40, 0x22, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 162 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, + 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 163 */ + 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x24, + 0x24, 0x3c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* 164 */ + 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x3e, + 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 165 */ + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, + 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 166 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 167 */ + 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 168 */ + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4d, 0x51, + 0x51, 0x4d, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 169 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 170 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x12, 0x24, + 0x48, 0x24, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, /* 171 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 172 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 173 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 174 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 175 */ + 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 176 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 177 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 178 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 179 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 180 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 181 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 182 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 183 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x30, 0x00, /* 184 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 185 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 186 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, + 0x09, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, /* 187 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 189 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 190 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, + 0x00, 0x08, 0x10, 0x20, 0x40, 0x42, 0x3c, 0x00, /* 191 */ + 0x20, 0x10, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 192 */ + 0x04, 0x08, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 193 */ + 0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 194 */ + 0x32, 0x4c, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 195 */ + 0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 196 */ + 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x24, + 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 197 */ + 0x00, 0x00, 0x00, 0x0f, 0x14, 0x14, 0x24, 0x27, + 0x3c, 0x44, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00, /* 198 */ + 0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x1e, 0x08, 0x08, 0x30, 0x00, /* 199 */ + 0x20, 0x10, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 200 */ + 0x04, 0x08, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 201 */ + 0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 202 */ + 0x24, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, + 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 203 */ + 0x10, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 204 */ + 0x04, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 205 */ + 0x18, 0x24, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 206 */ + 0x22, 0x22, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 207 */ + 0x00, 0x00, 0x00, 0x3c, 0x22, 0x21, 0x21, 0x79, + 0x21, 0x21, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 208 */ + 0x32, 0x4c, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 209 */ + 0x10, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 210 */ + 0x04, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 211 */ + 0x18, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 212 */ + 0x32, 0x4c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 213 */ + 0x24, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 214 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, + 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 215 */ + 0x00, 0x00, 0x02, 0x3c, 0x42, 0x46, 0x4a, 0x52, + 0x62, 0x42, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 216 */ + 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 217 */ + 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 218 */ + 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 219 */ + 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 220 */ + 0x04, 0x08, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 221 */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x7c, 0x42, 0x42, + 0x42, 0x7c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 222 */ + 0x00, 0x00, 0x00, 0x3c, 0x42, 0x44, 0x4c, 0x42, + 0x42, 0x42, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* 223 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 224 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 225 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 226 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 227 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 228 */ + 0x18, 0x24, 0x24, 0x18, 0x00, 0x3c, 0x02, 0x02, + 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 229 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09, 0x39, + 0x4f, 0x48, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, /* 230 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, + 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, /* 231 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 232 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 233 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 234 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, + 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 235 */ + 0x00, 0x00, 0x10, 0x08, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 236 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 237 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 238 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x38, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 239 */ + 0x00, 0x09, 0x06, 0x1a, 0x01, 0x1d, 0x23, 0x41, + 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 240 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x7c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 241 */ + 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 242 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 243 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 244 */ + 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 245 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 246 */ + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 247 */ + 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, + 0x52, 0x62, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 248 */ + 0x00, 0x00, 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 249 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 250 */ + 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 251 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 252 */ + 0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 253 */ + 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x41, + 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x00, /* 254 */ + 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 255 */ + 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00 /* Special box character, 256 */ }; \ No newline at end of file diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index c4be03be..cbe7ad7d 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -83,7 +83,7 @@ template class Option ErrorHandle release_error() { expect(!has_value(), "Option::release_error called on a non-empty Option"); - return ErrorHandle{}; + return ErrorHandle {}; } private: @@ -127,5 +127,5 @@ template class Option } }; Storage m_storage; - bool m_has_value{false}; + bool m_has_value { false }; }; \ No newline at end of file diff --git a/luna/include/luna/OwnedStringView.h b/luna/include/luna/OwnedStringView.h index ba457b58..e9343e55 100644 --- a/luna/include/luna/OwnedStringView.h +++ b/luna/include/luna/OwnedStringView.h @@ -27,6 +27,6 @@ class OwnedStringView const char& operator[](usize) const; private: - char* m_string{nullptr}; - usize m_length{0}; + char* m_string { nullptr }; + usize m_length { 0 }; }; \ No newline at end of file diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index ed2935e3..180ea158 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -60,7 +60,7 @@ template class Result Error release_error() const { expect(has_error(), "Result::release_error() called on a Result that holds a value"); - return {m_error}; + return { m_error }; } const char* error_string() const @@ -154,7 +154,7 @@ template <> class Result Error release_error() const { expect(has_error(), "Result::release_error() called on a Result that holds a value"); - return {m_error}; + return { m_error }; } const char* error_string() const diff --git a/luna/include/luna/ScopeGuard.h b/luna/include/luna/ScopeGuard.h index 4d214002..cc758f26 100644 --- a/luna/include/luna/ScopeGuard.h +++ b/luna/include/luna/ScopeGuard.h @@ -18,11 +18,11 @@ template class ScopeGuard } private: - bool m_activated{true}; + bool m_activated { true }; Callback m_callback; }; template [[nodiscard]] ScopeGuard make_scope_guard(const Callback& callback) { - return {callback}; + return { callback }; } \ No newline at end of file diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index ff936a24..cd68ba8c 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -487,7 +487,7 @@ Result cstyle_format(const char* format, callback_t callback, void* arg, usize precision = parse_precision(&format, flags, ap); parse_length(&format, flags); - conv_state vstate = {flags, width, precision}; + conv_state vstate = { flags, width, precision }; const char specifier = *format; format++; @@ -587,7 +587,7 @@ usize pure_cstyle_format(const char* format, pure_callback_t callback, void* arg usize precision = parse_precision(&format, flags, ap); parse_length(&format, flags); - conv_state vstate = {flags, width, precision}; + conv_state vstate = { flags, width, precision }; const char specifier = *format; format++; @@ -664,7 +664,7 @@ struct StringFormatInfo usize vstring_format(char* buf, usize max, const char* format, va_list ap) { - StringFormatInfo info = {.buffer = buf, .remaining = max - 1}; + StringFormatInfo info = { .buffer = buf, .remaining = max - 1 }; usize result = pure_cstyle_format( format, diff --git a/luna/src/OwnedStringView.cpp b/luna/src/OwnedStringView.cpp index 0bf41af3..ba786cfe 100644 --- a/luna/src/OwnedStringView.cpp +++ b/luna/src/OwnedStringView.cpp @@ -32,7 +32,7 @@ Result OwnedStringView::clone() const if (!c_str) return err(ENOMEM); - return OwnedStringView{c_str}; + return OwnedStringView { c_str }; } const char& OwnedStringView::operator[](usize index) const @@ -45,5 +45,5 @@ Result OwnedStringView::from_string_literal(const char* str) { char* dup = strdup(str); if (!dup) return err(ENOMEM); - return OwnedStringView{dup}; + return OwnedStringView { dup }; } \ No newline at end of file diff --git a/luna/src/TarStream.cpp b/luna/src/TarStream.cpp index 1dee4edd..e5d84a4b 100644 --- a/luna/src/TarStream.cpp +++ b/luna/src/TarStream.cpp @@ -105,5 +105,5 @@ Result TarStream::read_contents_as_string(const Entry& entry, u buf[nread] = 0; - return OwnedStringView{buf}; + return OwnedStringView { buf }; } \ No newline at end of file diff --git a/luna/src/Units.cpp b/luna/src/Units.cpp index 05afd720..9c4a31f5 100644 --- a/luna/src/Units.cpp +++ b/luna/src/Units.cpp @@ -24,5 +24,5 @@ Result to_dynamic_unit(usize value) to_dynamic_unit_cstr(value, buf, 64); - return OwnedStringView{buf}; + return OwnedStringView { buf }; } \ No newline at end of file diff --git a/luna/src/Utf8.cpp b/luna/src/Utf8.cpp index 15930c2a..96336ed3 100644 --- a/luna/src/Utf8.cpp +++ b/luna/src/Utf8.cpp @@ -208,11 +208,11 @@ Result> Utf8StateDecoder::feed(char c) if (m_state_len == 1) { m_state_len = 0; - return Option{c & 0x7f}; + return Option { c & 0x7f }; } m_state_index = 0; m_state[m_state_index] = c; - return {{}}; + return { {} }; } m_state_index++; @@ -223,10 +223,10 @@ Result> Utf8StateDecoder::feed(char c) usize len = m_state_len; wchar_t wc = TRY(encode_utf8_as_wide_char(m_state, len)); m_state_len = 0; - return Option{wc}; + return Option { wc }; } - return {{}}; + return { {} }; } void Utf8StateDecoder::reset() From 9afaad8fedfa05989be0a1a76e1d3fb2e4b10820 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 22 Dec 2022 18:00:35 +0100 Subject: [PATCH 317/407] Add dbgln() for the luna library --- kernel/src/Log.cpp | 6 ++++++ luna/CMakeLists.txt | 1 + luna/include/luna/DebugLog.h | 7 +++++++ luna/src/DebugLog.cpp | 9 +++++++++ 4 files changed, 23 insertions(+) create mode 100644 luna/include/luna/DebugLog.h create mode 100644 luna/src/DebugLog.cpp diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index ae3db02e..d8194fd1 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -87,6 +87,12 @@ void log(LogLevel level, const char* format, ...) va_end(ap); } +// for luna/DebugLog.h +void debug_log_impl(const char* format, va_list ap) +{ + vlog(LogLevel::Debug, format, ap); +} + void setup_log(bool enable_debug, bool enable_serial, bool enable_text_console) { g_debug_enabled = enable_debug; diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 54b55b97..7583fc4b 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -12,6 +12,7 @@ set(FREESTANDING_SOURCES src/OwnedStringView.cpp src/Utf8.cpp src/TarStream.cpp + src/DebugLog.cpp ) set(SOURCES diff --git a/luna/include/luna/DebugLog.h b/luna/include/luna/DebugLog.h new file mode 100644 index 00000000..5a32a7a4 --- /dev/null +++ b/luna/include/luna/DebugLog.h @@ -0,0 +1,7 @@ +#pragma once +#include +#include + +extern void debug_log_impl(const char* format, va_list ap); + +void dbgln(const char* format, ...) _format(1, 2); \ No newline at end of file diff --git a/luna/src/DebugLog.cpp b/luna/src/DebugLog.cpp new file mode 100644 index 00000000..b2639723 --- /dev/null +++ b/luna/src/DebugLog.cpp @@ -0,0 +1,9 @@ +#include + +void dbgln(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + debug_log_impl(format, ap); + va_end(ap); +} \ No newline at end of file From bd4b05e534e629bd6f0980f75a93f8e85ee184e2 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 10:23:13 +0100 Subject: [PATCH 318/407] Add OwnedPtr and SharedPtr --- luna/include/luna/OwnedPtr.h | 61 ++++++++++++++++++++ luna/include/luna/SharedPtr.h | 104 ++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 luna/include/luna/OwnedPtr.h create mode 100644 luna/include/luna/SharedPtr.h diff --git a/luna/include/luna/OwnedPtr.h b/luna/include/luna/OwnedPtr.h new file mode 100644 index 00000000..cc147f24 --- /dev/null +++ b/luna/include/luna/OwnedPtr.h @@ -0,0 +1,61 @@ +#pragma once +#include +#include + +template class OwnedPtr +{ + public: + OwnedPtr(T* ptr) + { + m_ptr = ptr; + } + + ~OwnedPtr() + { + if (m_ptr) delete m_ptr; + } + + OwnedPtr(const OwnedPtr& other) = delete; + + OwnedPtr(OwnedPtr&& other) + { + m_ptr = other.m_ptr; + other.m_ptr = nullptr; + } + + T* ptr() const + { + return m_ptr; + } + + T* operator->() const + { + return m_ptr; + } + + T& operator*() const + { + return *m_ptr; + } + + private: + T* m_ptr; +}; + +template Result> make_owned(Args... args) +{ + T* raw = TRY(make(args...)); + return OwnedPtr { raw }; +} + +template OwnedPtr adopt_owned(T* ptr) +{ + return OwnedPtr { ptr }; +} + +template Result> adopt_owned_if_nonnull(T* ptr) +{ + if (ptr) return OwnedPtr { ptr }; + else + return err(ENOMEM); +} \ No newline at end of file diff --git a/luna/include/luna/SharedPtr.h b/luna/include/luna/SharedPtr.h new file mode 100644 index 00000000..08c09931 --- /dev/null +++ b/luna/include/luna/SharedPtr.h @@ -0,0 +1,104 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace __detail +{ + struct RefCount + { + void ref() + { + m_ref_count++; + } + + bool unref() + { + m_ref_count--; + return m_ref_count == 0; + } + + private: + Atomic m_ref_count { 1 }; + }; +} + +template class SharedPtr +{ + using RefCount = __detail::RefCount; + + public: + SharedPtr(T* ptr, RefCount* ref_count) : m_ptr(ptr), m_ref_count(ref_count) + { + } + + SharedPtr(const SharedPtr& other) : m_ptr(other.m_ptr), m_ref_count(other.m_ref_count) + { + m_ref_count->ref(); + } + + SharedPtr(SharedPtr&& other) : m_ptr(other.m_ptr), m_ref_count(other.m_ref_count) + { + other.m_ptr = nullptr; + other.m_ref_count = nullptr; + } + + ~SharedPtr() + { + if (m_ref_count && m_ref_count->unref()) + { + delete m_ref_count; + delete m_ptr; + } + } + + T* ptr() const + { + return m_ptr; + } + + T* operator->() const + { + return m_ptr; + } + + T& operator*() const + { + return *m_ptr; + } + + private: + T* m_ptr; + RefCount* m_ref_count; +}; + +template Result> make_shared(Args... args) +{ + using RefCount = __detail::RefCount; + + RefCount* ref_count = TRY(make()); + auto guard = make_scope_guard([&] { delete ref_count; }); + + T* ptr = TRY(make(args...)); + guard.deactivate(); + + return SharedPtr { ptr, ref_count }; +} + +template Result> adopt_shared(T* ptr) +{ + using RefCount = __detail::RefCount; + + RefCount* ref_count = TRY(make()); + + return SharedPtr { ptr, ref_count }; +} + +template Result> adopt_shared_if_nonnull(T* ptr) +{ + if (ptr) return adopt_shared(ptr); + else + return err(ENOMEM); +} \ No newline at end of file From 4fa33a9689e4d77a9ad3e283ec789f54f9971954 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 10:31:48 +0100 Subject: [PATCH 319/407] SharedPtr: Add operator= --- luna/include/luna/SharedPtr.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/luna/include/luna/SharedPtr.h b/luna/include/luna/SharedPtr.h index 08c09931..4cf1bcff 100644 --- a/luna/include/luna/SharedPtr.h +++ b/luna/include/luna/SharedPtr.h @@ -1,7 +1,6 @@ #pragma once #include #include -#include #include #include @@ -54,6 +53,24 @@ template class SharedPtr } } + SharedPtr& operator=(const SharedPtr& other) + { + if (&other == this) return *this; + + if (m_ref_count && m_ref_count->unref()) + { + delete m_ref_count; + delete m_ptr; + } + + m_ptr = other.m_ptr; + m_ref_count = other.m_ref_count; + + m_ref_count->ref(); + + return *this; + } + T* ptr() const { return m_ptr; From 913b13b38035f590aecff1624a63c0006bebece8 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 10:46:44 +0100 Subject: [PATCH 320/407] Fix up the header install script --- tools/install-headers.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/install-headers.sh b/tools/install-headers.sh index eed3b849..665ef7e2 100755 --- a/tools/install-headers.sh +++ b/tools/install-headers.sh @@ -5,10 +5,10 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -mkdir -p base -mkdir -p base/usr/include -mkdir -p base/usr/include/moon -mkdir -p base/usr/include/luna +mkdir -p $LUNA_BASE +mkdir -p $LUNA_BASE/usr/include +mkdir -p $LUNA_BASE/usr/include/moon +mkdir -p $LUNA_BASE/usr/include/luna -cp -RT kernel/**/*.h base/usr/include/moon -cp -RT luna/*.h base/usr/include/luna \ No newline at end of file +cp -RT kernel/**/*.h $LUNA_BASE/usr/include/moon +cp -RT luna/*.h $LUNA_BASE/usr/include/luna \ No newline at end of file From 34e6c05cef1bde78d2fe32cd99a0ddbe7910065c Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 10:48:00 +0100 Subject: [PATCH 321/407] Fix it up a bit more --- tools/install-headers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/install-headers.sh b/tools/install-headers.sh index 665ef7e2..94cf0b7c 100755 --- a/tools/install-headers.sh +++ b/tools/install-headers.sh @@ -11,4 +11,4 @@ mkdir -p $LUNA_BASE/usr/include/moon mkdir -p $LUNA_BASE/usr/include/luna cp -RT kernel/**/*.h $LUNA_BASE/usr/include/moon -cp -RT luna/*.h $LUNA_BASE/usr/include/luna \ No newline at end of file +cp -RT luna/include/luna/*.h $LUNA_BASE/usr/include/luna \ No newline at end of file From c39e54b7c6aabf10ab9acf41e590cd9d2c4ea81a Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 10:51:55 +0100 Subject: [PATCH 322/407] Make TarStream::read_contents take any pointer as output --- luna/include/luna/TarStream.h | 2 +- luna/src/TarStream.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/luna/include/luna/TarStream.h b/luna/include/luna/TarStream.h index b4f62402..fede39dd 100644 --- a/luna/include/luna/TarStream.h +++ b/luna/include/luna/TarStream.h @@ -32,7 +32,7 @@ class TarStream void rewind(); - usize read_contents(const Entry& entry, char* buf, usize offset, usize length); + usize read_contents(const Entry& entry, void* buf, usize offset, usize length); Result read_contents_as_string(const Entry& entry, usize offset, usize max); diff --git a/luna/src/TarStream.cpp b/luna/src/TarStream.cpp index e5d84a4b..7383ef07 100644 --- a/luna/src/TarStream.cpp +++ b/luna/src/TarStream.cpp @@ -87,7 +87,7 @@ Result TarStream::read_next_entry() return parse_header(&header); } -usize TarStream::read_contents(const Entry& entry, char* buf, usize offset, usize length) +usize TarStream::read_contents(const Entry& entry, void* buf, usize offset, usize length) { if (offset >= entry.size) return 0; if ((length + offset) > entry.size) length = entry.size - offset; From 575752eb23dfc82fd29d9a4214d4822cd8a5ba36 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 11:04:50 +0100 Subject: [PATCH 323/407] Update drone config to pull toolchain from a new purpose-built toolchain archive for CI --- .drone.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index d532a47f..ea4497f7 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,9 +12,9 @@ steps: commands: - apt update - apt install build-essential cmake ninja-build wget nasm -y - - wget https://pub.cloudapio.eu/luna/toolchain-linux-arm64.tar.gz --quiet - - tar xf toolchain-linux-arm64.tar.gz - - rm toolchain-linux-arm64.tar.gz + - wget https://pub.cloudapio.eu/luna/ci-toolchain-arm64.tar.gz --quiet + - tar xf ci-toolchain-arm64.tar.gz + - rm ci-toolchain-arm64.tar.gz - tools/rebuild-iso.sh trigger: From e6384ae90daa675ff4785a2372e0c5941214e555 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 11:06:37 +0100 Subject: [PATCH 324/407] Use the new toolchain location --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index ea4497f7..ac733b83 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,7 +12,7 @@ steps: commands: - apt update - apt install build-essential cmake ninja-build wget nasm -y - - wget https://pub.cloudapio.eu/luna/ci-toolchain-arm64.tar.gz --quiet + - wget https://pub.cloudapio.eu/luna/toolchains/ci-toolchain-arm64.tar.gz --quiet - tar xf ci-toolchain-arm64.tar.gz - rm ci-toolchain-arm64.tar.gz - tools/rebuild-iso.sh From 74235c2c998d47d78e6e63ccd15feacf874fbc5f Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 11:06:59 +0100 Subject: [PATCH 325/407] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c4f7b82..e0e08b1a 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ A simple kernel and userspace for the x86_64 platform, written mostly in C++ and ## Setup (broken) **WARNING**: Setup will fail on this branch, since we do not have the required libc headers yet, and I removed the patches for now. Your best bet to build the toolchain is to switch to the `main` branch, where it will build successfully, and run `tools/setup.sh`. Then switch back to this branch, run `git clean -fd`, and continue development :) -Alternatively, you can also download prebuilt toolchains for x86_64/arm64 Linux hosts from [here](https://pub.cloudapio.eu/luna). Then run `tar xf toolchain-linux-ARCH.tar.gz -C /path/to/luna`. +Alternatively, you can also download prebuilt toolchains for x86_64/arm64 Linux hosts from [here](https://pub.cloudapio.eu/luna/toolchains). Then run `tar xf toolchain-linux-ARCH.tar.gz -C /path/to/luna`. **ORIGINAL INSTRUCTIONS** From 6ff92b171419104ca259dbeb28534e887a7b0cd7 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 11:30:49 +0100 Subject: [PATCH 326/407] MemoryManager: Add get_kernel_mapping_for_frames() This function allocates a continuous range of VM and maps the physical frames passed to said VM range. --- kernel/src/memory/MemoryManager.cpp | 26 ++++++++++++++++++++++++++ kernel/src/memory/MemoryManager.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 33935d26..b410cc0d 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -247,6 +247,32 @@ namespace MemoryManager return start; } + Result get_kernel_mapping_for_frames(u64 phys, usize count, int flags) + { + u64 start = TRY(KernelVM::alloc_several_pages(count)); + + usize pages_mapped = 0; + + auto guard = make_scope_guard([=, &pages_mapped] { + KernelVM::free_several_pages(start, pages_mapped); + unmap_weak(start, pages_mapped); + }); + + u64 virt = start; + + while (pages_mapped < count) + { + TRY(MMU::map(virt, phys, flags)); + virt += ARCH_PAGE_SIZE; + phys += ARCH_PAGE_SIZE; + pages_mapped++; + } + + guard.deactivate(); + + return start; + } + Result unmap_owned(u64 virt, usize count) { CHECK_PAGE_ALIGNED(virt); diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index cf3ed2ce..a5570157 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -25,6 +25,8 @@ namespace MemoryManager Result alloc_at(u64 virt, usize count, int flags); Result alloc_for_kernel(usize count, int flags); + Result get_kernel_mapping_for_frames(u64 phys, usize count, int flags); + Result unmap_owned(u64 virt, usize count); Result unmap_owned_and_free_vm(u64 virt, usize count); Result unmap_weak(u64 virt, usize count); From ad0f6546d7c94c39037855db9b892110b33cd937 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 11:33:23 +0100 Subject: [PATCH 327/407] Add a global initrd TarStream to make the initial ramdisk accessible everywhere It's also mapped into virtual memory instead of directly going into the physical location!! --- kernel/CMakeLists.txt | 1 + kernel/src/InitRD.cpp | 18 ++++++++++++++++++ kernel/src/InitRD.h | 9 +++++++++ kernel/src/boot/Init.cpp | 2 ++ kernel/src/main.cpp | 7 +++---- luna/include/luna/TarStream.h | 1 + 6 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 kernel/src/InitRD.cpp create mode 100644 kernel/src/InitRD.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 9cf0febf..66637a77 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES src/thread/Spinlock.cpp src/thread/Thread.cpp src/thread/Scheduler.cpp + src/InitRD.cpp ) if("${ARCH}" MATCHES "x86_64") diff --git a/kernel/src/InitRD.cpp b/kernel/src/InitRD.cpp new file mode 100644 index 00000000..c8d7d957 --- /dev/null +++ b/kernel/src/InitRD.cpp @@ -0,0 +1,18 @@ +#include "InitRD.h" +#include "arch/MMU.h" +#include "boot/bootboot.h" +#include "memory/MemoryManager.h" +#include + +TarStream g_initrd; +extern const BOOTBOOT bootboot; + +void InitRD::initialize() +{ + u64 virtual_initrd_address = + MemoryManager::get_kernel_mapping_for_frames( + bootboot.initrd_ptr, get_blocks_from_size(bootboot.initrd_size, ARCH_PAGE_SIZE), MMU::NoExecute) + .expect_value("Unable to map the initial ramdisk into virtual memory"); + + g_initrd.initialize((void*)virtual_initrd_address, bootboot.initrd_size); +} \ No newline at end of file diff --git a/kernel/src/InitRD.h b/kernel/src/InitRD.h new file mode 100644 index 00000000..632a8e54 --- /dev/null +++ b/kernel/src/InitRD.h @@ -0,0 +1,9 @@ +#pragma once +#include + +extern TarStream g_initrd; + +namespace InitRD +{ + void initialize(); +} \ No newline at end of file diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 0aba173e..e28471ab 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -1,4 +1,5 @@ #include "boot/Init.h" +#include "InitRD.h" #include "Log.h" #include "arch/CPU.h" #include "boot/bootboot.h" @@ -28,6 +29,7 @@ void Init::early_init() setup_log(log_debug_enabled(), log_serial_enabled(), true); MemoryManager::init(); + InitRD::initialize(); CPU::platform_init(); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index a8e8622d..cfd37243 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,3 +1,4 @@ +#include "InitRD.h" #include "Log.h" #include "arch/CPU.h" #include "arch/MMU.h" @@ -11,7 +12,6 @@ #include "thread/Scheduler.h" #include #include -#include #include extern const BOOTBOOT bootboot; @@ -67,9 +67,8 @@ Result init() kinfoln("Used memory: %s", to_dynamic_unit(MemoryManager::used()).release_value().chars()); kinfoln("Reserved memory: %s", to_dynamic_unit(MemoryManager::reserved()).release_value().chars()); - TarStream stream((void*)bootboot.initrd_ptr, bootboot.initrd_size); TarStream::Entry entry; - while (TRY(stream.read_next_entry().try_set_value_with_specific_error(entry, 0))) + while (TRY(g_initrd.read_next_entry().try_set_value_with_specific_error(entry, 0))) { if (entry.type == TarStream::EntryType::RegularFile) { @@ -78,7 +77,7 @@ Result init() if (!strcmp(entry.name, "sys/config")) { - auto contents = TRY(stream.read_contents_as_string(entry, 0, entry.size)); + auto contents = TRY(g_initrd.read_contents_as_string(entry, 0, entry.size)); kinfoln("%s", contents.chars()); } diff --git a/luna/include/luna/TarStream.h b/luna/include/luna/TarStream.h index fede39dd..29506dbe 100644 --- a/luna/include/luna/TarStream.h +++ b/luna/include/luna/TarStream.h @@ -24,6 +24,7 @@ class TarStream friend class TarStream; }; + TarStream() = default; TarStream(void* base, usize size); void initialize(void* base, usize size); From e5ae2b043568a33052c924e2a9c107f74f5f9af6 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 13:08:31 +0100 Subject: [PATCH 328/407] TarStream: Make read_contents and friends const --- luna/include/luna/TarStream.h | 4 ++-- luna/src/TarStream.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/luna/include/luna/TarStream.h b/luna/include/luna/TarStream.h index 29506dbe..9c926331 100644 --- a/luna/include/luna/TarStream.h +++ b/luna/include/luna/TarStream.h @@ -33,9 +33,9 @@ class TarStream void rewind(); - usize read_contents(const Entry& entry, void* buf, usize offset, usize length); + usize read_contents(const Entry& entry, void* buf, usize offset, usize length) const; - Result read_contents_as_string(const Entry& entry, usize offset, usize max); + Result read_contents_as_string(const Entry& entry, usize offset, usize max) const; private: struct [[gnu::packed]] TarHeader diff --git a/luna/src/TarStream.cpp b/luna/src/TarStream.cpp index 7383ef07..0235881c 100644 --- a/luna/src/TarStream.cpp +++ b/luna/src/TarStream.cpp @@ -87,7 +87,7 @@ Result TarStream::read_next_entry() return parse_header(&header); } -usize TarStream::read_contents(const Entry& entry, void* buf, usize offset, usize length) +usize TarStream::read_contents(const Entry& entry, void* buf, usize offset, usize length) const { if (offset >= entry.size) return 0; if ((length + offset) > entry.size) length = entry.size - offset; @@ -97,7 +97,7 @@ usize TarStream::read_contents(const Entry& entry, void* buf, usize offset, usiz return length; } -Result TarStream::read_contents_as_string(const Entry& entry, usize offset, usize max) +Result TarStream::read_contents_as_string(const Entry& entry, usize offset, usize max) const { char* buf = TRY(make_array(max + 1)); From f2cc79759989e2dd5024f9ed00989367366a7baa Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 23 Dec 2022 13:09:21 +0100 Subject: [PATCH 329/407] Add a simple ELF loader --- .gitignore | 3 +- CMakeLists.txt | 5 +- apps/CMakeLists.txt | 6 ++ apps/app.asm | 18 ++++++ kernel/CMakeLists.txt | 1 + kernel/src/ELF.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++ kernel/src/ELF.h | 78 ++++++++++++++++++++++++ kernel/src/main.cpp | 11 ++-- 8 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 apps/CMakeLists.txt create mode 100644 apps/app.asm create mode 100644 kernel/src/ELF.cpp create mode 100644 kernel/src/ELF.h diff --git a/.gitignore b/.gitignore index 616233bd..34f5764f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ toolchain/ .vscode/ build/ initrd/boot/moon -env-local.sh \ No newline at end of file +env-local.sh +initrd/bin/** \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f522402..a43fbb8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ set(CMAKE_CXX_COMPILER x86_64-luna-g++) set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) +set(CMAKE_ASM_NASM_LINK_EXECUTABLE "x86_64-luna-ld -o ") + set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) set(ARCH $ENV{ARCH}) @@ -25,4 +27,5 @@ endif() message(STATUS "Configuring Luna for ${ARCH}") add_subdirectory(luna) -add_subdirectory(kernel) \ No newline at end of file +add_subdirectory(kernel) +add_subdirectory(apps) \ No newline at end of file diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt new file mode 100644 index 00000000..cc7a0218 --- /dev/null +++ b/apps/CMakeLists.txt @@ -0,0 +1,6 @@ +function(luna_app SOURCE_FILE APP_NAME) + add_executable(${APP_NAME} ${SOURCE_FILE}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${APP_NAME}" DESTINATION ${LUNA_ROOT}/initrd/bin) +endfunction() + +luna_app(app.asm app) \ No newline at end of file diff --git a/apps/app.asm b/apps/app.asm new file mode 100644 index 00000000..78dc6066 --- /dev/null +++ b/apps/app.asm @@ -0,0 +1,18 @@ +section .text +global _start +_start: + mov eax, ecx + push rdx + mov eax, 1 + mov edi, hello_world + mov esi, 14 + int 42h + nop + +section .rodata +hello_world: + db 'Hello, world!', 0xa, 0 + +section .bss +array: + resb 10 \ No newline at end of file diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 66637a77..7e9e5db4 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES src/thread/Thread.cpp src/thread/Scheduler.cpp src/InitRD.cpp + src/ELF.cpp ) if("${ARCH}" MATCHES "x86_64") diff --git a/kernel/src/ELF.cpp b/kernel/src/ELF.cpp new file mode 100644 index 00000000..fe4a1357 --- /dev/null +++ b/kernel/src/ELF.cpp @@ -0,0 +1,137 @@ +#include "ELF.h" +#include "Log.h" +#include "arch/CPU.h" +#include "arch/MMU.h" +#include "memory/MemoryManager.h" +#include +#include +#include +#include + +static bool can_execute_segment(u32 flags) +{ + return flags & 1; +} + +static bool can_write_segment(u32 flags) +{ + return flags & 2; +} + +/*static bool can_write_and_execute_segment(u32 flags) +{ + return can_write_segment(flags) && can_execute_segment(flags); +}*/ + +ELFSegment::ELFSegment(u64 base, usize size) : m_base(base), m_size(size) +{ +} + +namespace ELFLoader +{ + // FIXME: Check that all calls to read_contents() read the proper amount of bytes. + Result load(const TarStream::Entry& elf_entry, const TarStream& stream) + { + LinkedList segments; + + auto guard = make_scope_guard([&] { segments.consume([](ELFSegment* segment) { delete segment; }); }); + + Elf64_Ehdr elf_header; + usize nread = stream.read_contents(elf_entry, &elf_header, 0, sizeof elf_header); + if (nread < sizeof elf_header) + { + kdbgln("Error while loading ELF: ELF header does not fit in entry"); + return err(ENOEXEC); + } + + if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) + { + kdbgln("Error while loading ELF: ELF header has no valid magic"); + return err(ENOEXEC); + } + + if (elf_header.e_ident[EI_CLASS] != ELFCLASS64) + { + kdbgln("Error while loading ELF: ELF object is not 64-bit"); + return err(ENOEXEC); + } + + if (elf_header.e_ident[EI_DATA] != ELFDATA2LSB) + { + kdbgln("Error while loading ELF: ELF object is not 2's complement little-endian"); + return err(ENOEXEC); + } + + if (elf_header.e_type != ET_EXEC) + { + kdbgln("Error while loading ELF: ELF object is not an executable"); + return err(ENOEXEC); + } + + if (elf_header.e_machine != EM_MACH) + { + kdbgln("Error while loading ELF: ELF object's target architecture does not match the current one (%s)", + CPU::platform_string()); + return err(ENOEXEC); + } + + if (elf_header.e_phnum == 0) + { + kdbgln("Error while loading ELF: ELF object has no program headers"); + return err(ENOEXEC); + } + + kdbgln("ELF: Loading ELF with entry=%#.16lx", elf_header.e_entry); + + usize i; + Elf64_Phdr program_header; + + for (stream.read_contents(elf_entry, &program_header, elf_header.e_phoff, sizeof program_header), i = 0; + i < elf_header.e_phnum; + i++, stream.read_contents(elf_entry, &program_header, elf_header.e_phoff + (i * elf_header.e_phentsize), + sizeof program_header)) + { + if (program_header.p_type == PT_LOAD) + { + kdbgln("ELF: Loading segment (offset=%zu, base=%#.16lx, filesize=%zu, memsize=%zu)", + program_header.p_offset, program_header.p_vaddr, program_header.p_filesz, + program_header.p_memsz); + + check(is_aligned(program_header.p_vaddr)); + /*expect(!can_write_and_execute_segment(program_header.p_flags), + "Segment is both writable and executable");*/ + + ELFSegment* segment = TRY(make(program_header.p_vaddr, program_header.p_memsz)); + segments.append(segment); + + int flags = MMU::User | MMU::NoExecute; + if (can_write_segment(program_header.p_flags)) flags |= MMU::ReadWrite; + else if (can_execute_segment(program_header.p_flags)) + flags &= ~MMU::NoExecute; + + // Allocate physical memory for the segment + TRY(MemoryManager::alloc_at(program_header.p_vaddr, + get_blocks_from_size(program_header.p_memsz, ARCH_PAGE_SIZE), flags)); + + // Load the file section of the segment + stream.read_contents(elf_entry, (void*)program_header.p_vaddr, program_header.p_offset, + program_header.p_filesz); + + // Fill out the rest of the segment with 0s + memset((void*)(program_header.p_vaddr + program_header.p_filesz), 0, + program_header.p_memsz - program_header.p_filesz); + } + else { kdbgln("ELF: Encountered non-loadable program header, skipping"); } + } + + if (segments.count() == 0) + { + kdbgln("Error while loading ELF: No loadable segments"); + return err(ENOEXEC); + } + + guard.deactivate(); + + return ELFData { segments, elf_header.e_entry }; + } +} \ No newline at end of file diff --git a/kernel/src/ELF.h b/kernel/src/ELF.h new file mode 100644 index 00000000..1a3dce72 --- /dev/null +++ b/kernel/src/ELF.h @@ -0,0 +1,78 @@ +#pragma once +#include +#include +#include + +#define ELFMAG "\177ELF" +#define SELFMAG 4 +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ET_EXEC 2 /* Executable file */ +#define PT_LOAD 1 /* Loadable program segment */ +#ifdef ARCH_X86_64 +#define EM_MACH 62 /* AMD x86-64 architecture */ +#else +#error "Unknown architecture." +#endif + +typedef struct +{ + u8 e_ident[16]; /* Magic number and other info */ + u16 e_type; /* Object file type */ + u16 e_machine; /* Architecture */ + u32 e_version; /* Object file version */ + u64 e_entry; /* Entry point virtual address */ + u64 e_phoff; /* Program header table file offset */ + u64 e_shoff; /* Section header table file offset */ + u32 e_flags; /* Processor-specific flags */ + u16 e_ehsize; /* ELF header size in bytes */ + u16 e_phentsize; /* Program header table entry size */ + u16 e_phnum; /* Program header table entry count */ + u16 e_shentsize; /* Section header table entry size */ + u16 e_shnum; /* Section header table entry count */ + u16 e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +typedef struct +{ + u32 p_type; /* Segment type */ + u32 p_flags; /* Segment flags */ + u64 p_offset; /* Segment file offset */ + u64 p_vaddr; /* Segment virtual address */ + u64 p_paddr; /* Segment physical address */ + u64 p_filesz; /* Segment size in file */ + u64 p_memsz; /* Segment size in memory */ + u64 p_align; /* Segment alignment */ +} Elf64_Phdr; + +struct ELFSegment : public LinkedListNode +{ + u64 base() const + { + return m_base; + } + + usize size() const + { + return m_size; + } + + ELFSegment(u64 base, usize size); + + private: + u64 m_base; + usize m_size; +}; + +struct ELFData +{ + LinkedList segments; + u64 entry; +}; + +namespace ELFLoader +{ + Result load(const TarStream::Entry& elf_entry, const TarStream& stream); +}; \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index cfd37243..83519890 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,3 +1,4 @@ +#include "ELF.h" #include "InitRD.h" #include "Log.h" #include "arch/CPU.h" @@ -67,6 +68,8 @@ Result init() kinfoln("Used memory: %s", to_dynamic_unit(MemoryManager::used()).release_value().chars()); kinfoln("Reserved memory: %s", to_dynamic_unit(MemoryManager::reserved()).release_value().chars()); + MMU::unmap(0x400000); + TarStream::Entry entry; while (TRY(g_initrd.read_next_entry().try_set_value_with_specific_error(entry, 0))) { @@ -75,11 +78,11 @@ Result init() kinfoln("Found file %s in initial ramdisk, of size %s", entry.name, to_dynamic_unit(entry.size).release_value().chars()); - if (!strcmp(entry.name, "sys/config")) + if (!strcmp(entry.name, "bin/app")) { - auto contents = TRY(g_initrd.read_contents_as_string(entry, 0, entry.size)); - - kinfoln("%s", contents.chars()); + auto data = TRY(ELFLoader::load(entry, g_initrd)); + data.segments.consume([](ELFSegment* segment) { delete segment; }); + kinfoln("Loaded ELF with entry=%#.16lx", data.entry); } } } From f71ccde8330b8317d3a72947cf5f8689ac1ef289 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 24 Dec 2022 11:49:12 +0100 Subject: [PATCH 330/407] Add an overload for aligned deletes which just calls the normal operator delete --- luna/include/luna/Alloc.h | 1 + luna/src/Alloc.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/luna/include/luna/Alloc.h b/luna/include/luna/Alloc.h index 562ac483..921dbe3d 100644 --- a/luna/include/luna/Alloc.h +++ b/luna/include/luna/Alloc.h @@ -20,6 +20,7 @@ void raw_free(void*); void* operator new(usize size, const std::nothrow_t&) noexcept; void* operator new[](usize size, const std::nothrow_t&) noexcept; +void operator delete(void* ptr, usize size, std::align_val_t alignment) noexcept; template [[nodiscard]] Result make(Args... args) { diff --git a/luna/src/Alloc.cpp b/luna/src/Alloc.cpp index 57ec3eb7..d97a3434 100644 --- a/luna/src/Alloc.cpp +++ b/luna/src/Alloc.cpp @@ -22,4 +22,9 @@ void raw_free(void* ptr) #else return free(ptr); #endif +} + +void operator delete(void* ptr, usize size, std::align_val_t) noexcept +{ + operator delete(ptr, size); } \ No newline at end of file From 59d69f684f0962dd0fb0ce2c5954819b8fe735c9 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 24 Dec 2022 11:49:47 +0100 Subject: [PATCH 331/407] x86_64: Add general protection fault handler --- kernel/src/arch/x86_64/CPU.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 5a725e88..f343c4af 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -28,6 +28,8 @@ extern void setup_idt(); [[noreturn]] void handle_page_fault(Registers* regs) { + CPU::disable_interrupts(); + u64 cr2; asm volatile("mov %%cr2, %0" : "=r"(cr2)); kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2); @@ -37,6 +39,17 @@ extern void setup_idt(); CPU::efficient_halt(); } +[[noreturn]] void handle_general_protection_fault(Registers* regs) +{ + CPU::disable_interrupts(); + + kerrorln("General protection fault at RIP %lx, error code %lx!", regs->rip, regs->error); + + CPU::print_stack_trace_at(regs); + + CPU::efficient_halt(); +} + extern "C" void handle_x86_exception(Registers* regs) { switch (regs->isr) @@ -52,7 +65,7 @@ extern "C" void handle_x86_exception(Registers* regs) case 10: FIXME_UNHANDLED_INTERRUPT("Invalid TSS"); case 11: FIXME_UNHANDLED_INTERRUPT("Segment not present"); case 12: FIXME_UNHANDLED_INTERRUPT("Stack-segment fault"); - case 13: FIXME_UNHANDLED_INTERRUPT("General protection fault"); + case 13: handle_general_protection_fault(regs); case 14: handle_page_fault(regs); case 16: FIXME_UNHANDLED_INTERRUPT("x87 floating-point exception"); case 17: FIXME_UNHANDLED_INTERRUPT("Alignment check"); From 08984e1673365a17ae8ebdfbd37b24c6c6a64137 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 12:10:47 +0100 Subject: [PATCH 332/407] x86_64: Create a has_flag() helper function and remove redundant clearing of reserved bits --- kernel/src/arch/x86_64/MMU.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 3b927aa4..c381b7d9 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -24,6 +24,11 @@ void PageTableEntry::clear() raw = 0; } +static bool has_flag(int flags, MMU::Flags flag) +{ + return flags & flag; +} + namespace MMU { @@ -172,7 +177,6 @@ namespace MMU l4.present = true; l4.set_address(addr); memset(l3_table(virt), 0, ARCH_PAGE_SIZE); - l4.ignore0 = l4.ignore1 = 0; } if (flags & Flags::ReadWrite) l4.read_write = true; if (flags & Flags::User) l4.user = true; @@ -184,7 +188,6 @@ namespace MMU l3.present = true; l3.set_address(addr); memset(l2_table(virt), 0, ARCH_PAGE_SIZE); - l3.ignore0 = l3.ignore1 = 0; } if (flags & Flags::ReadWrite) l3.read_write = true; if (flags & Flags::User) l3.user = true; @@ -198,7 +201,6 @@ namespace MMU l2.present = true; l2.set_address(addr); memset(l1_table(virt), 0, ARCH_PAGE_SIZE); - l2.ignore0 = l2.ignore1 = 0; } if (flags & Flags::ReadWrite) l2.read_write = true; if (flags & Flags::User) l2.user = true; @@ -207,13 +209,12 @@ namespace MMU auto& l1 = l1_entry(virt); if (l1.present) return err(EEXIST); // Please explicitly unmap the page before mapping it again. - l1.ignore0 = l1.ignore1 = false; l1.present = true; - l1.read_write = (flags & Flags::ReadWrite); - l1.user = (flags & Flags::User); - l1.write_through = (flags & Flags::WriteThrough); - l1.cache_disabled = (flags & Flags::CacheDisable); - l1.no_execute = (flags & Flags::NoExecute); + l1.read_write = has_flag(flags, Flags::ReadWrite); + l1.user = has_flag(flags, Flags::User); + l1.write_through = has_flag(flags, Flags::WriteThrough); + l1.cache_disabled = has_flag(flags, Flags::CacheDisable); + l1.no_execute = has_flag(flags, Flags::NoExecute); l1.set_address(phys); return {}; } @@ -222,11 +223,12 @@ namespace MMU { auto& l1 = *TRY(apply_cascading_flags(virt, flags)); if (!l1.present) return err(EFAULT); - l1.read_write = (flags & Flags::ReadWrite); - l1.user = (flags & Flags::User); - l1.write_through = (flags & Flags::WriteThrough); - l1.cache_disabled = (flags & Flags::CacheDisable); - l1.no_execute = (flags & Flags::NoExecute); + l1.read_write = has_flag(flags, Flags::ReadWrite); + l1.user = has_flag(flags, Flags::User); + l1.write_through = has_flag(flags, Flags::WriteThrough); + l1.cache_disabled = has_flag(flags, Flags::CacheDisable); + l1.no_execute = has_flag(flags, Flags::NoExecute); + flush_page(virt); return {}; } From 0054777e7df5c5281fcabb268293291ff9baf490 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 12:11:10 +0100 Subject: [PATCH 333/407] x86_64: Warn if NX is not supported --- kernel/src/arch/x86_64/CPU.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index f343c4af..e58c4fa8 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -143,6 +143,8 @@ namespace CPU enable_sse(); enable_write_protect(); if (test_nx()) enable_nx(); + else + kwarnln("not setting the NX bit as it is unsupported"); setup_gdt(); setup_idt(); } From 73c58bd902bc92da361a052cb31909d9250d7f49 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 12:12:55 +0100 Subject: [PATCH 334/407] Init: Move platform_init() before MemoryManager::init() This enables NX before we actually use it. Wasn't causing problems with KVM on, but crashed with KVM off with a 'reserved bit set' page fault. --- kernel/src/boot/Init.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index e28471ab..2c413a02 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -28,10 +28,10 @@ void Init::early_init() setup_log(log_debug_enabled(), log_serial_enabled(), true); + CPU::platform_init(); + MemoryManager::init(); InitRD::initialize(); - CPU::platform_init(); - MemoryManager::protect_kernel_sections().expect_release_value("We should succeed to protect sections"); } \ No newline at end of file From 7e62ee66be6ff0b273db304d190920377abd076a Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 12:24:39 +0100 Subject: [PATCH 335/407] Change heap.first().has_value() to the cheaper heap.count() --- kernel/src/memory/Heap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index ec590d74..fa663dce 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -175,7 +175,7 @@ Result kmalloc(usize size, bool should_scrub) size = align_up<16>(size); - if (!heap.first().has_value()) + if (heap.count() == 0) { const usize pages = get_pages_for_allocation(size + sizeof(HeapBlock)); HeapBlock* const block = TRY(allocate_pages(pages)); From 7efb79dd2606efcb56d3ee02f17720325f2eb1de Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 12:45:49 +0100 Subject: [PATCH 336/407] LinkedList: Check for nullptrs in detach_from_list() --- luna/include/luna/LinkedList.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 63b858b8..bfb1f2de 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -41,8 +41,8 @@ template class LinkedListNode void detach_from_list() { - m_next_node->m_last_node = m_last_node; - m_last_node->m_next_node = m_next_node; + if (m_next_node) m_next_node->m_last_node = m_last_node; + if (m_last_node) m_last_node->m_next_node = m_next_node; } void append_to_list(SelfType* end_node) From 2600acc96c0f8bc45d5bc1637bee41fab2b285bb Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 12:46:07 +0100 Subject: [PATCH 337/407] Thread: Add init_regs_user() --- kernel/src/arch/x86_64/Thread.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/src/arch/x86_64/Thread.cpp b/kernel/src/arch/x86_64/Thread.cpp index b9b76d59..042ef119 100644 --- a/kernel/src/arch/x86_64/Thread.cpp +++ b/kernel/src/arch/x86_64/Thread.cpp @@ -34,6 +34,14 @@ void Thread::init_regs_kernel() regs.rflags = 1 << 9; // IF (Interrupt enable flag) } +void Thread::init_regs_user() +{ + memset(®s, 0, sizeof(Registers)); + regs.cs = 0x18 | 3; + regs.ss = 0x20 | 3; + regs.rflags = 1 << 9; // IF (Interrupt enable flag) +} + void Thread::set_arguments(u64 arg1, u64 arg2, u64 arg3, u64 arg4) { regs.rdi = arg1; From a1eca479d551482a630a64efae19f12198fb1a3a Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 12:57:25 +0100 Subject: [PATCH 338/407] x86_64: Add a getter for the initial page directory --- kernel/src/arch/MMU.h | 2 ++ kernel/src/arch/x86_64/MMU.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index 095ed40a..cc0b6b42 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -32,4 +32,6 @@ namespace MMU Result create_page_directory_for_userspace(); void setup_initial_page_directory(); + + PageDirectory* kernel_page_directory(); } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index c381b7d9..a985df7b 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -7,6 +7,8 @@ #pragma GCC push_options #pragma GCC diagnostic ignored "-Wconversion" +PageDirectory* g_kernel_directory; + void PageTableEntry::set_address(u64 addr) { this->address = (addr >> 12); @@ -259,6 +261,7 @@ namespace MMU void setup_initial_page_directory() { PageDirectory* const dir = get_page_directory(); + g_kernel_directory = dir; const u64 paddr = (u64)dir; PageTableEntry& recursive_entry = dir->entries[rindex]; recursive_entry.read_write = true; @@ -266,4 +269,9 @@ namespace MMU recursive_entry.set_address(paddr); flush_all(); } + + PageDirectory* kernel_page_directory() + { + return g_kernel_directory; + } } \ No newline at end of file From 1c70ab5a1ac4916294a500e4cb0f2e80bf19db10 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 15:20:56 +0100 Subject: [PATCH 339/407] Heap: Avoid combines with blocks outside a range --- kernel/src/memory/Heap.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index fa663dce..3a2f4b67 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -125,8 +125,14 @@ static Option split(HeapBlock* block, usize size) static Result combine_forward(HeapBlock* block) { + // This block ends a memory range, cannot be combined with blocks outside its range. + if (block->status & BLOCK_END_MEM) return {}; + // The caller needs to ensure there is a next block. HeapBlock* const next = heap.next(block).value(); + // This block starts a memory range, cannot be combined with blocks outside its range. + if (next->status & BLOCK_START_MEM) return {}; + heap.remove(next); next->magic = BLOCK_DEAD; @@ -148,8 +154,13 @@ static Result combine_forward(HeapBlock* block) static Result combine_backward(HeapBlock* block) { + // This block starts a memory range, cannot be combined with blocks outside its range. + if (block->status & BLOCK_START_MEM) return block; + // The caller needs to ensure there is a last block. HeapBlock* const last = heap.previous(block).value(); + // This block ends a memory range, cannot be combined with blocks outside its range. + if (last->status & BLOCK_END_MEM) return block; heap.remove(block); block->magic = BLOCK_DEAD; From 2af39974562619094441e0485b7ec7025d9dd717 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 15:54:29 +0100 Subject: [PATCH 340/407] LinkedList: Fixed some boogs, LinkedList is now boog-free :) --- luna/include/luna/LinkedList.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index bfb1f2de..cb2e6c66 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -49,12 +49,14 @@ template class LinkedListNode { end_node->m_next_node = this; this->m_last_node = end_node; + this->m_next_node = nullptr; } void prepend_to_list(SelfType* start_node) { start_node->m_last_node = this; this->m_next_node = start_node; + this->m_last_node = nullptr; } friend class LinkedList; @@ -104,6 +106,8 @@ template class LinkedList if (m_end_node == base_node) m_end_node = new_node; + if (base_node->get_next()) base_node->get_next()->set_last(new_node); + new_node->set_next(base_node->get_next()); base_node->set_next(new_node); new_node->set_last(base_node); From ed34009b50d733380d6d7deb5c4bb4e89e243802 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 16:17:24 +0100 Subject: [PATCH 341/407] Heap: Log more details of blocks --- kernel/src/memory/Heap.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index 3a2f4b67..ace511c4 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -140,7 +140,8 @@ static Result combine_forward(HeapBlock* block) { if (next->status & BLOCK_START_MEM) { - TRY(release_pages(next, get_blocks_from_size(next->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE))); + const usize pages = get_blocks_from_size(next->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE); + TRY(release_pages(next, pages)); return {}; } else @@ -168,7 +169,8 @@ static Result combine_backward(HeapBlock* block) { if (block->status & BLOCK_START_MEM) { - TRY(release_pages(block, get_blocks_from_size(block->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE))); + const usize pages = get_blocks_from_size(block->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE); + TRY(release_pages(block, pages)); return last; } else @@ -284,7 +286,8 @@ Result kfree(void* ptr) if ((block->status & BLOCK_START_MEM) && (block->status & BLOCK_END_MEM)) { heap.remove(block); - TRY(release_pages(block, get_blocks_from_size(block->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE))); + const usize pages = get_blocks_from_size(block->full_size + sizeof(HeapBlock), ARCH_PAGE_SIZE); + TRY(release_pages(block, pages)); } return {}; @@ -363,12 +366,15 @@ void dump_heap_usage() { if (is_block_free(block)) { - kdbgln("- Available block, of size %zu", block->full_size); + kdbgln("- Available block (%p), of size %zu (%s%s)", (void*)block, block->full_size, + block->status & BLOCK_START_MEM ? "b" : "-", block->status & BLOCK_END_MEM ? "e" : "-"); alloc_total += block->full_size + sizeof(HeapBlock); } else { - kdbgln("- Used block, of size %zu, of which %zu bytes are being used", block->full_size, block->req_size); + kdbgln("- Used block (%p), of size %zu, of which %zu bytes are being used (%s%s)", (void*)block, + block->full_size, block->req_size, block->status & BLOCK_START_MEM ? "b" : "-", + block->status & BLOCK_END_MEM ? "e" : "-"); alloc_total += block->full_size + sizeof(HeapBlock); alloc_used += block->req_size; } From 7952d1d8a085a229977e43b958a317de6ea57b19 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 19:59:18 +0100 Subject: [PATCH 342/407] x86_64: Add basic keyboard support with an ASYNC DRIVER --- kernel/src/arch/x86_64/CPU.asm | 3 +- kernel/src/arch/x86_64/CPU.cpp | 25 ++++++++++++- kernel/src/arch/x86_64/init/IDT.cpp | 2 + kernel/src/arch/x86_64/init/PIC.cpp | 2 +- kernel/src/main.cpp | 16 +------- luna/include/luna/CircularQueue.h | 57 +++++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 luna/include/luna/CircularQueue.h diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index f3e2d2fc..f5a2c98a 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -186,4 +186,5 @@ ISR 19 ; SIMD floating-point exception (#XM) ISR 20 ; virtualization exception (#VE) ISR_ERROR 21 ; control-protection exception (#CP) ; ISR 22-31 reserved -IRQ 32, 0 ; timer interrupt \ No newline at end of file +IRQ 32, 0 ; timer interrupt +IRQ 33, 0 ; keyboard interrupt \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index e58c4fa8..44c5a932 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -2,10 +2,12 @@ #include "Log.h" #include "arch/Timer.h" #include "arch/x86_64/CPU.h" +#include "arch/x86_64/IO.h" #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include #include +#include #include #include #include @@ -76,16 +78,35 @@ extern "C" void handle_x86_exception(Registers* regs) } } +CircularQueue scancode_queue; + +void io_thread() +{ + while (true) + { + u8 scancode; + while (!scancode_queue.try_pop(scancode)) { kernel_sleep(10); } + + kinfoln("Read scancode: %#hhx", scancode); + } +} + // Called from _asm_interrupt_entry extern "C" void arch_interrupt_entry(Registers* regs) { if (regs->isr < 32) handle_x86_exception(regs); - else if (regs->isr == 32) + else if (regs->isr == 32) // Timer interrupt { Timer::tick(); if (should_invoke_scheduler()) Scheduler::invoke(regs); pic_eoi(regs); } + else if (regs->isr == 33) // Keyboard interrupt + { + u8 scancode = IO::inb(0x60); + scancode_queue.try_push(scancode); + pic_eoi(regs); + } else { kwarnln("IRQ catched! Halting."); @@ -151,6 +172,8 @@ namespace CPU void platform_finish_init() { + Scheduler::new_kernel_thread(io_thread).expect_value("Could not create the IO background thread!"); + remap_pic(); } diff --git a/kernel/src/arch/x86_64/init/IDT.cpp b/kernel/src/arch/x86_64/init/IDT.cpp index eb1d01e6..00ad454b 100644 --- a/kernel/src/arch/x86_64/init/IDT.cpp +++ b/kernel/src/arch/x86_64/init/IDT.cpp @@ -82,6 +82,7 @@ INT(19); INT(20); INT(21); INT(32); +INT(33); void setup_idt() { @@ -108,6 +109,7 @@ void setup_idt() TRAP(20); TRAP(21); IRQ(32); + IRQ(33); static IDTR idtr; idtr.limit = 0x0FFF; diff --git a/kernel/src/arch/x86_64/init/PIC.cpp b/kernel/src/arch/x86_64/init/PIC.cpp index a3af5be2..632c94a0 100644 --- a/kernel/src/arch/x86_64/init/PIC.cpp +++ b/kernel/src/arch/x86_64/init/PIC.cpp @@ -36,7 +36,7 @@ void remap_pic() IO::outb(PIC2_DATA, ICW4_8086); io_delay(); - IO::outb(PIC1_DATA, 0b11111110); + IO::outb(PIC1_DATA, 0b11111100); io_delay(); IO::outb(PIC2_DATA, 0b11111111); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 83519890..7237c191 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -12,25 +12,12 @@ #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include +#include #include #include extern const BOOTBOOT bootboot; -void async_thread() -{ - while (true) - { - Thread* current = Scheduler::current(); - kinfoln("Ticks: %lu, %lu user, %lu kernel, %lu idle", current->ticks, current->ticks_in_user, - current->ticks_in_kernel, Scheduler::idle()->ticks); - - CPU::wait_for_interrupt(); - - kernel_sleep(1000); - } -} - void heap_thread() { CPU::disable_interrupts(); @@ -90,7 +77,6 @@ Result init() Thread::init(); Scheduler::init(); - TRY(Scheduler::new_kernel_thread(async_thread)); TRY(Scheduler::new_kernel_thread(heap_thread)); TRY(Scheduler::new_kernel_thread(reap_thread)); diff --git a/luna/include/luna/CircularQueue.h b/luna/include/luna/CircularQueue.h new file mode 100644 index 00000000..3960854e --- /dev/null +++ b/luna/include/luna/CircularQueue.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include + +template class CircularQueue +{ + enum + { + Capacity = Size + 1 + }; + + public: + CircularQueue() + { + } + + bool try_push(const T& value) + { + usize current_tail = m_tail.load(MemoryOrder::Relaxed); + const usize new_tail = (current_tail + 1) % Capacity; + if (new_tail == m_head.load(MemoryOrder::Acquire)) + { + // Queue is full + return false; + } + m_data[current_tail] = value; + if (!m_tail.compare_exchange_strong(current_tail, new_tail, MemoryOrder::Release, MemoryOrder::Relaxed)) + { + // Someone else updated the tail + return false; + } + return true; + } + + bool try_pop(T& value) + { + usize current_head = m_head.load(MemoryOrder::Relaxed); + if (current_head == m_tail.load(MemoryOrder::Acquire)) + { + // Queue is empty + return false; + } + value = m_data[current_head]; + const usize new_head = (current_head + 1) % Capacity; + if (!m_head.compare_exchange_strong(current_head, new_head, MemoryOrder::Release, MemoryOrder::Relaxed)) + { + // Someone else updated the head + return false; + } + return true; + } + + private: + T m_data[Capacity]; + Atomic m_head = 0; + Atomic m_tail = 0; +}; From 8e59a0a79f65fa450e510fb9692e1cdb333a01af Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 11:48:18 +0100 Subject: [PATCH 343/407] CMakeLists improvements --- CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a43fbb8f..037a08ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,21 +9,21 @@ project(Luna LANGUAGES C CXX ASM_NASM VERSION 0.1.0) set(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR}) -set(CMAKE_C_COMPILER x86_64-luna-gcc) -set(CMAKE_CXX_COMPILER x86_64-luna-g++) - -set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) - -set(CMAKE_ASM_NASM_LINK_EXECUTABLE "x86_64-luna-ld -o ") - -set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) - set(ARCH $ENV{ARCH}) if(NOT DEFINED $ENV{ARCH}) set(ARCH "x86_64") endif() +set(CMAKE_C_COMPILER ${ARCH}-luna-gcc) +set(CMAKE_CXX_COMPILER ${ARCH}-luna-g++) + +set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) + +set(CMAKE_ASM_NASM_LINK_EXECUTABLE "${ARCH}-luna-ld -o ") + +set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) + message(STATUS "Configuring Luna for ${ARCH}") add_subdirectory(luna) From 400d0395a2fce0fe7d4b1778b56f4405516efef1 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 15:00:02 +0100 Subject: [PATCH 344/407] Result: Avoid double-checking when calling through to the underlying Option --- luna/include/luna/Badge.h | 12 ++++++++++++ luna/include/luna/Option.h | 14 ++++++++++++++ luna/include/luna/Result.h | 8 ++++---- 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 luna/include/luna/Badge.h diff --git a/luna/include/luna/Badge.h b/luna/include/luna/Badge.h new file mode 100644 index 00000000..c319b035 --- /dev/null +++ b/luna/include/luna/Badge.h @@ -0,0 +1,12 @@ +#pragma once + +template struct Badge +{ + private: + constexpr Badge() = default; + + Badge(const Badge&) = delete; + Badge(Badge&&) = delete; + + friend T; +}; \ No newline at end of file diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index cbe7ad7d..2173b704 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -1,8 +1,11 @@ #pragma once +#include #include #include #include +template class Result; + template class Option { public: @@ -42,6 +45,11 @@ template class Option return m_storage.fetch_reference(); } + T unchecked_value(Badge>) const + { + return m_storage.fetch_reference(); + } + T release_value() { expect(has_value(), "Option::release_value called on an empty Option"); @@ -49,6 +57,12 @@ template class Option return move(m_storage.fetch_reference()); } + T unchecked_release_value(Badge>) + { + m_has_value = false; + return move(m_storage.fetch_reference()); + } + T value_or(const T& other) const { if (has_value()) return m_storage.fetch_reference(); diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index 180ea158..36124bac 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -72,13 +72,13 @@ template class Result T value() const { expect(has_value(), "Result::value() called on a Result that holds an error"); - return m_value.value(); + return m_value.unchecked_value({}); } T expect_value(const char* reason) const { expect(has_value(), reason); - return m_value.value(); + return m_value.unchecked_value({}); } T value_or(const T& other) const @@ -101,13 +101,13 @@ template class Result T release_value() { expect(has_value(), "Result::release_value() called on a Result that holds an error"); - return m_value.release_value(); + return m_value.unchecked_release_value({}); } T expect_release_value(const char* reason) { expect(has_value(), reason); - return m_value.release_value(); + return m_value.unchecked_release_value({}); } private: From 956938569136dba2cdec7d239b9566ad3bd3a198 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 18:32:44 +0100 Subject: [PATCH 345/407] Remove unused include --- kernel/src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 7237c191..69569cba 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -12,7 +12,6 @@ #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include -#include #include #include From 74aa30a44fb8c8090acbd67cbf868a241af3eea5 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 18:36:22 +0100 Subject: [PATCH 346/407] Init: Call efficient_halt() on magic number mismatch instead of busy-looping --- kernel/src/boot/Init.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 2c413a02..69e40cb9 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -15,8 +15,7 @@ void Init::check_magic() if (memcmp(bootboot.magic, BOOTBOOT_MAGIC, 4)) { kerrorln("ERROR: Invalid magic value from bootloader"); - for (;;) - ; + CPU::efficient_halt(); } } From 24773fbece5579f7e84a14a4a92a6fab4de2c3b7 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 18:38:50 +0100 Subject: [PATCH 347/407] kernel/main: Remove reference to 'extern const BOOTBOOT bootboot' --- kernel/src/main.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 69569cba..521b3178 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,7 +5,6 @@ #include "arch/MMU.h" #include "arch/Timer.h" #include "boot/Init.h" -#include "boot/bootboot.h" #include "config.h" #include "memory/Heap.h" #include "memory/KernelVM.h" @@ -15,8 +14,6 @@ #include #include -extern const BOOTBOOT bootboot; - void heap_thread() { CPU::disable_interrupts(); From 1f36ecd0446295959b76ee77881d9a7e94b85f28 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 18:43:39 +0100 Subject: [PATCH 348/407] LinkedList: Make expect_first() and expect_last() show a more accurate error description on panic Instead of showing a generic "Option::value() called on an empty Option" with no useful source location, you will get something like "check failed: m_start_node at LinkedList.h:139" --- luna/include/luna/LinkedList.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index cb2e6c66..3c6bcb44 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -136,7 +136,8 @@ template class LinkedList T* expect_first() { - return first().value(); + check(m_start_node); + return m_start_node; } Option last() @@ -146,7 +147,8 @@ template class LinkedList T* expect_last() { - return last().value(); + check(m_end_node); + return m_end_node; } Option next(T* item) From 28f53f9ccfd9d7ab210ac73fd3608f1e4a14e69f Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 18:44:37 +0100 Subject: [PATCH 349/407] LinkedList: Rename the nonnull_or_error() helper to a more accurate nonnull_or_empty_option() --- luna/include/luna/LinkedList.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 3c6bcb44..6a899ea1 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -2,7 +2,7 @@ #include #include -template inline Option nonnull_or_error(T* ptr) +template inline Option nonnull_or_empty_option(T* ptr) { if (ptr == nullptr) return {}; else @@ -131,7 +131,7 @@ template class LinkedList Option first() { - return nonnull_or_error((T*)m_start_node); + return nonnull_or_empty_option((T*)m_start_node); } T* expect_first() @@ -142,7 +142,7 @@ template class LinkedList Option last() { - return nonnull_or_error((T*)m_end_node); + return nonnull_or_empty_option((T*)m_end_node); } T* expect_last() @@ -153,12 +153,12 @@ template class LinkedList Option next(T* item) { - return nonnull_or_error((T*)extract_node(item)->get_next()); + return nonnull_or_empty_option((T*)extract_node(item)->get_next()); } Option previous(T* item) { - return nonnull_or_error((T*)extract_node(item)->get_last()); + return nonnull_or_empty_option((T*)extract_node(item)->get_last()); } // Iterates over the elements of the LinkedList from start to end, calling callback for every element. From 973e39a25586af96c250df0d6f0d1f7d6782a42d Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 18:46:18 +0100 Subject: [PATCH 350/407] LinkedList: Move nonnull_or_empty_option to Option.h so everyone can use it --- luna/include/luna/LinkedList.h | 7 ------- luna/include/luna/Option.h | 9 ++++++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 6a899ea1..c390f986 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -2,13 +2,6 @@ #include #include -template inline Option nonnull_or_empty_option(T* ptr) -{ - if (ptr == nullptr) return {}; - else - return ptr; -} - template class LinkedList; template class LinkedListNode diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index 2173b704..8dcf4521 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -142,4 +142,11 @@ template class Option }; Storage m_storage; bool m_has_value { false }; -}; \ No newline at end of file +}; + +template inline Option nonnull_or_empty_option(T* ptr) +{ + if (ptr == nullptr) return {}; + else + return ptr; +} \ No newline at end of file From 3a3968b26889cd25bf673072a3814c1e6895a031 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 18:46:27 +0100 Subject: [PATCH 351/407] Result: Add nonnull_or_error() --- luna/include/luna/Result.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index 36124bac..df34375b 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -202,3 +202,10 @@ template <> class Result if (!_expr_rc.has_value()) return _expr_rc.release_error(); \ _expr_rc.release_value(); \ }) + +template inline Result nonnull_or_error(T* ptr, int error) +{ + if (ptr == nullptr) return err(error); + else + return ptr; +} \ No newline at end of file From 4081186b2791289e68069a9a226e930574112a8c Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 19:02:25 +0100 Subject: [PATCH 352/407] Heap: Rewrite kmalloc to use Option instead of nullable pointers to iterate over the heap At some point, this should be done inside LinkedList itself, but we have no such thing as break in for_each(). It's iterate over everything or nothing. This also requires operator= in Option, might be also added to Result in the future. --- kernel/src/memory/Heap.cpp | 64 +++++++++++++++++++--------------- luna/include/luna/LinkedList.h | 4 +-- luna/include/luna/Option.h | 25 +++++++++++++ 3 files changed, 62 insertions(+), 31 deletions(-) diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index ace511c4..a8ae9c08 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -199,45 +199,50 @@ Result kmalloc(usize size, bool should_scrub) heap.append(block); } - HeapBlock* block = heap.expect_first(); - while (block) + Option block = heap.first(); + while (block.has_value()) { + HeapBlock* const current = block.value(); // Trying to find a free block... - if (is_block_free(block)) + if (is_block_free(current)) { - if (block->full_size < size) + if (current->full_size < size) { - block = heap.next(block).value_or(nullptr); + block = heap.next(current); continue; } break; // We found a free block that's big enough!! } - auto rc = split(block, size); + auto rc = split(current, size); if (rc.has_value()) { block = rc.value(); // We managed to get a free block from a larger used block!! break; } - block = heap.next(block).value_or(nullptr); + block = heap.next(current); } - if (!block) // No free blocks, let's allocate a new one + if (!block.has_value()) // No free blocks, let's allocate a new one { usize pages = get_pages_for_allocation(size + sizeof(HeapBlock)); - block = TRY(allocate_pages(pages)); + HeapBlock* const current = TRY(allocate_pages(pages)); - block->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); - block->magic = BLOCK_MAGIC; - block->status = BLOCK_START_MEM | BLOCK_END_MEM; - heap.append(block); + current->full_size = (pages * ARCH_PAGE_SIZE) - sizeof(HeapBlock); + current->magic = BLOCK_MAGIC; + current->status = BLOCK_START_MEM | BLOCK_END_MEM; + heap.append(current); + + block = current; } - block->req_size = size; - block->status |= BLOCK_USED; + HeapBlock* const current = block.value(); - if (should_scrub) { memset(get_pointer_from_heap_block(block), KMALLOC_SCRUB_BYTE, size); } + current->req_size = size; + current->status |= BLOCK_USED; - return get_pointer_from_heap_block(block); + if (should_scrub) { memset(get_pointer_from_heap_block(current), KMALLOC_SCRUB_BYTE, size); } + + return get_pointer_from_heap_block(current); } Result kfree(void* ptr) @@ -361,24 +366,25 @@ void dump_heap_usage() } usize alloc_total = 0; usize alloc_used = 0; - HeapBlock* block = heap.expect_first(); - while (block) + auto block = heap.first(); + while (block.has_value()) { - if (is_block_free(block)) + HeapBlock* current = block.value(); + if (is_block_free(current)) { - kdbgln("- Available block (%p), of size %zu (%s%s)", (void*)block, block->full_size, - block->status & BLOCK_START_MEM ? "b" : "-", block->status & BLOCK_END_MEM ? "e" : "-"); - alloc_total += block->full_size + sizeof(HeapBlock); + kdbgln("- Available block (%p), of size %zu (%s%s)", (void*)current, current->full_size, + current->status & BLOCK_START_MEM ? "b" : "-", current->status & BLOCK_END_MEM ? "e" : "-"); + alloc_total += current->full_size + sizeof(HeapBlock); } else { - kdbgln("- Used block (%p), of size %zu, of which %zu bytes are being used (%s%s)", (void*)block, - block->full_size, block->req_size, block->status & BLOCK_START_MEM ? "b" : "-", - block->status & BLOCK_END_MEM ? "e" : "-"); - alloc_total += block->full_size + sizeof(HeapBlock); - alloc_used += block->req_size; + kdbgln("- Used block (%p), of size %zu, of which %zu bytes are being used (%s%s)", (void*)current, + current->full_size, current->req_size, current->status & BLOCK_START_MEM ? "b" : "-", + current->status & BLOCK_END_MEM ? "e" : "-"); + alloc_total += current->full_size + sizeof(HeapBlock); + alloc_used += current->req_size; } - block = heap.next(block).value_or(nullptr); + block = heap.next(current); } kdbgln("-- Total memory allocated for heap: %zu bytes", alloc_total); diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index c390f986..442e0ecc 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -130,7 +130,7 @@ template class LinkedList T* expect_first() { check(m_start_node); - return m_start_node; + return (T*)m_start_node; } Option last() @@ -141,7 +141,7 @@ template class LinkedList T* expect_last() { check(m_end_node); - return m_end_node; + return (T*)m_end_node; } Option next(T* item) diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index 8dcf4521..6bbe8b5c 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -30,6 +30,31 @@ template class Option if (m_has_value) { m_storage.store_moved_reference(move(other.m_storage.fetch_reference())); } } + Option& operator=(const Option& other) + { + if (this == &other) return *this; + + if (m_has_value) m_storage.destroy(); + m_has_value = other.m_has_value; + + if (m_has_value) { m_storage.store_reference(other.m_storage.fetch_reference()); } + + return *this; + } + + Option& operator=(Option&& other) + { + if (this == &other) return *this; + + if (m_has_value) m_storage.destroy(); + m_has_value = other.m_has_value; + other.m_has_value = false; + + if (m_has_value) { m_storage.store_moved_reference(move(other.m_storage.fetch_reference())); } + + return *this; + } + Option() : m_has_value(false) { } From e2e21923d7b37c24ae4a25bd600c3a7879dc27dd Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 30 Dec 2022 19:06:47 +0100 Subject: [PATCH 353/407] Result: Implement operator=() --- luna/include/luna/Result.h | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index df34375b..f156b73c 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -41,6 +41,29 @@ template class Result { } + Result& operator=(const Result& other) + { + if (this == &other) return *this; + + m_has_value = other.m_has_value; + m_error = other.m_error; + m_value = other.m_value; + + return *this; + } + + Result& operator=(Result&& other) + { + if (this == &other) return *this; + + m_has_value = other.m_has_value; + other.m_has_value = false; + m_error = other.m_error; + m_value = move(other.m_value); + + return *this; + } + bool has_error() const { return !m_has_value; @@ -135,6 +158,26 @@ template <> class Result { } + Result& operator=(const Result& other) + { + if (this == &other) return *this; + + m_has_error = other.m_has_error; + m_error = other.m_error; + + return *this; + } + + Result& operator=(Result&& other) + { + if (this == &other) return *this; + + m_has_error = other.m_has_error; + m_error = other.m_error; + + return *this; + } + bool has_error() const { return m_has_error; From 831711ab7e4402c34ba4f9c6ebe02f3bf42ac035 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 31 Dec 2022 11:50:30 +0100 Subject: [PATCH 354/407] TypeTraits: Remove const, volatile, and reference --- luna/include/luna/TypeTraits.h | 47 +++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/luna/include/luna/TypeTraits.h b/luna/include/luna/TypeTraits.h index b9c6309c..e34e941d 100644 --- a/luna/include/luna/TypeTraits.h +++ b/luna/include/luna/TypeTraits.h @@ -1,4 +1,49 @@ #pragma once template inline constexpr bool IsBaseOf = __is_base_of(Base, Derived); -template inline constexpr bool IsPowerOfTwo = (value & (value - 1)) == 0; \ No newline at end of file +template inline constexpr bool IsPowerOfTwo = (value & (value - 1)) == 0; + +template struct __remove_const_impl +{ + using type = T; +}; + +template struct __remove_const_impl +{ + using type = T; +}; + +template using RemoveConst = __remove_const_impl::type; + +template struct __remove_volatile_impl +{ + using type = T; +}; + +template struct __remove_volatile_impl +{ + using type = T; +}; + +template using RemoveVolatile = __remove_volatile_impl::type; + +template using RemoveCV = RemoveVolatile>; + +template struct __remove_ref_impl +{ + using type = T; +}; + +template struct __remove_ref_impl +{ + using type = T; +}; + +template struct __remove_ref_impl +{ + using type = T; +}; + +template using RemoveReference = __remove_ref_impl::type; + +template using RemoveCVReference = RemoveCV>; \ No newline at end of file From df8f9c6cf614e719eaf2463ef0b72641acc08572 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 31 Dec 2022 12:02:15 +0100 Subject: [PATCH 355/407] SharedPtr: adopt_shared_from_owned --- luna/include/luna/OwnedPtr.h | 4 ++++ luna/include/luna/SharedPtr.h | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/luna/include/luna/OwnedPtr.h b/luna/include/luna/OwnedPtr.h index cc147f24..0f76630d 100644 --- a/luna/include/luna/OwnedPtr.h +++ b/luna/include/luna/OwnedPtr.h @@ -2,6 +2,8 @@ #include #include +template class SharedPtr; + template class OwnedPtr { public: @@ -38,6 +40,8 @@ template class OwnedPtr return *m_ptr; } + template friend Result> adopt_shared_from_owned(OwnedPtr&&); + private: T* m_ptr; }; diff --git a/luna/include/luna/SharedPtr.h b/luna/include/luna/SharedPtr.h index 4cf1bcff..6a9caffd 100644 --- a/luna/include/luna/SharedPtr.h +++ b/luna/include/luna/SharedPtr.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include @@ -118,4 +119,18 @@ template Result> adopt_shared_if_nonnull(T* ptr) if (ptr) return adopt_shared(ptr); else return err(ENOMEM); +} + +template Result> adopt_shared_from_owned(OwnedPtr&& other) +{ + T* ptr = other.m_ptr; + other.m_ptr = nullptr; + + auto guard = make_scope_guard([&] { delete ptr; }); + + SharedPtr shared_ptr = TRY(adopt_shared(ptr)); + + guard.deactivate(); + + return shared_ptr; } \ No newline at end of file From 344297067831621441b2f4f701f0969b42a65cec Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 2 Jan 2023 13:00:22 +0100 Subject: [PATCH 356/407] Add vscode configuration --- .gitignore | 1 - .vscode/c_cpp_properties.json | 13 +++++++++++++ .vscode/settings.json | 4 ++++ luna/CMakeLists.txt | 3 +++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 34f5764f..b8172a1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ Luna.iso toolchain/ -.vscode/ build/ initrd/boot/moon env-local.sh diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..c40fe288 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,13 @@ +{ + "configurations": [ + { + "name": "Luna", + "compilerPath": "${workspaceFolder}/toolchain/x86-64-luna/bin/x86_64-luna-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "gcc-x64", + "configurationProvider": "ms-vscode.cmake-tools" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..133694f8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "xaver.clang-format" +} \ No newline at end of file diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 7583fc4b..4d8be399 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -1,6 +1,9 @@ # The miscellaneous library shared between the Luna kernel and userspace, with stuff such as custom types, common routines and data structures. +file(GLOB HEADERS include/luna/*.h) + set(FREESTANDING_SOURCES + ${HEADERS} src/Format.cpp src/NumberParsing.cpp src/CString.cpp From aab3a0a840b9cc17acaa0f3936575d218bbc5876 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 2 Jan 2023 13:07:13 +0100 Subject: [PATCH 357/407] Update settings.json --- .vscode/settings.json | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 133694f8..6583b570 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,17 @@ { "editor.formatOnSave": true, - "editor.defaultFormatter": "xaver.clang-format" -} \ No newline at end of file + "editor.defaultFormatter": "xaver.clang-format", + "files.exclude": { + "toolchain/build/**": true, + "toolchain/tarballs/**": true, + }, + "search.exclude": { + "toolchain/build/**": true, + "toolchain/tarballs/**": true, + }, + "editor.tabSize": 4, + "files.trimFinalNewlines": true, + "files.insertFinalNewline": true, + "git.inputValidationLength": 72, + "git.inputValidationSubjectLength": 72 +} From 5854e5e53018d2de1715ed5a4d32a0cd0c46e7de Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 2 Jan 2023 13:07:29 +0100 Subject: [PATCH 358/407] Add newlines at end-of-file --- kernel/src/ELF.cpp | 2 +- kernel/src/ELF.h | 2 +- kernel/src/InitRD.cpp | 2 +- kernel/src/InitRD.h | 2 +- kernel/src/Log.cpp | 2 +- kernel/src/Log.h | 2 +- kernel/src/arch/CPU.h | 2 +- kernel/src/arch/MMU.h | 2 +- kernel/src/arch/Serial.cpp | 2 +- kernel/src/arch/Serial.h | 2 +- kernel/src/arch/Timer.cpp | 2 +- kernel/src/arch/Timer.h | 2 +- kernel/src/arch/x86_64/CPU.cpp | 2 +- kernel/src/arch/x86_64/CPU.h | 2 +- kernel/src/arch/x86_64/IO.cpp | 2 +- kernel/src/arch/x86_64/IO.h | 2 +- kernel/src/arch/x86_64/MMU.cpp | 2 +- kernel/src/arch/x86_64/MMU.h | 2 +- kernel/src/arch/x86_64/Serial.cpp | 2 +- kernel/src/arch/x86_64/Thread.cpp | 2 +- kernel/src/arch/x86_64/Timer.cpp | 2 +- kernel/src/arch/x86_64/Timer.h | 2 +- kernel/src/arch/x86_64/init/GDT.cpp | 2 +- kernel/src/arch/x86_64/init/IDT.cpp | 2 +- kernel/src/arch/x86_64/init/PIC.cpp | 2 +- kernel/src/boot/Init.cpp | 2 +- kernel/src/boot/Init.h | 2 +- kernel/src/main.cpp | 2 +- kernel/src/memory/Heap.cpp | 2 +- kernel/src/memory/Heap.h | 2 +- kernel/src/memory/KernelVM.cpp | 2 +- kernel/src/memory/KernelVM.h | 2 +- kernel/src/memory/MemoryManager.cpp | 2 +- kernel/src/memory/MemoryManager.h | 2 +- kernel/src/memory/MemoryMap.cpp | 2 +- kernel/src/memory/MemoryMap.h | 2 +- kernel/src/thread/Scheduler.cpp | 2 +- kernel/src/thread/Scheduler.h | 2 +- kernel/src/thread/Spinlock.cpp | 2 +- kernel/src/thread/Spinlock.h | 2 +- kernel/src/thread/Thread.cpp | 2 +- kernel/src/thread/Thread.h | 2 +- kernel/src/video/BuiltinFont.h | 2 +- kernel/src/video/Framebuffer.cpp | 2 +- kernel/src/video/Framebuffer.h | 2 +- kernel/src/video/TextConsole.cpp | 2 +- kernel/src/video/TextConsole.h | 2 +- luna/include/luna/Alignment.h | 2 +- luna/include/luna/Alloc.h | 2 +- luna/include/luna/Atomic.h | 2 +- luna/include/luna/Attributes.h | 2 +- luna/include/luna/Badge.h | 2 +- luna/include/luna/Bitmap.h | 2 +- luna/include/luna/CString.h | 2 +- luna/include/luna/CType.h | 2 +- luna/include/luna/DebugLog.h | 2 +- luna/include/luna/Format.h | 2 +- luna/include/luna/LinkedList.h | 2 +- luna/include/luna/Move.h | 2 +- luna/include/luna/NumberParsing.h | 2 +- luna/include/luna/Option.h | 2 +- luna/include/luna/OwnedPtr.h | 2 +- luna/include/luna/OwnedStringView.h | 2 +- luna/include/luna/PlacementNew.h | 2 +- luna/include/luna/Result.h | 2 +- luna/include/luna/SafeArithmetic.h | 2 +- luna/include/luna/ScopeGuard.h | 2 +- luna/include/luna/SharedPtr.h | 2 +- luna/include/luna/Stack.h | 2 +- luna/include/luna/SystemError.h | 2 +- luna/include/luna/TarStream.h | 2 +- luna/include/luna/TypeTraits.h | 2 +- luna/include/luna/Types.h | 2 +- luna/include/luna/Units.h | 2 +- luna/include/luna/Utf8.h | 2 +- luna/src/Alloc.cpp | 2 +- luna/src/Bitmap.cpp | 2 +- luna/src/CString.cpp | 2 +- luna/src/Check.cpp | 2 +- luna/src/DebugLog.cpp | 2 +- luna/src/Format.cpp | 2 +- luna/src/OwnedStringView.cpp | 2 +- luna/src/Stack.cpp | 2 +- luna/src/SystemError.cpp | 2 +- luna/src/TarStream.cpp | 2 +- luna/src/Units.cpp | 2 +- luna/src/Utf8.cpp | 2 +- 87 files changed, 87 insertions(+), 87 deletions(-) diff --git a/kernel/src/ELF.cpp b/kernel/src/ELF.cpp index fe4a1357..1e71682a 100644 --- a/kernel/src/ELF.cpp +++ b/kernel/src/ELF.cpp @@ -134,4 +134,4 @@ namespace ELFLoader return ELFData { segments, elf_header.e_entry }; } -} \ No newline at end of file +} diff --git a/kernel/src/ELF.h b/kernel/src/ELF.h index 1a3dce72..d81a9c6f 100644 --- a/kernel/src/ELF.h +++ b/kernel/src/ELF.h @@ -75,4 +75,4 @@ struct ELFData namespace ELFLoader { Result load(const TarStream::Entry& elf_entry, const TarStream& stream); -}; \ No newline at end of file +}; diff --git a/kernel/src/InitRD.cpp b/kernel/src/InitRD.cpp index c8d7d957..1fc592df 100644 --- a/kernel/src/InitRD.cpp +++ b/kernel/src/InitRD.cpp @@ -15,4 +15,4 @@ void InitRD::initialize() .expect_value("Unable to map the initial ramdisk into virtual memory"); g_initrd.initialize((void*)virtual_initrd_address, bootboot.initrd_size); -} \ No newline at end of file +} diff --git a/kernel/src/InitRD.h b/kernel/src/InitRD.h index 632a8e54..2eecf546 100644 --- a/kernel/src/InitRD.h +++ b/kernel/src/InitRD.h @@ -6,4 +6,4 @@ extern TarStream g_initrd; namespace InitRD { void initialize(); -} \ No newline at end of file +} diff --git a/kernel/src/Log.cpp b/kernel/src/Log.cpp index d8194fd1..deaad49d 100644 --- a/kernel/src/Log.cpp +++ b/kernel/src/Log.cpp @@ -127,4 +127,4 @@ static bool g_check_already_failed = false; CPU::print_stack_trace(); } CPU::efficient_halt(); -} \ No newline at end of file +} diff --git a/kernel/src/Log.h b/kernel/src/Log.h index 31dddd5c..97f2155d 100644 --- a/kernel/src/Log.h +++ b/kernel/src/Log.h @@ -22,4 +22,4 @@ bool log_text_console_enabled(); #define kdbgln(...) log(LogLevel::Debug, __VA_ARGS__) #define kinfoln(...) log(LogLevel::Info, __VA_ARGS__) #define kwarnln(...) log(LogLevel::Warn, __VA_ARGS__) -#define kerrorln(...) log(LogLevel::Error, __VA_ARGS__) \ No newline at end of file +#define kerrorln(...) log(LogLevel::Error, __VA_ARGS__) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index 1701057f..54422463 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -27,4 +27,4 @@ namespace CPU void print_stack_trace_at(Registers* regs); void pause(); -} \ No newline at end of file +} diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index cc0b6b42..c0620071 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -34,4 +34,4 @@ namespace MMU void setup_initial_page_directory(); PageDirectory* kernel_page_directory(); -} \ No newline at end of file +} diff --git a/kernel/src/arch/Serial.cpp b/kernel/src/arch/Serial.cpp index 8bedd13c..c21c88e8 100644 --- a/kernel/src/arch/Serial.cpp +++ b/kernel/src/arch/Serial.cpp @@ -30,4 +30,4 @@ namespace Serial va_end(ap); return rc; } -} \ No newline at end of file +} diff --git a/kernel/src/arch/Serial.h b/kernel/src/arch/Serial.h index f74597c7..c8af2565 100644 --- a/kernel/src/arch/Serial.h +++ b/kernel/src/arch/Serial.h @@ -11,4 +11,4 @@ namespace Serial void print(const char* str); void println(const char* str); usize printf(const char* str, ...) _format(1, 2); -} \ No newline at end of file +} diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 0bed7394..6314427b 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -137,4 +137,4 @@ bool should_invoke_scheduler() { // FIXME: Modulo is SLOW. We're calling this every tick. return (timer_ticks % ARCH_TIMER_FREQ) == 0; -} \ No newline at end of file +} diff --git a/kernel/src/arch/Timer.h b/kernel/src/arch/Timer.h index 2cd462d1..bcceb762 100644 --- a/kernel/src/arch/Timer.h +++ b/kernel/src/arch/Timer.h @@ -36,4 +36,4 @@ namespace Timer void init(); } -bool should_invoke_scheduler(); \ No newline at end of file +bool should_invoke_scheduler(); diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 44c5a932..bb0455d8 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -284,4 +284,4 @@ namespace CPU extern "C" void switch_task(Registers* regs) { Scheduler::switch_task(regs); -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/CPU.h b/kernel/src/arch/x86_64/CPU.h index c5747521..3d69c63d 100644 --- a/kernel/src/arch/x86_64/CPU.h +++ b/kernel/src/arch/x86_64/CPU.h @@ -22,4 +22,4 @@ struct [[gnu::packed]] TSS static_assert(sizeof(TSS) == 104UL); -extern TSS task_state_segment; \ No newline at end of file +extern TSS task_state_segment; diff --git a/kernel/src/arch/x86_64/IO.cpp b/kernel/src/arch/x86_64/IO.cpp index 8afa0a08..76f51cc3 100644 --- a/kernel/src/arch/x86_64/IO.cpp +++ b/kernel/src/arch/x86_64/IO.cpp @@ -37,4 +37,4 @@ namespace IO { asm volatile("outl %0, %1" : : "a"(value), "Nd"(port)); } -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/IO.h b/kernel/src/arch/x86_64/IO.h index 5f5a6fc2..d25513c5 100644 --- a/kernel/src/arch/x86_64/IO.h +++ b/kernel/src/arch/x86_64/IO.h @@ -10,4 +10,4 @@ namespace IO void outb(u16 port, u8 value); void outw(u16 port, u16 value); void outl(u16 port, u32 value); -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index a985df7b..a51dced4 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -274,4 +274,4 @@ namespace MMU { return g_kernel_directory; } -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/MMU.h b/kernel/src/arch/x86_64/MMU.h index 0ebc7978..198485f0 100644 --- a/kernel/src/arch/x86_64/MMU.h +++ b/kernel/src/arch/x86_64/MMU.h @@ -40,4 +40,4 @@ struct alignas(ARCH_PAGE_SIZE) PageDirectory }; static_assert(sizeof(PageTableEntry) == 8UL); -static_assert(sizeof(PageDirectory) == ARCH_PAGE_SIZE); \ No newline at end of file +static_assert(sizeof(PageDirectory) == ARCH_PAGE_SIZE); diff --git a/kernel/src/arch/x86_64/Serial.cpp b/kernel/src/arch/x86_64/Serial.cpp index 3dc26ec4..3d1dcc35 100644 --- a/kernel/src/arch/x86_64/Serial.cpp +++ b/kernel/src/arch/x86_64/Serial.cpp @@ -12,4 +12,4 @@ void Serial::putchar(u8 c) { serial_wait(); IO::outb(COM1, c); -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/Thread.cpp b/kernel/src/arch/x86_64/Thread.cpp index 042ef119..f02fbaaf 100644 --- a/kernel/src/arch/x86_64/Thread.cpp +++ b/kernel/src/arch/x86_64/Thread.cpp @@ -55,4 +55,4 @@ void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs) if (!old_thread->is_idle()) memcpy(&old_thread->regs, regs, sizeof(Registers)); memcpy(regs, &new_thread->regs, sizeof(Registers)); -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/Timer.cpp b/kernel/src/arch/x86_64/Timer.cpp index c35a4cf5..26e441cc 100644 --- a/kernel/src/arch/x86_64/Timer.cpp +++ b/kernel/src/arch/x86_64/Timer.cpp @@ -12,4 +12,4 @@ void Timer::arch_init() IO::outb(PIT_CHANNEL_0, (u8)(divisor & 0xFF)); IO::outb(0x80, 0); // short delay IO::outb(PIT_CHANNEL_0, (u8)((divisor & 0xFF00) >> 8)); -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/Timer.h b/kernel/src/arch/x86_64/Timer.h index 1a0e474b..6ab40002 100644 --- a/kernel/src/arch/x86_64/Timer.h +++ b/kernel/src/arch/x86_64/Timer.h @@ -1,4 +1,4 @@ #pragma once #include -const usize ARCH_TIMER_FREQ = 5; \ No newline at end of file +const usize ARCH_TIMER_FREQ = 5; diff --git a/kernel/src/arch/x86_64/init/GDT.cpp b/kernel/src/arch/x86_64/init/GDT.cpp index 77317c00..54480a0e 100644 --- a/kernel/src/arch/x86_64/init/GDT.cpp +++ b/kernel/src/arch/x86_64/init/GDT.cpp @@ -91,4 +91,4 @@ void setup_gdt() setup_tss(); load_gdt(&gdtr); load_tr(0x2b); -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/init/IDT.cpp b/kernel/src/arch/x86_64/init/IDT.cpp index 00ad454b..e507613e 100644 --- a/kernel/src/arch/x86_64/init/IDT.cpp +++ b/kernel/src/arch/x86_64/init/IDT.cpp @@ -115,4 +115,4 @@ void setup_idt() idtr.limit = 0x0FFF; idtr.offset = (u64)idt; asm volatile("lidt %0" : : "m"(idtr)); -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/init/PIC.cpp b/kernel/src/arch/x86_64/init/PIC.cpp index 632c94a0..e24a23a1 100644 --- a/kernel/src/arch/x86_64/init/PIC.cpp +++ b/kernel/src/arch/x86_64/init/PIC.cpp @@ -50,4 +50,4 @@ void pic_eoi(unsigned char irq) void pic_eoi(Registers* regs) { pic_eoi((unsigned char)(regs->error)); // On IRQs, the error code is the IRQ number -} \ No newline at end of file +} diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 69e40cb9..dad4e9ed 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -33,4 +33,4 @@ void Init::early_init() InitRD::initialize(); MemoryManager::protect_kernel_sections().expect_release_value("We should succeed to protect sections"); -} \ No newline at end of file +} diff --git a/kernel/src/boot/Init.h b/kernel/src/boot/Init.h index 5c5479c1..b7fb4422 100644 --- a/kernel/src/boot/Init.h +++ b/kernel/src/boot/Init.h @@ -4,4 +4,4 @@ namespace Init { void early_init(); void check_magic(); -} \ No newline at end of file +} diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 521b3178..d46b731b 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -90,4 +90,4 @@ extern "C" [[noreturn]] void _start() auto rc = init(); if (rc.has_error()) kerrorln("Runtime error: %s", rc.error_string()); CPU::idle_loop(); -} \ No newline at end of file +} diff --git a/kernel/src/memory/Heap.cpp b/kernel/src/memory/Heap.cpp index a8ae9c08..52df9b96 100644 --- a/kernel/src/memory/Heap.cpp +++ b/kernel/src/memory/Heap.cpp @@ -419,4 +419,4 @@ void operator delete(void* p, usize) noexcept void operator delete[](void* p, usize) noexcept { kfree(p); -} \ No newline at end of file +} diff --git a/kernel/src/memory/Heap.h b/kernel/src/memory/Heap.h index 7d13d69a..d1b7ada9 100644 --- a/kernel/src/memory/Heap.h +++ b/kernel/src/memory/Heap.h @@ -7,4 +7,4 @@ Result kcalloc(usize nmemb, usize size); Result krealloc(void* ptr, usize size); Result kfree(void* ptr); -void dump_heap_usage(); \ No newline at end of file +void dump_heap_usage(); diff --git a/kernel/src/memory/KernelVM.cpp b/kernel/src/memory/KernelVM.cpp index 74bbfa37..0c403f8d 100644 --- a/kernel/src/memory/KernelVM.cpp +++ b/kernel/src/memory/KernelVM.cpp @@ -120,4 +120,4 @@ namespace KernelVM { return KERNEL_VM_RANGE_SIZE - g_used_vm; } -} \ No newline at end of file +} diff --git a/kernel/src/memory/KernelVM.h b/kernel/src/memory/KernelVM.h index 9a7f358b..60d5e28c 100644 --- a/kernel/src/memory/KernelVM.h +++ b/kernel/src/memory/KernelVM.h @@ -15,4 +15,4 @@ namespace KernelVM usize free(); usize used(); -} \ No newline at end of file +} diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index b410cc0d..93447a5d 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -357,4 +357,4 @@ namespace MemoryManager { return free_mem + used_mem + reserved_mem; } -} \ No newline at end of file +} diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index a5570157..13a02a8a 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -35,4 +35,4 @@ namespace MemoryManager usize used(); usize reserved(); usize total(); -} \ No newline at end of file +} diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index fa2d13e2..9d9cdca1 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -84,4 +84,4 @@ MemoryMapEntry MemoryMapIterator::highest() } return at(highest_index).value(); -} \ No newline at end of file +} diff --git a/kernel/src/memory/MemoryMap.h b/kernel/src/memory/MemoryMap.h index 669b07aa..d6f3687d 100644 --- a/kernel/src/memory/MemoryMap.h +++ b/kernel/src/memory/MemoryMap.h @@ -61,4 +61,4 @@ class MemoryMapIterator const usize m_mmap_entries; const MMapEnt* m_base_ent; usize m_cur_ent; -}; \ No newline at end of file +}; diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index f84c98c5..8b498cd0 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -206,4 +206,4 @@ void kernel_sleep(u64 ms) g_current->state = ThreadState::Dying; kernel_yield(); unreachable(); -} \ No newline at end of file +} diff --git a/kernel/src/thread/Scheduler.h b/kernel/src/thread/Scheduler.h index 10a47534..f818c731 100644 --- a/kernel/src/thread/Scheduler.h +++ b/kernel/src/thread/Scheduler.h @@ -25,4 +25,4 @@ namespace Scheduler extern "C" void kernel_yield(); void kernel_sleep(u64 ms); -[[noreturn]] void kernel_exit(); \ No newline at end of file +[[noreturn]] void kernel_exit(); diff --git a/kernel/src/thread/Spinlock.cpp b/kernel/src/thread/Spinlock.cpp index 45cde161..f1802b80 100644 --- a/kernel/src/thread/Spinlock.cpp +++ b/kernel/src/thread/Spinlock.cpp @@ -25,4 +25,4 @@ void Spinlock::unlock() { kwarnln("Spinlock::unlock() called on an unlocked lock with value %d", expected); } -} \ No newline at end of file +} diff --git a/kernel/src/thread/Spinlock.h b/kernel/src/thread/Spinlock.h index 453327d7..d54edd96 100644 --- a/kernel/src/thread/Spinlock.h +++ b/kernel/src/thread/Spinlock.h @@ -88,4 +88,4 @@ template class LockedValue private: T m_value; Spinlock m_lock; -}; \ No newline at end of file +}; diff --git a/kernel/src/thread/Thread.cpp b/kernel/src/thread/Thread.cpp index 22cdebac..fea866e3 100644 --- a/kernel/src/thread/Thread.cpp +++ b/kernel/src/thread/Thread.cpp @@ -18,4 +18,4 @@ Result new_thread() thread->id = g_next_id++; return thread; -} \ No newline at end of file +} diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 6e8cc628..43a94e5d 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -60,4 +60,4 @@ bool is_in_kernel(Registers* regs); Result new_thread(); -extern LinkedList g_threads; \ No newline at end of file +extern LinkedList g_threads; diff --git a/kernel/src/video/BuiltinFont.h b/kernel/src/video/BuiltinFont.h index ee55a00a..ffe907a4 100644 --- a/kernel/src/video/BuiltinFont.h +++ b/kernel/src/video/BuiltinFont.h @@ -516,4 +516,4 @@ u8 font[] = { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 255 */ 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, - 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00 /* Special box character, 256 */ }; \ No newline at end of file + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00 /* Special box character, 256 */ }; diff --git a/kernel/src/video/Framebuffer.cpp b/kernel/src/video/Framebuffer.cpp index 8b28dbba..2d379b59 100644 --- a/kernel/src/video/Framebuffer.cpp +++ b/kernel/src/video/Framebuffer.cpp @@ -80,4 +80,4 @@ namespace Framebuffer { return g_fb_scanline; } -} \ No newline at end of file +} diff --git a/kernel/src/video/Framebuffer.h b/kernel/src/video/Framebuffer.h index 033ac127..fb851cc7 100644 --- a/kernel/src/video/Framebuffer.h +++ b/kernel/src/video/Framebuffer.h @@ -15,4 +15,4 @@ namespace Framebuffer u32 width(); u32 height(); u32 scanline(); -} \ No newline at end of file +} diff --git a/kernel/src/video/TextConsole.cpp b/kernel/src/video/TextConsole.cpp index 8ccea5cf..86c7e4ec 100644 --- a/kernel/src/video/TextConsole.cpp +++ b/kernel/src/video/TextConsole.cpp @@ -199,4 +199,4 @@ namespace TextConsole va_end(ap); return rc; } -} \ No newline at end of file +} diff --git a/kernel/src/video/TextConsole.h b/kernel/src/video/TextConsole.h index 6614108e..c700b138 100644 --- a/kernel/src/video/TextConsole.h +++ b/kernel/src/video/TextConsole.h @@ -18,4 +18,4 @@ namespace TextConsole Result println(const char* str); void wprintln(const wchar_t* str); Result printf(const char* format, ...) _format(1, 2); -} \ No newline at end of file +} diff --git a/luna/include/luna/Alignment.h b/luna/include/luna/Alignment.h index f6f127dc..af572950 100644 --- a/luna/include/luna/Alignment.h +++ b/luna/include/luna/Alignment.h @@ -50,4 +50,4 @@ static_assert(get_blocks_from_size(0, 256) == 0); template constexpr T* offset_ptr(T* ptr, Offset offset) { return (T*)((char*)ptr + offset); -} \ No newline at end of file +} diff --git a/luna/include/luna/Alloc.h b/luna/include/luna/Alloc.h index 921dbe3d..96ef2b94 100644 --- a/luna/include/luna/Alloc.h +++ b/luna/include/luna/Alloc.h @@ -44,4 +44,4 @@ template void destroy(T* item) template void destroy_array(T* item) { delete[] item; -} \ No newline at end of file +} diff --git a/luna/include/luna/Atomic.h b/luna/include/luna/Atomic.h index 8f2dd9ff..f2c9cd79 100644 --- a/luna/include/luna/Atomic.h +++ b/luna/include/luna/Atomic.h @@ -115,4 +115,4 @@ template class Atomic private: T m_value; -}; \ No newline at end of file +}; diff --git a/luna/include/luna/Attributes.h b/luna/include/luna/Attributes.h index 2f8edf7e..28d84975 100644 --- a/luna/include/luna/Attributes.h +++ b/luna/include/luna/Attributes.h @@ -2,4 +2,4 @@ #define _weak __attribute__((weak)) #define _format(n, m) __attribute__((format(printf, n, m))) -#define _align(x) __attribute__((aligned(x))) \ No newline at end of file +#define _align(x) __attribute__((aligned(x))) diff --git a/luna/include/luna/Badge.h b/luna/include/luna/Badge.h index c319b035..50cb5cbc 100644 --- a/luna/include/luna/Badge.h +++ b/luna/include/luna/Badge.h @@ -9,4 +9,4 @@ template struct Badge Badge(Badge&&) = delete; friend T; -}; \ No newline at end of file +}; diff --git a/luna/include/luna/Bitmap.h b/luna/include/luna/Bitmap.h index b8ab0c40..5b062fd7 100644 --- a/luna/include/luna/Bitmap.h +++ b/luna/include/luna/Bitmap.h @@ -45,4 +45,4 @@ class Bitmap u8* m_location = nullptr; usize m_size_in_bytes = 0; -}; \ No newline at end of file +}; diff --git a/luna/include/luna/CString.h b/luna/include/luna/CString.h index 8b606af7..df46497c 100644 --- a/luna/include/luna/CString.h +++ b/luna/include/luna/CString.h @@ -16,4 +16,4 @@ extern "C" // Copies len bytes from src into dest and adds a null terminator. void nullcpy(char* dest, const char* src, usize len); -} \ No newline at end of file +} diff --git a/luna/include/luna/CType.h b/luna/include/luna/CType.h index 79daf531..91994286 100644 --- a/luna/include/luna/CType.h +++ b/luna/include/luna/CType.h @@ -93,4 +93,4 @@ inline constexpr int _toupper(int c) #define isblank _isblank #define tolower _tolower #define toupper _toupper -#endif \ No newline at end of file +#endif diff --git a/luna/include/luna/DebugLog.h b/luna/include/luna/DebugLog.h index 5a32a7a4..0f78aa53 100644 --- a/luna/include/luna/DebugLog.h +++ b/luna/include/luna/DebugLog.h @@ -4,4 +4,4 @@ extern void debug_log_impl(const char* format, va_list ap); -void dbgln(const char* format, ...) _format(1, 2); \ No newline at end of file +void dbgln(const char* format, ...) _format(1, 2); diff --git a/luna/include/luna/Format.h b/luna/include/luna/Format.h index 6607e4d5..7fe3bcdc 100644 --- a/luna/include/luna/Format.h +++ b/luna/include/luna/Format.h @@ -16,4 +16,4 @@ usize pure_cstyle_format(const char* format, pure_callback_t callback, void* arg usize vstring_format(char* buf, usize max, const char* format, va_list ap); // Convenience function which outputs into a fixed-size buffer (not unlike snprintf) -usize string_format(char* buf, usize max, const char* format, ...) _format(3, 4); \ No newline at end of file +usize string_format(char* buf, usize max, const char* format, ...) _format(3, 4); diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h index 442e0ecc..f1e6df08 100644 --- a/luna/include/luna/LinkedList.h +++ b/luna/include/luna/LinkedList.h @@ -220,4 +220,4 @@ template class LinkedList } usize m_count = 0; -}; \ No newline at end of file +}; diff --git a/luna/include/luna/Move.h b/luna/include/luna/Move.h index 9006d68a..6a88f7b0 100644 --- a/luna/include/luna/Move.h +++ b/luna/include/luna/Move.h @@ -3,4 +3,4 @@ template inline T&& move(T& lvalue) { return (T &&) lvalue; -} \ No newline at end of file +} diff --git a/luna/include/luna/NumberParsing.h b/luna/include/luna/NumberParsing.h index e7c94bf5..ca00841c 100644 --- a/luna/include/luna/NumberParsing.h +++ b/luna/include/luna/NumberParsing.h @@ -11,4 +11,4 @@ isize scan_signed_integer(const char** str); usize parse_unsigned_integer(const char* str, const char** endptr, int base); // Parse a signed integer, similar to strtoll(). -isize parse_signed_integer(const char* str, const char** endptr, int base); \ No newline at end of file +isize parse_signed_integer(const char* str, const char** endptr, int base); diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index 6bbe8b5c..d8ca65f2 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -174,4 +174,4 @@ template inline Option nonnull_or_empty_option(T* ptr) if (ptr == nullptr) return {}; else return ptr; -} \ No newline at end of file +} diff --git a/luna/include/luna/OwnedPtr.h b/luna/include/luna/OwnedPtr.h index 0f76630d..01911ea8 100644 --- a/luna/include/luna/OwnedPtr.h +++ b/luna/include/luna/OwnedPtr.h @@ -62,4 +62,4 @@ template Result> adopt_owned_if_nonnull(T* ptr) if (ptr) return OwnedPtr { ptr }; else return err(ENOMEM); -} \ No newline at end of file +} diff --git a/luna/include/luna/OwnedStringView.h b/luna/include/luna/OwnedStringView.h index e9343e55..876e9c60 100644 --- a/luna/include/luna/OwnedStringView.h +++ b/luna/include/luna/OwnedStringView.h @@ -29,4 +29,4 @@ class OwnedStringView private: char* m_string { nullptr }; usize m_length { 0 }; -}; \ No newline at end of file +}; diff --git a/luna/include/luna/PlacementNew.h b/luna/include/luna/PlacementNew.h index 91a20f39..554bde97 100644 --- a/luna/include/luna/PlacementNew.h +++ b/luna/include/luna/PlacementNew.h @@ -10,4 +10,4 @@ inline void* operator new[](usize, void* p) noexcept return p; } inline void operator delete(void*, void*) noexcept {}; -inline void operator delete[](void*, void*) noexcept {}; \ No newline at end of file +inline void operator delete[](void*, void*) noexcept {}; diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index f156b73c..1bfb1cf4 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -251,4 +251,4 @@ template inline Result nonnull_or_error(T* ptr, int error) if (ptr == nullptr) return err(error); else return ptr; -} \ No newline at end of file +} diff --git a/luna/include/luna/SafeArithmetic.h b/luna/include/luna/SafeArithmetic.h index 90cc3897..95f48ce4 100644 --- a/luna/include/luna/SafeArithmetic.h +++ b/luna/include/luna/SafeArithmetic.h @@ -53,4 +53,4 @@ template bool mul_will_overflow(T a, T b) #else return safe_mul(a, b).has_error(); #endif -} \ No newline at end of file +} diff --git a/luna/include/luna/ScopeGuard.h b/luna/include/luna/ScopeGuard.h index cc758f26..faded0ba 100644 --- a/luna/include/luna/ScopeGuard.h +++ b/luna/include/luna/ScopeGuard.h @@ -25,4 +25,4 @@ template class ScopeGuard template [[nodiscard]] ScopeGuard make_scope_guard(const Callback& callback) { return { callback }; -} \ No newline at end of file +} diff --git a/luna/include/luna/SharedPtr.h b/luna/include/luna/SharedPtr.h index 6a9caffd..304b906e 100644 --- a/luna/include/luna/SharedPtr.h +++ b/luna/include/luna/SharedPtr.h @@ -133,4 +133,4 @@ template Result> adopt_shared_from_owned(OwnedPtr&& guard.deactivate(); return shared_ptr; -} \ No newline at end of file +} diff --git a/luna/include/luna/Stack.h b/luna/include/luna/Stack.h index d1a73f0d..fbd3f64c 100644 --- a/luna/include/luna/Stack.h +++ b/luna/include/luna/Stack.h @@ -21,4 +21,4 @@ struct Stack private: u64 m_base; usize m_bytes; -}; \ No newline at end of file +}; diff --git a/luna/include/luna/SystemError.h b/luna/include/luna/SystemError.h index a6aba0c3..45f4f921 100644 --- a/luna/include/luna/SystemError.h +++ b/luna/include/luna/SystemError.h @@ -60,4 +60,4 @@ const char* error_string(int error); -#endif \ No newline at end of file +#endif diff --git a/luna/include/luna/TarStream.h b/luna/include/luna/TarStream.h index 9c926331..e21a0aa3 100644 --- a/luna/include/luna/TarStream.h +++ b/luna/include/luna/TarStream.h @@ -67,4 +67,4 @@ class TarStream void* m_pos; usize m_size; usize m_offset = 0; -}; \ No newline at end of file +}; diff --git a/luna/include/luna/TypeTraits.h b/luna/include/luna/TypeTraits.h index e34e941d..4894ac1a 100644 --- a/luna/include/luna/TypeTraits.h +++ b/luna/include/luna/TypeTraits.h @@ -46,4 +46,4 @@ template struct __remove_ref_impl template using RemoveReference = __remove_ref_impl::type; -template using RemoveCVReference = RemoveCV>; \ No newline at end of file +template using RemoveCVReference = RemoveCV>; diff --git a/luna/include/luna/Types.h b/luna/include/luna/Types.h index f75bb652..e1924440 100644 --- a/luna/include/luna/Types.h +++ b/luna/include/luna/Types.h @@ -22,4 +22,4 @@ static_assert(sizeof(i32) == 4UL); static_assert(sizeof(i64) == 8UL); static_assert(sizeof(usize) == sizeof(void*)); -static_assert(sizeof(isize) == sizeof(void*)); \ No newline at end of file +static_assert(sizeof(isize) == sizeof(void*)); diff --git a/luna/include/luna/Units.h b/luna/include/luna/Units.h index 6b062f1a..edc22635 100644 --- a/luna/include/luna/Units.h +++ b/luna/include/luna/Units.h @@ -3,4 +3,4 @@ #include usize to_dynamic_unit_cstr(usize value, char* buffer, usize max); -Result to_dynamic_unit(usize value); \ No newline at end of file +Result to_dynamic_unit(usize value); diff --git a/luna/include/luna/Utf8.h b/luna/include/luna/Utf8.h index 25509b73..280d29ed 100644 --- a/luna/include/luna/Utf8.h +++ b/luna/include/luna/Utf8.h @@ -62,4 +62,4 @@ class Utf8Encoder public: // Does not null-terminate. Returns the number of bytes written. Result encode(wchar_t c, char buf[4]); -}; \ No newline at end of file +}; diff --git a/luna/src/Alloc.cpp b/luna/src/Alloc.cpp index d97a3434..23f80e6c 100644 --- a/luna/src/Alloc.cpp +++ b/luna/src/Alloc.cpp @@ -27,4 +27,4 @@ void raw_free(void* ptr) void operator delete(void* ptr, usize size, std::align_val_t) noexcept { operator delete(ptr, size); -} \ No newline at end of file +} diff --git a/luna/src/Bitmap.cpp b/luna/src/Bitmap.cpp index 35b2ea8d..5a3e5130 100644 --- a/luna/src/Bitmap.cpp +++ b/luna/src/Bitmap.cpp @@ -85,4 +85,4 @@ void Bitmap::clear_region(usize start, usize bits, bool value) set(start, value); start++; } -} \ No newline at end of file +} diff --git a/luna/src/CString.cpp b/luna/src/CString.cpp index 83d15661..ac048c3c 100644 --- a/luna/src/CString.cpp +++ b/luna/src/CString.cpp @@ -81,4 +81,4 @@ extern "C" memcpy(dest, src, len); dest[len] = 0; } -} \ No newline at end of file +} diff --git a/luna/src/Check.cpp b/luna/src/Check.cpp index f01fef8d..b57856e7 100644 --- a/luna/src/Check.cpp +++ b/luna/src/Check.cpp @@ -3,4 +3,4 @@ _weak [[noreturn]] bool __check_failed(const char*, const char*, const char*, const char*) { __builtin_trap(); -} \ No newline at end of file +} diff --git a/luna/src/DebugLog.cpp b/luna/src/DebugLog.cpp index b2639723..c926390c 100644 --- a/luna/src/DebugLog.cpp +++ b/luna/src/DebugLog.cpp @@ -6,4 +6,4 @@ void dbgln(const char* format, ...) va_start(ap, format); debug_log_impl(format, ap); va_end(ap); -} \ No newline at end of file +} diff --git a/luna/src/Format.cpp b/luna/src/Format.cpp index cd68ba8c..c06a51a9 100644 --- a/luna/src/Format.cpp +++ b/luna/src/Format.cpp @@ -693,4 +693,4 @@ usize string_format(char* buf, usize max, const char* format, ...) va_end(ap); return result; -} \ No newline at end of file +} diff --git a/luna/src/OwnedStringView.cpp b/luna/src/OwnedStringView.cpp index ba786cfe..90e0f549 100644 --- a/luna/src/OwnedStringView.cpp +++ b/luna/src/OwnedStringView.cpp @@ -46,4 +46,4 @@ Result OwnedStringView::from_string_literal(const char* str) char* dup = strdup(str); if (!dup) return err(ENOMEM); return OwnedStringView { dup }; -} \ No newline at end of file +} diff --git a/luna/src/Stack.cpp b/luna/src/Stack.cpp index 0c53e6f3..f323470b 100644 --- a/luna/src/Stack.cpp +++ b/luna/src/Stack.cpp @@ -7,4 +7,4 @@ Stack::Stack(u64 base, usize bytes) : m_base(base), m_bytes(bytes) u64 Stack::top() { return (m_base + m_bytes) - sizeof(void*); -} \ No newline at end of file +} diff --git a/luna/src/SystemError.cpp b/luna/src/SystemError.cpp index 79279044..74586781 100644 --- a/luna/src/SystemError.cpp +++ b/luna/src/SystemError.cpp @@ -59,4 +59,4 @@ const char* error_string(int error) case EFIXME: return "Functionality not yet implemented"; default: return "Unknown error"; } -} \ No newline at end of file +} diff --git a/luna/src/TarStream.cpp b/luna/src/TarStream.cpp index 0235881c..c4e4cced 100644 --- a/luna/src/TarStream.cpp +++ b/luna/src/TarStream.cpp @@ -106,4 +106,4 @@ Result TarStream::read_contents_as_string(const Entry& entry, u buf[nread] = 0; return OwnedStringView { buf }; -} \ No newline at end of file +} diff --git a/luna/src/Units.cpp b/luna/src/Units.cpp index 9c4a31f5..1476e637 100644 --- a/luna/src/Units.cpp +++ b/luna/src/Units.cpp @@ -25,4 +25,4 @@ Result to_dynamic_unit(usize value) to_dynamic_unit_cstr(value, buf, 64); return OwnedStringView { buf }; -} \ No newline at end of file +} diff --git a/luna/src/Utf8.cpp b/luna/src/Utf8.cpp index 96336ed3..3a84df36 100644 --- a/luna/src/Utf8.cpp +++ b/luna/src/Utf8.cpp @@ -241,4 +241,4 @@ Result Utf8Encoder::encode(wchar_t c, char buf[4]) TRY(encode_wide_char_as_utf8(c, buf, len)); return len; -} \ No newline at end of file +} From f0e14cf7e9380b222b220b2de3478b197481a888 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 2 Jan 2023 13:08:42 +0100 Subject: [PATCH 359/407] Update year range in LICENSE :) --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 954a62b0..ef0b5c4d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 2-Clause License -Copyright (c) 2022, apio. +Copyright (c) 2022-2023, apio. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -22,4 +22,4 @@ 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. \ No newline at end of file +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From d3c414af4e12d3ab93836e11bd9d602cbbcde02f Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 21:46:03 +0100 Subject: [PATCH 360/407] ELFLoader: Do not keep track of segments This reduces calls to kmalloc() since segment data is heap-allocated, and the segments loaded will be deleted when deleting the page directory. --- kernel/src/ELF.cpp | 21 +-------------------- kernel/src/ELF.h | 20 -------------------- 2 files changed, 1 insertion(+), 40 deletions(-) diff --git a/kernel/src/ELF.cpp b/kernel/src/ELF.cpp index 1e71682a..c9fe522f 100644 --- a/kernel/src/ELF.cpp +++ b/kernel/src/ELF.cpp @@ -23,19 +23,11 @@ static bool can_write_segment(u32 flags) return can_write_segment(flags) && can_execute_segment(flags); }*/ -ELFSegment::ELFSegment(u64 base, usize size) : m_base(base), m_size(size) -{ -} - namespace ELFLoader { // FIXME: Check that all calls to read_contents() read the proper amount of bytes. Result load(const TarStream::Entry& elf_entry, const TarStream& stream) { - LinkedList segments; - - auto guard = make_scope_guard([&] { segments.consume([](ELFSegment* segment) { delete segment; }); }); - Elf64_Ehdr elf_header; usize nread = stream.read_contents(elf_entry, &elf_header, 0, sizeof elf_header); if (nread < sizeof elf_header) @@ -101,9 +93,6 @@ namespace ELFLoader /*expect(!can_write_and_execute_segment(program_header.p_flags), "Segment is both writable and executable");*/ - ELFSegment* segment = TRY(make(program_header.p_vaddr, program_header.p_memsz)); - segments.append(segment); - int flags = MMU::User | MMU::NoExecute; if (can_write_segment(program_header.p_flags)) flags |= MMU::ReadWrite; else if (can_execute_segment(program_header.p_flags)) @@ -124,14 +113,6 @@ namespace ELFLoader else { kdbgln("ELF: Encountered non-loadable program header, skipping"); } } - if (segments.count() == 0) - { - kdbgln("Error while loading ELF: No loadable segments"); - return err(ENOEXEC); - } - - guard.deactivate(); - - return ELFData { segments, elf_header.e_entry }; + return ELFData { elf_header.e_entry }; } } diff --git a/kernel/src/ELF.h b/kernel/src/ELF.h index d81a9c6f..440bae4b 100644 --- a/kernel/src/ELF.h +++ b/kernel/src/ELF.h @@ -47,28 +47,8 @@ typedef struct u64 p_align; /* Segment alignment */ } Elf64_Phdr; -struct ELFSegment : public LinkedListNode -{ - u64 base() const - { - return m_base; - } - - usize size() const - { - return m_size; - } - - ELFSegment(u64 base, usize size); - - private: - u64 m_base; - usize m_size; -}; - struct ELFData { - LinkedList segments; u64 entry; }; From c53bba03921d0377280c80557b984c12b8a72f64 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 21:50:06 +0100 Subject: [PATCH 361/407] MemoryManager: Add an unmap_weak_and_free_vm() helper function This function mirrors unmap_owned_and_free_vm(), but using weak unmapping (does not free the underlying physical memory) --- kernel/src/memory/MemoryManager.cpp | 9 +++++++++ kernel/src/memory/MemoryManager.h | 1 + 2 files changed, 10 insertions(+) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 93447a5d..75014bae 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -309,6 +309,15 @@ namespace MemoryManager return {}; } + Result unmap_weak_and_free_vm(u64 virt, usize count) + { + CHECK_PAGE_ALIGNED(virt); + + KernelVM::free_several_pages(virt, count); + + return unmap_weak(virt, count); + } + Result remap_unaligned(u64 address, usize count, int flags) { if (!is_aligned(address)) count++; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 13a02a8a..d22ed45c 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -30,6 +30,7 @@ namespace MemoryManager Result unmap_owned(u64 virt, usize count); Result unmap_owned_and_free_vm(u64 virt, usize count); Result unmap_weak(u64 virt, usize count); + Result unmap_weak_and_free_vm(u64 virt, usize count); usize free(); usize used(); From 31ea030c7fd6d17d6bf87b9c58a582620c6b0888 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 21:50:26 +0100 Subject: [PATCH 362/407] MMU: Add functions to create and delete userspace page directories --- kernel/src/arch/MMU.h | 1 + kernel/src/arch/x86_64/MMU.cpp | 118 +++++++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 6 deletions(-) diff --git a/kernel/src/arch/MMU.h b/kernel/src/arch/MMU.h index c0620071..031c038e 100644 --- a/kernel/src/arch/MMU.h +++ b/kernel/src/arch/MMU.h @@ -31,6 +31,7 @@ namespace MMU void flush_all(); Result create_page_directory_for_userspace(); + Result delete_userspace_page_directory(PageDirectory* directory); void setup_initial_page_directory(); PageDirectory* kernel_page_directory(); diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index a51dced4..f6081f2a 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -2,6 +2,7 @@ #include "memory/MemoryManager.h" #include #include +#include #include #pragma GCC push_options @@ -50,11 +51,16 @@ namespace MMU return l4_table()->entries[l4_index(addr)]; } + constexpr PageDirectory* raw_l3_table(u64 l4) + { + const u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12); + return (PageDirectory*)l3; + } + constexpr PageDirectory* l3_table(u64 addr) { const u64 l4 = l4_index(addr); - const u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12); - return (PageDirectory*)l3; + return raw_l3_table(l4); } constexpr u64 l3_index(u64 addr) @@ -67,12 +73,17 @@ namespace MMU return l3_table(addr)->entries[l3_index(addr)]; } + constexpr PageDirectory* raw_l2_table(u64 l4, u64 l3) + { + const u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12); + return (PageDirectory*)l2; + } + constexpr PageDirectory* l2_table(u64 addr) { const u64 l4 = l4_index(addr); const u64 l3 = l3_index(addr); - const u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12); - return (PageDirectory*)l2; + return raw_l2_table(l4, l3); } constexpr u64 l2_index(u64 addr) @@ -85,13 +96,18 @@ namespace MMU return l2_table(addr)->entries[l2_index(addr)]; } + constexpr PageDirectory* raw_l1_table(u64 l4, u64 l3, u64 l2) + { + const u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12); + return (PageDirectory*)l1; + } + constexpr PageDirectory* l1_table(u64 addr) { const u64 l4 = l4_index(addr); const u64 l3 = l3_index(addr); const u64 l2 = l2_index(addr); - const u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12); - return (PageDirectory*)l1; + return raw_l1_table(l4, l3, l2); } constexpr u64 l1_index(u64 addr) @@ -270,6 +286,96 @@ namespace MMU flush_all(); } + Result create_page_directory_for_userspace() + { + u64 directory_virt = TRY(MemoryManager::alloc_for_kernel(1, MMU::ReadWrite | MMU::NoExecute)); + u64 directory_phys = MMU::get_physical(directory_virt).value(); + + PageDirectory* directory = (PageDirectory*)directory_virt; + memset(directory, 0, ARCH_PAGE_SIZE); + PageTableEntry& recursive_entry = directory->entries[rindex]; + recursive_entry.read_write = true; + recursive_entry.present = true; + recursive_entry.set_address(directory_phys); + + directory->entries[511] = g_kernel_directory->entries[511]; + + // From now on, we're only going to use the physical address, since accessing the PageDirectory will be dealt + // with using recursive mapping. So let's make sure we don't leak any VM. + MemoryManager::unmap_weak_and_free_vm(directory_virt, 1); + + return (PageDirectory*)directory_phys; + } + + Result delete_userspace_page_directory(PageDirectory* directory) + { + check(directory); + + // Needed in order to access page tables using the recursive mapping system. + switch_page_directory(directory); + + auto guard = make_scope_guard([&] { + check(g_kernel_directory); + switch_page_directory(g_kernel_directory); + MemoryManager::free_frame((u64)directory); + }); + + PageDirectory* table = l4_table(); + + // Let's iterate over every top-level entry, skipping the last two entries (recursive mapping and kernel pages) + for (u64 i = 0; i < 510; i++) + { + PageTableEntry& l4 = table->entries[i]; + if (!l4.present) continue; + + PageDirectory* pdp = raw_l3_table(i); + + for (u64 j = 0; j < 512; j++) + { + PageTableEntry& l3 = pdp->entries[j]; + if (!l3.present) continue; + if (l3.larger_pages) + { + // FIXME: Maybe we shouldn't delete some pages in an address space, such as shared memory. + TRY(MemoryManager::free_frame(l3.get_address())); + } + + PageDirectory* pd = raw_l2_table(i, j); + + for (u64 k = 0; k < 512; k++) + { + PageTableEntry& l2 = pd->entries[k]; + if (!l2.present) continue; + if (l2.larger_pages) + { + // FIXME: Maybe we shouldn't delete some pages in an address space, such as shared memory. + TRY(MemoryManager::free_frame(l2.get_address())); + } + + PageDirectory* pt = raw_l1_table(i, j, k); + + for (u64 l = 0; l < 512; l++) + { + PageTableEntry& l1 = pt->entries[l]; + if (!l1.present) continue; + + // FIXME: Maybe we shouldn't delete some pages in an address space, such as shared memory. + TRY(MemoryManager::free_frame(l1.get_address())); + } + + TRY(MemoryManager::free_frame(l2.get_address())); + } + + TRY(MemoryManager::free_frame(l3.get_address())); + } + + TRY(MemoryManager::free_frame(l4.get_address())); + } + + // No need to clean up manually, the ScopeGuard we set up earlier will do that for us. + return {}; + } + PageDirectory* kernel_page_directory() { return g_kernel_directory; From ea89b9267520ee693a8a35b48ce114ee441d8bf6 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 21:50:53 +0100 Subject: [PATCH 363/407] Store a bit more stuff in a thread :) --- kernel/src/thread/Thread.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 43a94e5d..3b37923a 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -1,5 +1,6 @@ #pragma once +#include "arch/MMU.h" #include #include #include @@ -32,9 +33,14 @@ struct Thread : public LinkedListNode u64 sleep_ticks_left; Stack stack; + Stack kernel_stack; ThreadState state = ThreadState::Runnable; + bool is_kernel { true }; + + PageDirectory* directory; + bool is_idle() { return state == ThreadState::Idle; From a33a72915e9fe0e198618a40efae5b32380072ea Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 21:52:26 +0100 Subject: [PATCH 364/407] Scheduler: Creation, destruction and switching of userspace tasks :)) From a TarStream. Not optimal, but OK for the moment. --- kernel/src/thread/Scheduler.cpp | 93 +++++++++++++++++++++++++++++++-- kernel/src/thread/Scheduler.h | 3 ++ 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 8b498cd0..11b8366a 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -1,4 +1,5 @@ #include "thread/Scheduler.h" +#include "ELF.h" #include "Log.h" #include "arch/CPU.h" #include "arch/MMU.h" @@ -19,6 +20,7 @@ namespace Scheduler g_idle.init_regs_kernel(); g_idle.set_ip((u64)CPU::idle_loop); g_idle.state = ThreadState::Idle; + g_idle.is_kernel = true; g_idle.ticks_left = 1; @@ -60,6 +62,8 @@ namespace Scheduler thread->stack = thread_stack; + thread->is_kernel = true; + g_threads.append(thread); kinfoln("CREATED THREAD: id %lu with ip %lx and sp %lx", thread->id, thread->ip(), thread->sp()); @@ -95,13 +99,84 @@ namespace Scheduler return new_kernel_thread_impl(thread); } + static Result create_stacks(Stack& user_stack, Stack& kernel_stack) + { + const u64 THREAD_STACK_BASE = 0x10000; + + TRY(MemoryManager::alloc_at(THREAD_STACK_BASE, 4, MMU::ReadWrite | MMU::NoExecute | MMU::User)); + + auto guard = make_scope_guard([&] { MemoryManager::unmap_owned(THREAD_STACK_BASE, 4); }); + + u64 kernel_stack_base = TRY(MemoryManager::alloc_for_kernel(4, MMU::ReadWrite | MMU::NoExecute)); + + guard.deactivate(); + + user_stack = { THREAD_STACK_BASE, 4 * ARCH_PAGE_SIZE }; + kernel_stack = { kernel_stack_base, 4 * ARCH_PAGE_SIZE }; + + return {}; + } + + Result new_userspace_thread(const TarStream::Entry& entry, const TarStream& stream) + { + Thread* thread = TRY(new_thread()); + + thread->is_kernel = false; + + auto guard = make_scope_guard([&] { delete thread; }); + + auto directory = TRY(MMU::create_page_directory_for_userspace()); + + auto directory_guard = make_scope_guard([&] { + MMU::switch_page_directory(MMU::kernel_page_directory()); + MemoryManager::free_frame((u64)directory); + }); + + MMU::switch_page_directory(directory); + + thread->init_regs_user(); + + auto data = TRY(ELFLoader::load(entry, stream)); + + thread->set_ip(data.entry); + + TRY(create_stacks(thread->stack, thread->kernel_stack)); + thread->set_sp(thread->stack.top()); + + thread->directory = directory; + + guard.deactivate(); + directory_guard.deactivate(); + + kinfoln("CREATED USERSPACE THREAD: id %lu with ip %lx and sp %lx (ksp %lx)", thread->id, thread->ip(), + thread->sp(), thread->kernel_stack.top()); + + g_threads.append(thread); + + return {}; + } + void reap_thread(Thread* thread) { kinfoln("reap: reaping thread with id %zu", thread->id); - auto stack = thread->stack; - kinfoln("deleting thread stack @ %#lx, has %zu bytes of stack", stack.bottom(), stack.bytes()); - // FIXME: Propagate errors I guess? - MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value(); + + if (thread->is_kernel) + { + auto stack = thread->stack; + // FIXME: Propagate errors I guess? + kinfoln("deleting stack @ %#lx", stack.bottom()); + MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value(); + } + else + { + auto stack = thread->kernel_stack; + kinfoln("deleting kstack @ %#lx", stack.bottom()); + // FIXME: Propagate errors I guess? + MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value(); + } + + if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->directory); + delete thread; } @@ -138,7 +213,15 @@ namespace Scheduler void generic_switch_context(Thread* old_thread, Thread* new_thread, Registers* regs) { - if (old_thread != new_thread) switch_context(old_thread, new_thread, regs); + if (old_thread != new_thread) + { + switch_context(old_thread, new_thread, regs); + if (!new_thread->is_kernel) + { + MMU::switch_page_directory(new_thread->directory); + CPU::switch_kernel_stack(new_thread->kernel_stack.top()); + } + } if (new_thread->is_idle()) { diff --git a/kernel/src/thread/Scheduler.h b/kernel/src/thread/Scheduler.h index f818c731..c2dd4cfc 100644 --- a/kernel/src/thread/Scheduler.h +++ b/kernel/src/thread/Scheduler.h @@ -1,5 +1,6 @@ #pragma once #include "thread/Thread.h" +#include namespace Scheduler { @@ -12,6 +13,8 @@ namespace Scheduler Result new_kernel_thread(void (*func)(void)); Result new_kernel_thread(void (*func)(void*), void* arg); + Result new_userspace_thread(const TarStream::Entry& entry, const TarStream& stream); + Thread* pick_task(); void reap_thread(Thread* thread); From 0aac6c888d23d70fb4792ce42c90b150cc464f85 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 21:53:48 +0100 Subject: [PATCH 365/407] x86_64: Basic exit() syscall! User processes need to do something, amirite? --- kernel/src/arch/x86_64/CPU.asm | 3 ++- kernel/src/arch/x86_64/CPU.cpp | 6 ++++++ kernel/src/arch/x86_64/init/IDT.cpp | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index f5a2c98a..00b58b7e 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -187,4 +187,5 @@ ISR 20 ; virtualization exception (#VE) ISR_ERROR 21 ; control-protection exception (#CP) ; ISR 22-31 reserved IRQ 32, 0 ; timer interrupt -IRQ 33, 0 ; keyboard interrupt \ No newline at end of file +IRQ 33, 0 ; keyboard interrupt +ISR 66 ; user exit diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index bb0455d8..8dca8b89 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -107,6 +107,12 @@ extern "C" void arch_interrupt_entry(Registers* regs) scancode_queue.try_push(scancode); pic_eoi(regs); } + else if (regs->isr == 66) // Exit!! + { + kdbgln("exiting from user task!!"); + Scheduler::current()->state = ThreadState::Dying; + kernel_yield(); + } else { kwarnln("IRQ catched! Halting."); diff --git a/kernel/src/arch/x86_64/init/IDT.cpp b/kernel/src/arch/x86_64/init/IDT.cpp index e507613e..22ea980a 100644 --- a/kernel/src/arch/x86_64/init/IDT.cpp +++ b/kernel/src/arch/x86_64/init/IDT.cpp @@ -36,7 +36,7 @@ u64 IDTEntry::get_offset() const static IDTEntry idt[256]; #define IDT_TA_InterruptGate 0b10001110 -#define IDT_TA_UserInterruptGate 0b11101110 +#define IDT_TA_UserCallableInterruptGate 0b11101110 #define IDT_TA_TrapGate 0b10001111 struct [[gnu::packed]] IDTR @@ -60,6 +60,7 @@ static void idt_add_handler(short num, void* handler, u8 type_attr) #define INT(x) extern "C" void _isr##x() #define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) #define IRQ(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_InterruptGate) +#define SYS(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_UserCallableInterruptGate) INT(0); INT(1); @@ -83,6 +84,7 @@ INT(20); INT(21); INT(32); INT(33); +INT(66); void setup_idt() { @@ -110,6 +112,7 @@ void setup_idt() TRAP(21); IRQ(32); IRQ(33); + SYS(66); static IDTR idtr; idtr.limit = 0x0FFF; From 0ea9974512adb8cf58974646b0421669e2c6f96f Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 21:55:21 +0100 Subject: [PATCH 366/407] First user process! Putting it all together, we have a user process that successfully calls sys_exit() w/o crashing. --- apps/app.asm | 14 -------------- kernel/src/main.cpp | 13 +++---------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/apps/app.asm b/apps/app.asm index 78dc6066..56062887 100644 --- a/apps/app.asm +++ b/apps/app.asm @@ -1,18 +1,4 @@ section .text global _start _start: - mov eax, ecx - push rdx - mov eax, 1 - mov edi, hello_world - mov esi, 14 int 42h - nop - -section .rodata -hello_world: - db 'Hello, world!', 0xa, 0 - -section .bss -array: - resb 10 \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index d46b731b..f9ba6a30 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -51,7 +51,8 @@ Result init() kinfoln("Used memory: %s", to_dynamic_unit(MemoryManager::used()).release_value().chars()); kinfoln("Reserved memory: %s", to_dynamic_unit(MemoryManager::reserved()).release_value().chars()); - MMU::unmap(0x400000); + Thread::init(); + Scheduler::init(); TarStream::Entry entry; while (TRY(g_initrd.read_next_entry().try_set_value_with_specific_error(entry, 0))) @@ -61,18 +62,10 @@ Result init() kinfoln("Found file %s in initial ramdisk, of size %s", entry.name, to_dynamic_unit(entry.size).release_value().chars()); - if (!strcmp(entry.name, "bin/app")) - { - auto data = TRY(ELFLoader::load(entry, g_initrd)); - data.segments.consume([](ELFSegment* segment) { delete segment; }); - kinfoln("Loaded ELF with entry=%#.16lx", data.entry); - } + if (!strcmp(entry.name, "bin/app")) { TRY(Scheduler::new_userspace_thread(entry, g_initrd)); } } } - Thread::init(); - Scheduler::init(); - TRY(Scheduler::new_kernel_thread(heap_thread)); TRY(Scheduler::new_kernel_thread(reap_thread)); From caa3fe8c457cae8046d3d8e87311895eedbcd541 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 22:39:09 +0100 Subject: [PATCH 367/407] MemoryManager: Add validate_userspace_string() A bit crude, should be replaced by a strdup_from_user() helper to avoid touching userspace memory directly. But it'll do for now. --- kernel/src/memory/MemoryManager.cpp | 17 +++++++++++++++++ kernel/src/memory/MemoryManager.h | 2 ++ 2 files changed, 19 insertions(+) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 75014bae..9a834af2 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -347,6 +347,23 @@ namespace MemoryManager return false; } + // FIXME: Replace this with some kind of strdup_from_user() function. + bool validate_userspace_string(u64 address) + { + if (!validate_readable_page(address)) return false; + + while (*(char*)address != 0) + { + address++; + if (address % ARCH_PAGE_SIZE) + { + if (!validate_readable_page(address)) return false; + } + } + + return true; + } + usize free() { return free_mem; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index d22ed45c..b2f72a84 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -20,6 +20,8 @@ namespace MemoryManager bool validate_readable_page(u64 address); bool validate_writable_page(u64 address); + bool validate_userspace_string(u64 address); + Result map_frames_at(u64 virt, u64 phys, usize count, int flags); Result alloc_at(u64 virt, usize count, int flags); From fd8a0175d9912b8798f76613796369d94a0b4d6b Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 5 Jan 2023 22:39:56 +0100 Subject: [PATCH 368/407] Add a syscall infrastructure (our baby program can print to the console now!) --- apps/app.asm | 13 +++++++++++++ kernel/CMakeLists.txt | 5 ++++- kernel/src/arch/x86_64/CPU.asm | 2 +- kernel/src/arch/x86_64/CPU.cpp | 8 ++++---- kernel/src/sys/Syscall.cpp | 18 ++++++++++++++++++ kernel/src/sys/Syscall.h | 16 ++++++++++++++++ kernel/src/sys/console_print.cpp | 12 ++++++++++++ kernel/src/sys/exit.cpp | 7 +++++++ luna/include/luna/Syscall.h | 12 ++++++++++++ 9 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 kernel/src/sys/Syscall.cpp create mode 100644 kernel/src/sys/Syscall.h create mode 100644 kernel/src/sys/console_print.cpp create mode 100644 kernel/src/sys/exit.cpp create mode 100644 luna/include/luna/Syscall.h diff --git a/apps/app.asm b/apps/app.asm index 56062887..a0dffce7 100644 --- a/apps/app.asm +++ b/apps/app.asm @@ -1,4 +1,17 @@ section .text global _start _start: + mov rax, 1 + mov rdi, message int 42h + mov rax, 1 + mov rdi, message2 + int 42h + mov rax, 0 + int 42h + +section .rodata +message: + db "Hello!", 0xa, 0 +message2: + db "I am an app", 0xa, 0 diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 7e9e5db4..d8498225 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -15,6 +15,9 @@ set(SOURCES src/thread/Spinlock.cpp src/thread/Thread.cpp src/thread/Scheduler.cpp + src/sys/Syscall.cpp + src/sys/exit.cpp + src/sys/console_print.cpp src/InitRD.cpp src/ELF.cpp ) @@ -82,4 +85,4 @@ target_include_directories(moon PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/gen) target_link_options(moon PRIVATE LINKER:-T ${CMAKE_CURRENT_LIST_DIR}/moon.ld -nostdlib -nodefaultlibs) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/moon" DESTINATION ${LUNA_ROOT}/initrd/boot) \ No newline at end of file +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/moon" DESTINATION ${LUNA_ROOT}/initrd/boot) diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 00b58b7e..364a7367 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -188,4 +188,4 @@ ISR_ERROR 21 ; control-protection exception (#CP) ; ISR 22-31 reserved IRQ 32, 0 ; timer interrupt IRQ 33, 0 ; keyboard interrupt -ISR 66 ; user exit +ISR 66 ; system call diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 8dca8b89..72289888 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -4,6 +4,7 @@ #include "arch/x86_64/CPU.h" #include "arch/x86_64/IO.h" #include "memory/MemoryManager.h" +#include "sys/Syscall.h" #include "thread/Scheduler.h" #include #include @@ -107,11 +108,10 @@ extern "C" void arch_interrupt_entry(Registers* regs) scancode_queue.try_push(scancode); pic_eoi(regs); } - else if (regs->isr == 66) // Exit!! + else if (regs->isr == 66) // System call { - kdbgln("exiting from user task!!"); - Scheduler::current()->state = ThreadState::Dying; - kernel_yield(); + SyscallArgs args = { regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8, regs->r9 }; + regs->rax = (u64)invoke_syscall(regs, args, regs->rax); } else { diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp new file mode 100644 index 00000000..d45552aa --- /dev/null +++ b/kernel/src/sys/Syscall.cpp @@ -0,0 +1,18 @@ +#include "sys/Syscall.h" +#include + +syscall_func_t syscalls[] = { +#undef __enumerate +#define __enumerate(name) sys_##name, + enumerate_syscalls(__enumerate) +#undef __enumerate +}; + +i64 invoke_syscall(Registers* regs, SyscallArgs args, u64 syscall) +{ + if (syscall >= Syscalls::__count) { return -ENOSYS; } + + auto rc = syscalls[syscall](regs, args); + if (rc.has_error()) return -rc.error(); + return (i64)rc.value(); +} diff --git a/kernel/src/sys/Syscall.h b/kernel/src/sys/Syscall.h new file mode 100644 index 00000000..15b69505 --- /dev/null +++ b/kernel/src/sys/Syscall.h @@ -0,0 +1,16 @@ +#pragma once +#include "arch/CPU.h" +#include +#include + +typedef u64 SyscallArgs[6]; + +typedef Result (*syscall_func_t)(Registers*, SyscallArgs); + +// Invoked by the architecture-dependent system call entry point. +i64 invoke_syscall(Registers*, SyscallArgs, u64 syscall); + +#undef __enumerate +#define __enumerate(name) extern Result sys_##name(Registers*, SyscallArgs); +enumerate_syscalls(__enumerate) +#undef __enumerate diff --git a/kernel/src/sys/console_print.cpp b/kernel/src/sys/console_print.cpp new file mode 100644 index 00000000..b112c5b2 --- /dev/null +++ b/kernel/src/sys/console_print.cpp @@ -0,0 +1,12 @@ +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include "video/TextConsole.h" + +Result sys_console_print(Registers*, SyscallArgs args) +{ + if (!MemoryManager::validate_userspace_string(args[0])) return err(EFAULT); + + TextConsole::print((char*)args[0]); + + return { 0 }; +} diff --git a/kernel/src/sys/exit.cpp b/kernel/src/sys/exit.cpp new file mode 100644 index 00000000..adc591c1 --- /dev/null +++ b/kernel/src/sys/exit.cpp @@ -0,0 +1,7 @@ +#include "sys/Syscall.h" +#include "thread/Scheduler.h" + +Result sys_exit(Registers*, SyscallArgs) +{ + kernel_exit(); +} diff --git a/luna/include/luna/Syscall.h b/luna/include/luna/Syscall.h new file mode 100644 index 00000000..30551cfa --- /dev/null +++ b/luna/include/luna/Syscall.h @@ -0,0 +1,12 @@ +#pragma once + +#define enumerate_syscalls(_e) _e(exit) _e(console_print) + +enum Syscalls +{ +#undef __enumerate +#define __enumerate(name) SYS_##name, + enumerate_syscalls(__enumerate) +#undef __enumerate + __count +}; From 293b979e7580ce9f9a07bd77523a78a1922539b7 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 13:30:17 +0100 Subject: [PATCH 369/407] ELFLoader: Do not crash on non-page-aligned sections --- kernel/src/ELF.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/src/ELF.cpp b/kernel/src/ELF.cpp index c9fe522f..df28d389 100644 --- a/kernel/src/ELF.cpp +++ b/kernel/src/ELF.cpp @@ -89,7 +89,8 @@ namespace ELFLoader program_header.p_offset, program_header.p_vaddr, program_header.p_filesz, program_header.p_memsz); - check(is_aligned(program_header.p_vaddr)); + u64 base_vaddr = align_down(program_header.p_vaddr); + u64 vaddr_diff = program_header.p_vaddr - base_vaddr; /*expect(!can_write_and_execute_segment(program_header.p_flags), "Segment is both writable and executable");*/ @@ -99,8 +100,8 @@ namespace ELFLoader flags &= ~MMU::NoExecute; // Allocate physical memory for the segment - TRY(MemoryManager::alloc_at(program_header.p_vaddr, - get_blocks_from_size(program_header.p_memsz, ARCH_PAGE_SIZE), flags)); + TRY(MemoryManager::alloc_at( + base_vaddr, get_blocks_from_size(program_header.p_memsz + vaddr_diff, ARCH_PAGE_SIZE), flags)); // Load the file section of the segment stream.read_contents(elf_entry, (void*)program_header.p_vaddr, program_header.p_offset, From b27cefb9c59670c96461a9fbb7831213a0ebea86 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 13:30:49 +0100 Subject: [PATCH 370/407] SystemError: Define _LUNA_SYSTEM_ERROR_EXTENSIONS to compile properly in hosted envs --- luna/src/SystemError.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/luna/src/SystemError.cpp b/luna/src/SystemError.cpp index 74586781..5237d5a7 100644 --- a/luna/src/SystemError.cpp +++ b/luna/src/SystemError.cpp @@ -1,3 +1,4 @@ +#define _LUNA_SYSTEM_ERROR_EXTENSIONS #include const char* error_string(int error) From 129e3c434af7ad1a2e002d897b9372a2dbd2f46b Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 13:31:14 +0100 Subject: [PATCH 371/407] Switch to C for userspace, with a very bare-bones libc!! --- .gitignore | 3 +- CMakeLists.txt | 7 +++- apps/CMakeLists.txt | 5 ++- apps/app.asm | 17 -------- apps/app.c | 9 +++++ libc/CMakeLists.txt | 61 ++++++++++++++++++++++++++++ libc/include/bits/attrs.h | 10 +++++ libc/include/stdio.h | 15 +++++++ libc/include/stdlib.h | 73 ++++++++++++++++++++++++++++++++++ libc/include/sys/syscall.h | 6 +++ libc/include/sys/types.h | 9 +++++ libc/include/unistd.h | 15 +++++++ libc/src/arch/x86_64/crt0.S | 20 ++++++++++ libc/src/arch/x86_64/crti.S | 13 ++++++ libc/src/arch/x86_64/crtn.S | 9 +++++ libc/src/arch/x86_64/syscall.S | 10 +++++ libc/src/stdio.cpp | 11 +++++ libc/src/stdlib.cpp | 30 ++++++++++++++ libc/src/unistd.cpp | 26 ++++++++++++ luna/CMakeLists.txt | 21 +++++----- tools/install-headers.sh | 5 +-- 21 files changed, 339 insertions(+), 36 deletions(-) delete mode 100644 apps/app.asm create mode 100644 apps/app.c create mode 100644 libc/CMakeLists.txt create mode 100644 libc/include/bits/attrs.h create mode 100644 libc/include/stdio.h create mode 100644 libc/include/stdlib.h create mode 100644 libc/include/sys/syscall.h create mode 100644 libc/include/sys/types.h create mode 100644 libc/include/unistd.h create mode 100644 libc/src/arch/x86_64/crt0.S create mode 100644 libc/src/arch/x86_64/crti.S create mode 100644 libc/src/arch/x86_64/crtn.S create mode 100644 libc/src/arch/x86_64/syscall.S create mode 100644 libc/src/stdio.cpp create mode 100644 libc/src/stdlib.cpp create mode 100644 libc/src/unistd.cpp diff --git a/.gitignore b/.gitignore index b8172a1c..bd68726a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ toolchain/ build/ initrd/boot/moon env-local.sh -initrd/bin/** \ No newline at end of file +initrd/bin/** +base/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 037a08ce..691b5745 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,10 @@ set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_CROSSCOMPILING true) -project(Luna LANGUAGES C CXX ASM_NASM VERSION 0.1.0) +project(Luna LANGUAGES C CXX ASM ASM_NASM VERSION 0.1.0) set(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR}) +set(LUNA_BASE ${CMAKE_CURRENT_LIST_DIR}/base) set(ARCH $ENV{ARCH}) @@ -17,6 +18,7 @@ endif() set(CMAKE_C_COMPILER ${ARCH}-luna-gcc) set(CMAKE_CXX_COMPILER ${ARCH}-luna-g++) +set(CMAKE_ASM_COMPILER ${ARCH}-luna-gcc) set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) @@ -27,5 +29,6 @@ set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) message(STATUS "Configuring Luna for ${ARCH}") add_subdirectory(luna) +add_subdirectory(libc) add_subdirectory(kernel) -add_subdirectory(apps) \ No newline at end of file +add_subdirectory(apps) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index cc7a0218..4c4a143a 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,6 +1,7 @@ function(luna_app SOURCE_FILE APP_NAME) add_executable(${APP_NAME} ${SOURCE_FILE}) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${APP_NAME}" DESTINATION ${LUNA_ROOT}/initrd/bin) + add_dependencies(${APP_NAME} libc) + install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin) endfunction() -luna_app(app.asm app) \ No newline at end of file +luna_app(app.c app) diff --git a/apps/app.asm b/apps/app.asm deleted file mode 100644 index a0dffce7..00000000 --- a/apps/app.asm +++ /dev/null @@ -1,17 +0,0 @@ -section .text -global _start -_start: - mov rax, 1 - mov rdi, message - int 42h - mov rax, 1 - mov rdi, message2 - int 42h - mov rax, 0 - int 42h - -section .rodata -message: - db "Hello!", 0xa, 0 -message2: - db "I am an app", 0xa, 0 diff --git a/apps/app.c b/apps/app.c new file mode 100644 index 00000000..4f1419f1 --- /dev/null +++ b/apps/app.c @@ -0,0 +1,9 @@ +#include +#include + +int main() +{ + for (int i = 0; i < strtol("010", NULL, 0); i++) { console_print("."); } + + console_print("\n"); +} diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt new file mode 100644 index 00000000..3ac4b29d --- /dev/null +++ b/libc/CMakeLists.txt @@ -0,0 +1,61 @@ +file(GLOB HEADERS include/*.h) + +set(SOURCES + ${HEADERS} + src/stdio.cpp + src/stdlib.cpp + src/unistd.cpp +) + +if(${ARCH} STREQUAL "x86_64") + set(SOURCES + ${SOURCES} + src/arch/x86_64/syscall.S + ) +endif() + +add_library(crt0 STATIC src/arch/${ARCH}/crt0.S) +add_custom_command( + TARGET crt0 + COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crt0.o +) + +add_library(crti STATIC src/arch/${ARCH}/crti.S) +add_custom_command( + TARGET crti + COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crti.o +) + +add_library(crtn STATIC src/arch/${ARCH}/crtn.S) +add_custom_command( + TARGET crt0 + COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crtn.o +) + +add_library(bare_libc STATIC ${SOURCES}) + +target_link_libraries(bare_libc PUBLIC luna) + +target_include_directories(bare_libc PUBLIC include/) + +target_compile_options(bare_libc PRIVATE -Wall -Wextra -Werror -pedantic -nostdlib) + +target_link_options(bare_libc PRIVATE -nostdlib) + +set_target_properties(bare_libc PROPERTIES CXX_STANDARD 20) + +add_custom_target(libc + COMMAND ${CMAKE_AR} -x $ + COMMAND ${CMAKE_AR} -x $ + COMMAND ${CMAKE_AR} -rcs ${CMAKE_CURRENT_BINARY_DIR}/libc.a *.o + COMMAND rm *.o + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS bare_libc luna +) + +add_custom_command( + TARGET libc + COMMAND "${CMAKE_COMMAND}" -E copy ${CMAKE_CURRENT_BINARY_DIR}/libc.a ${LUNA_BASE}/usr/lib/libc.a +) + +file(WRITE "${LUNA_BASE}/usr/lib/libm.a" "INPUT(libc.a)") diff --git a/libc/include/bits/attrs.h b/libc/include/bits/attrs.h new file mode 100644 index 00000000..f71081cc --- /dev/null +++ b/libc/include/bits/attrs.h @@ -0,0 +1,10 @@ +#ifndef _BITS_ATTRS_H +#define _BITS_ATTRS_H + +#if !defined(_STDLIB_H) +#error "Never include bits/attrs.h directly; use one of the standard library headers." +#endif + +#define __noreturn __attribute__((noreturn)) + +#endif diff --git a/libc/include/stdio.h b/libc/include/stdio.h new file mode 100644 index 00000000..746fe3a9 --- /dev/null +++ b/libc/include/stdio.h @@ -0,0 +1,15 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + void console_print(const char*); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h new file mode 100644 index 00000000..7e6a0f56 --- /dev/null +++ b/libc/include/stdlib.h @@ -0,0 +1,73 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +#include +#include + +typedef struct +{ + int quot; + int rem; +} div_t; + +typedef struct +{ + long quot; + long rem; +} ldiv_t; + +typedef struct +{ + long long quot; + long long rem; +} lldiv_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + + int abs(int); + long labs(long); + long long llabs(long long); + + div_t div(int, int); + ldiv_t ldiv(long, long); + lldiv_t lldiv(long long, long long); + + void* malloc(size_t); + void* calloc(size_t, size_t); + void* realloc(void*, size_t); + void free(void*); + + __noreturn void abort(); + int atexit(void (*)(void)); + + int atoi(const char*); + long atol(const char*); + long long atoll(const char*); + + double atof(const char*); + + double strtod(const char*, char**); + + long strtol(const char*, char**, int); + unsigned long strtoul(const char*, char**, int); + + int rand(); + void srand(int); + + __noreturn void exit(int); + + int system(const char*); + + char* getenv(const char*); + + void qsort(void*, size_t, size_t, int (*)(const void*, const void*)); + void* bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h new file mode 100644 index 00000000..b7e75c17 --- /dev/null +++ b/libc/include/sys/syscall.h @@ -0,0 +1,6 @@ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#include + +#endif diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h new file mode 100644 index 00000000..25b16927 --- /dev/null +++ b/libc/include/sys/types.h @@ -0,0 +1,9 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#define __need_size_t +#include + +typedef int pid_t; + +#endif diff --git a/libc/include/unistd.h b/libc/include/unistd.h new file mode 100644 index 00000000..6ad244fa --- /dev/null +++ b/libc/include/unistd.h @@ -0,0 +1,15 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + long syscall(long, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/src/arch/x86_64/crt0.S b/libc/src/arch/x86_64/crt0.S new file mode 100644 index 00000000..cfebdc21 --- /dev/null +++ b/libc/src/arch/x86_64/crt0.S @@ -0,0 +1,20 @@ +.section .text + +.global _start +.extern exit +_start: + # Set up end of the stack frame linked list. + movq $0, %rbp + pushq %rbp # rip=0 + pushq %rbp # rbp=0 + movq %rsp, %rbp + + # Run the global constructors. + call _init + + # Run main + call main + + # Terminate the process with the exit code. + movl %eax, %edi + call exit diff --git a/libc/src/arch/x86_64/crti.S b/libc/src/arch/x86_64/crti.S new file mode 100644 index 00000000..03ad2f91 --- /dev/null +++ b/libc/src/arch/x86_64/crti.S @@ -0,0 +1,13 @@ +.section .init +.global _init +_init: + push %rbp + movq %rsp, %rbp + /* gcc will nicely put the contents of crtbegin.o's .init section here. */ + +.section .fini +.global _fini +_fini: + push %rbp + movq %rsp, %rbp + /* gcc will nicely put the contents of crtbegin.o's .fini section here. */ diff --git a/libc/src/arch/x86_64/crtn.S b/libc/src/arch/x86_64/crtn.S new file mode 100644 index 00000000..762c7f6c --- /dev/null +++ b/libc/src/arch/x86_64/crtn.S @@ -0,0 +1,9 @@ +.section .init + /* gcc will nicely put the contents of crtend.o's .init section here. */ + popq %rbp + ret + +.section .fini + /* gcc will nicely put the contents of crtend.o's .fini section here. */ + popq %rbp + ret diff --git a/libc/src/arch/x86_64/syscall.S b/libc/src/arch/x86_64/syscall.S new file mode 100644 index 00000000..9ec1286c --- /dev/null +++ b/libc/src/arch/x86_64/syscall.S @@ -0,0 +1,10 @@ +.global arch_invoke_syscall +arch_invoke_syscall: + mov %rdi, %rax + mov %rsi, %rdi + mov %rdx, %rsi + mov %rcx, %rdx + mov %r8, %r10 + mov %r9, %r8 + int $66 + ret diff --git a/libc/src/stdio.cpp b/libc/src/stdio.cpp new file mode 100644 index 00000000..aec92562 --- /dev/null +++ b/libc/src/stdio.cpp @@ -0,0 +1,11 @@ +#include +#include +#include + +extern "C" +{ + void console_print(const char* str) + { + syscall(SYS_console_print, str); + } +} diff --git a/libc/src/stdlib.cpp b/libc/src/stdlib.cpp new file mode 100644 index 00000000..87fb244d --- /dev/null +++ b/libc/src/stdlib.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +extern "C" +{ + // FIXME: Check for overflow in both strtol() and strtoul(). + long strtol(const char* str, char** endptr, int base) + { + return (long)parse_signed_integer(str, const_cast(endptr), base); + } + + unsigned long strtoul(const char* str, char** endptr, int base) + { + return (unsigned long)parse_unsigned_integer(str, const_cast(endptr), base); + } + + __noreturn void abort() + { + syscall(SYS_exit); + __builtin_unreachable(); + } + + __noreturn void exit(int) + { + syscall(SYS_exit); + __builtin_unreachable(); + } +} diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp new file mode 100644 index 00000000..58b0c277 --- /dev/null +++ b/libc/src/unistd.cpp @@ -0,0 +1,26 @@ +#include +#include +#include + +extern "C" long arch_invoke_syscall(long, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); + +extern "C" +{ + long syscall(long num, ...) + { + va_list ap; + va_start(ap, num); + + uintptr_t arg0 = va_arg(ap, uintptr_t); + uintptr_t arg1 = va_arg(ap, uintptr_t); + uintptr_t arg2 = va_arg(ap, uintptr_t); + uintptr_t arg3 = va_arg(ap, uintptr_t); + uintptr_t arg4 = va_arg(ap, uintptr_t); + + long rc = arch_invoke_syscall(num, arg0, arg1, arg2, arg3, arg4); + + va_end(ap); + + return rc; + } +} diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 4d8be399..90dd5a40 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -36,24 +36,23 @@ target_compile_options(luna-freestanding PRIVATE -nostdlib -mcmodel=kernel) target_include_directories(luna-freestanding PUBLIC include/) set_target_properties(luna-freestanding PROPERTIES CXX_STANDARD 20) -#add_library(luna ${SOURCES}) -#target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) -#target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) -#target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) -#target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) -#target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer) -#target_include_directories(luna PUBLIC include/) -#set_target_properties(luna PROPERTIES CXX_STANDARD 20) +add_library(luna ${SOURCES}) +target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) +target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) +target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) +target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) +target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20) +target_include_directories(luna PUBLIC include/) if("${ARCH}" MATCHES "x86_64") target_compile_options(luna-freestanding PRIVATE -mno-red-zone) target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2) target_compile_definitions(luna-freestanding PUBLIC ARCH_X86_64) -#target_compile_definitions(luna PUBLIC ARCH_X86_64) +target_compile_definitions(luna PUBLIC ARCH_X86_64) endif() if(LUNA_DEBUG_SYMBOLS) message(STATUS "Building Luna with debug symbols") - #target_compile_options(luna PRIVATE -ggdb) + target_compile_options(luna PRIVATE -ggdb) target_compile_options(luna-freestanding PRIVATE -ggdb) -endif() \ No newline at end of file +endif() diff --git a/tools/install-headers.sh b/tools/install-headers.sh index 94cf0b7c..c851192f 100755 --- a/tools/install-headers.sh +++ b/tools/install-headers.sh @@ -7,8 +7,7 @@ cd $LUNA_ROOT mkdir -p $LUNA_BASE mkdir -p $LUNA_BASE/usr/include -mkdir -p $LUNA_BASE/usr/include/moon mkdir -p $LUNA_BASE/usr/include/luna -cp -RT kernel/**/*.h $LUNA_BASE/usr/include/moon -cp -RT luna/include/luna/*.h $LUNA_BASE/usr/include/luna \ No newline at end of file +cp -RT libc/include/ $LUNA_BASE/usr/include +cp -RT luna/include/luna/ $LUNA_BASE/usr/include/luna From f1923ce5bda0a551bfeecf315a64b57e185a04ef Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 13:35:57 +0100 Subject: [PATCH 372/407] Install headers before compilation --- tools/build-debug.sh | 4 +++- tools/build-iso.sh | 4 ++-- tools/build.sh | 4 ++-- tools/rebuild-iso.sh | 4 +++- tools/rebuild.sh | 4 +++- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/build-debug.sh b/tools/build-debug.sh index 0fcb695e..e571ff01 100755 --- a/tools/build-debug.sh +++ b/tools/build-debug.sh @@ -9,8 +9,10 @@ tools/setup.sh tools/full-clean.sh +tools/install-headers.sh + cmake -S . -B $BUILD_DIR -DMOON_DEBUG_SYMBOLS=ON -DLUNA_DEBUG_SYMBOLS=ON -G "$CMAKE_GEN" cmake --build $BUILD_DIR cmake --install $BUILD_DIR -mkbootimg luna.json Luna.iso \ No newline at end of file +mkbootimg luna.json Luna.iso diff --git a/tools/build-iso.sh b/tools/build-iso.sh index 168b75ac..ee0177dc 100755 --- a/tools/build-iso.sh +++ b/tools/build-iso.sh @@ -7,11 +7,11 @@ cd $LUNA_ROOT tools/setup.sh -#tools/install-headers.sh +tools/install-headers.sh mkdir -p $BUILD_DIR cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" cmake --build $BUILD_DIR cmake --install $BUILD_DIR -mkbootimg luna.json Luna.iso \ No newline at end of file +mkbootimg luna.json Luna.iso diff --git a/tools/build.sh b/tools/build.sh index ee07e209..f854d8e5 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -7,8 +7,8 @@ cd $LUNA_ROOT tools/setup.sh -#tools/install-headers.sh +tools/install-headers.sh mkdir -p $BUILD_DIR cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" -cmake --build $BUILD_DIR \ No newline at end of file +cmake --build $BUILD_DIR diff --git a/tools/rebuild-iso.sh b/tools/rebuild-iso.sh index a10085cb..012df09c 100755 --- a/tools/rebuild-iso.sh +++ b/tools/rebuild-iso.sh @@ -9,8 +9,10 @@ tools/setup.sh tools/full-clean.sh +tools/install-headers.sh + cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" cmake --build $BUILD_DIR cmake --install $BUILD_DIR -mkbootimg luna.json Luna.iso \ No newline at end of file +mkbootimg luna.json Luna.iso diff --git a/tools/rebuild.sh b/tools/rebuild.sh index 1c3e0316..524b7ba1 100755 --- a/tools/rebuild.sh +++ b/tools/rebuild.sh @@ -9,5 +9,7 @@ tools/setup.sh tools/full-clean.sh +tools/install-headers.sh + cmake -S . -B $BUILD_DIR -G "$CMAKE_GEN" -cmake --build $BUILD_DIR \ No newline at end of file +cmake --build $BUILD_DIR From 08608d2344c341a7a049f91ee326c81001c7f6f0 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 13:38:48 +0100 Subject: [PATCH 373/407] Depend on libc headers --- luna/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 90dd5a40..9e301eb1 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -43,6 +43,7 @@ target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wca target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20) target_include_directories(luna PUBLIC include/) +target_include_directories(luna PUBLIC ${LUNA_BASE}/usr/include) if("${ARCH}" MATCHES "x86_64") target_compile_options(luna-freestanding PRIVATE -mno-red-zone) From db1941140c41eb7f634436ad1b3ef6006d83fd87 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 13:40:53 +0100 Subject: [PATCH 374/407] Explicitly include system headers to make it build on CI --- apps/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 4c4a143a..8f0cdef2 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,6 +1,7 @@ function(luna_app SOURCE_FILE APP_NAME) add_executable(${APP_NAME} ${SOURCE_FILE}) add_dependencies(${APP_NAME} libc) + target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include) install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin) endfunction() From 71414c06535c639d423d07d4a460b63758f72608 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 14:28:53 +0100 Subject: [PATCH 375/407] Explicitly set the link path to make it build on CI --- apps/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 8f0cdef2..75fecfb8 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -2,6 +2,7 @@ function(luna_app SOURCE_FILE APP_NAME) add_executable(${APP_NAME} ${SOURCE_FILE}) add_dependencies(${APP_NAME} libc) target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include) + target_link_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/lib) install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin) endfunction() From 7acef24494766bf79da5f1395dc71516309c7e97 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 14:32:38 +0100 Subject: [PATCH 376/407] Make libc depend on crt{0,i,n}.o --- libc/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 3ac4b29d..00e9e281 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -28,7 +28,7 @@ add_custom_command( add_library(crtn STATIC src/arch/${ARCH}/crtn.S) add_custom_command( - TARGET crt0 + TARGET crtn COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crtn.o ) @@ -50,7 +50,7 @@ add_custom_target(libc COMMAND ${CMAKE_AR} -rcs ${CMAKE_CURRENT_BINARY_DIR}/libc.a *.o COMMAND rm *.o WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS bare_libc luna + DEPENDS bare_libc luna crti crtn crt0 ) add_custom_command( From 30555f8e5ade7c25f780230e7e5b7a3d63f4cd04 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 15:00:49 +0100 Subject: [PATCH 377/407] Skip these because CI needed a toolchain rebuild --- apps/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 75fecfb8..4c4a143a 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,8 +1,6 @@ function(luna_app SOURCE_FILE APP_NAME) add_executable(${APP_NAME} ${SOURCE_FILE}) add_dependencies(${APP_NAME} libc) - target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include) - target_link_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/lib) install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin) endfunction() From a01b56ed39f6cd16064edbd4f521fb391ee42895 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 16:20:35 +0100 Subject: [PATCH 378/407] CString: Support strcpy(), strcat() and strchr() --- luna/include/luna/CString.h | 5 +++++ luna/src/CString.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/luna/include/luna/CString.h b/luna/include/luna/CString.h index df46497c..b4ac3029 100644 --- a/luna/include/luna/CString.h +++ b/luna/include/luna/CString.h @@ -16,4 +16,9 @@ extern "C" // Copies len bytes from src into dest and adds a null terminator. void nullcpy(char* dest, const char* src, usize len); + + [[deprecated]] char* strcpy(char* dst, const char* src); + [[deprecated]] char* strcat(char* dst, const char* src); + + char* strchr(const char* str, int c); } diff --git a/luna/src/CString.cpp b/luna/src/CString.cpp index ac048c3c..06f129f6 100644 --- a/luna/src/CString.cpp +++ b/luna/src/CString.cpp @@ -81,4 +81,28 @@ extern "C" memcpy(dest, src, len); dest[len] = 0; } + + char* strcpy(char* dest, const char* src) + { + char* s = dest; + for (; *src; dest++, src++) *dest = *src; + *dest = 0; + return s; + } + + char* strcat(char* dest, const char* src) + { + char* s = dest; + while (*dest) dest++; + for (; *src; dest++, src++) *dest = *src; + *dest = 0; + return s; + } + + char* strchr(const char* str, int c) + { + while (*str && *str != c) str++; + if (*str) return const_cast(str); + return NULL; + } } From 87a4bc91d84ee7eca4ca25ef005542cfbc4bbea6 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 17:31:22 +0100 Subject: [PATCH 379/407] arch/x86_64: Nicer display for page faults that shows a human-readable version of the error code --- kernel/src/arch/x86_64/CPU.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 72289888..3f88e237 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -29,6 +29,19 @@ extern void setup_idt(); kerrorln("FIXME(interrupt): %s", name); \ CPU::efficient_halt(); +#define PF_PRESENT 1 << 0 +#define PF_WRITE 1 << 1 +#define PF_USER 1 << 2 +#define PF_RESERVED 1 << 3 +#define PF_NX_VIOLATION 1 << 4 + +void decode_page_fault_error_code(u64 code) +{ + kwarnln("Fault details: %s | %s | %s%s%s", (code & PF_PRESENT) ? "Present" : "Not present", + (code & PF_WRITE) ? "Write access" : "Read access", (code & PF_USER) ? "User mode" : "Kernel mode", + (code & PF_RESERVED) ? " | Reserved bits set" : "", (code & PF_NX_VIOLATION) ? " | NX violation" : ""); +} + [[noreturn]] void handle_page_fault(Registers* regs) { CPU::disable_interrupts(); @@ -37,6 +50,8 @@ extern void setup_idt(); asm volatile("mov %%cr2, %0" : "=r"(cr2)); kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2); + decode_page_fault_error_code(regs->error); + CPU::print_stack_trace_at(regs); CPU::efficient_halt(); From e37280b0e5ad5e836db2909e7726b58a66ca1a04 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 17:34:24 +0100 Subject: [PATCH 380/407] ELFLoader: Set both the read-write and execute flags if the section has both Not good for W^X, but the compiler decides to squash everything into a single program header :( --- kernel/src/ELF.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/src/ELF.cpp b/kernel/src/ELF.cpp index df28d389..1af55e15 100644 --- a/kernel/src/ELF.cpp +++ b/kernel/src/ELF.cpp @@ -96,8 +96,7 @@ namespace ELFLoader int flags = MMU::User | MMU::NoExecute; if (can_write_segment(program_header.p_flags)) flags |= MMU::ReadWrite; - else if (can_execute_segment(program_header.p_flags)) - flags &= ~MMU::NoExecute; + if (can_execute_segment(program_header.p_flags)) flags &= ~MMU::NoExecute; // Allocate physical memory for the segment TRY(MemoryManager::alloc_at( From 8838e2cf22bb10ced016be3d4ef38a43070b45cf Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 17:35:07 +0100 Subject: [PATCH 381/407] Bring back the OS-Specific Toolchain on restart :^) --- .drone.yml | 4 +- CMakeLists.txt | 2 +- README.md | 13 ++- libc/CMakeLists.txt | 2 + libc/include/bits/attrs.h | 3 +- libc/include/bits/errno-return.h | 16 ++++ libc/include/errno.h | 8 ++ libc/include/stdio.h | 32 +++++++- libc/include/string.h | 31 +++++++ libc/include/time.h | 4 + libc/include/unistd.h | 10 +++ libc/src/errno.cpp | 3 + libc/src/stdio.cpp | 8 +- libc/src/string.cpp | 14 ++++ tools/binutils.patch | 117 +++++++++++++++++++++++++++ tools/env.sh | 4 +- tools/gcc.patch | 134 +++++++++++++++++++++++++++++++ tools/setup-binutils.sh | 8 +- tools/setup-env.sh | 4 +- tools/setup-gcc.sh | 21 ++--- 20 files changed, 400 insertions(+), 38 deletions(-) create mode 100644 libc/include/bits/errno-return.h create mode 100644 libc/include/errno.h create mode 100644 libc/include/string.h create mode 100644 libc/include/time.h create mode 100644 libc/src/errno.cpp create mode 100644 libc/src/string.cpp create mode 100644 tools/binutils.patch create mode 100644 tools/gcc.patch diff --git a/.drone.yml b/.drone.yml index ac733b83..2636d74a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -11,7 +11,7 @@ steps: image: ubuntu commands: - apt update - - apt install build-essential cmake ninja-build wget nasm -y + - apt install cmake ninja-build wget nasm -y - wget https://pub.cloudapio.eu/luna/toolchains/ci-toolchain-arm64.tar.gz --quiet - tar xf ci-toolchain-arm64.tar.gz - rm ci-toolchain-arm64.tar.gz @@ -23,4 +23,4 @@ trigger: - restart event: - push - - pull_request \ No newline at end of file + - pull_request diff --git a/CMakeLists.txt b/CMakeLists.txt index 691b5745..0d4e5b69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) set(CMAKE_ASM_NASM_LINK_EXECUTABLE "${ARCH}-luna-ld -o ") -set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna) +set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86_64-luna) message(STATUS "Configuring Luna for ${ARCH}") diff --git a/README.md b/README.md index e0e08b1a..6bf71a57 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ A simple kernel and userspace for the x86_64 platform, written mostly in C++ and - Keeps track of [memory](kernel/src/memory/). (Rewritten) - Can read, write and execute files from a [virtual file system](kernel/src/fs/) supporting an initial ramdisk, device pseudo-filesystems... but no hard disks yet. (Not there yet) - Preemptive multitasking, with a round-robin [scheduler](kernel/src/thread/) that can switch between tasks. (Rewritten) -- Can [load ELF programs](kernel/src/sys/elf/) from the file system as userspace tasks. (Not there yet) -- [System call](kernel/src/sys/) interface and [C Library](libs/libc/), aiming to be mostly POSIX-compatible. (Not there yet) +- Can [load ELF programs](kernel/src/ELF.cpp) from the file system as userspace tasks. (Rewritten) +- [System call](kernel/src/sys/) interface and [C Library](libc/), aiming to be mostly POSIX-compatible. (Rewriting) - UNIX-like [multitasking primitives](kernel/src/sys/exec.cpp), which allow user tasks to spawn other tasks. (Not there yet) - Some simple [userspace programs](apps/src/), written in C. (Not there yet) - Simple [command-line shell](apps/src/sh.c), allowing for interactive use of the system. (Not there yet) @@ -25,12 +25,9 @@ A simple kernel and userspace for the x86_64 platform, written mostly in C++ and ## Notes - The default user is named 'selene' and you can log into it with the password 'moon'. -## Setup (broken) -**WARNING**: Setup will fail on this branch, since we do not have the required libc headers yet, and I removed the patches for now. Your best bet to build the toolchain is to switch to the `main` branch, where it will build successfully, and run `tools/setup.sh`. Then switch back to this branch, run `git clean -fd`, and continue development :) +## Setup (not broken anymore) -Alternatively, you can also download prebuilt toolchains for x86_64/arm64 Linux hosts from [here](https://pub.cloudapio.eu/luna/toolchains). Then run `tar xf toolchain-linux-ARCH.tar.gz -C /path/to/luna`. - -**ORIGINAL INSTRUCTIONS** +Although some prebuilt toolchains do exist, they have a hardcoded directory structure which is unlikely to match your setup and will thus cause problems. The best option is always to compile your own cross-toolchain, and now that the `restart` branch is mature enough to do that, go for it! To build and run Luna, you will need to build a [GCC Cross-Compiler](https://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler) and cross-binutils for `x86_64-luna`. (Yes, Luna is advanced enough that it can use its own [OS-Specific Toolchain](https://wiki.osdev.org/OS_Specific_Toolchain), instead of a bare metal target like `x86_64-elf`. It is the first of my OS projects to be able to do so. The patches for Binutils and GCC are [binutils.patch](tools/binutils.patch) and [gcc.patch](tools/gcc.patch)). @@ -113,4 +110,4 @@ Port usage: `ports/make-package.sh ` will compile the port and make a package archive from it, which may be used in the future with a package manager :) ## License -Luna is open-source and free software under the [BSD-2 License](LICENSE). \ No newline at end of file +Luna is open-source and free software under the [BSD-2 License](LICENSE). diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 00e9e281..da64b048 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -5,6 +5,8 @@ set(SOURCES src/stdio.cpp src/stdlib.cpp src/unistd.cpp + src/errno.cpp + src/string.cpp ) if(${ARCH} STREQUAL "x86_64") diff --git a/libc/include/bits/attrs.h b/libc/include/bits/attrs.h index f71081cc..e8d28f34 100644 --- a/libc/include/bits/attrs.h +++ b/libc/include/bits/attrs.h @@ -1,10 +1,11 @@ #ifndef _BITS_ATTRS_H #define _BITS_ATTRS_H -#if !defined(_STDLIB_H) +#if !defined(_STDLIB_H) && !defined(_STRING_H) #error "Never include bits/attrs.h directly; use one of the standard library headers." #endif #define __noreturn __attribute__((noreturn)) +#define __deprecated __attribute__((deprecated)) #endif diff --git a/libc/include/bits/errno-return.h b/libc/include/bits/errno-return.h new file mode 100644 index 00000000..2a147622 --- /dev/null +++ b/libc/include/bits/errno-return.h @@ -0,0 +1,16 @@ +#ifndef _BITS_ERRNO_RETURN_H +#define _BITS_ERRNO_RETURN_H + +#include + +#define __errno_return(value, type) \ + do { \ + if (value < 0) \ + { \ + errno = (int)(-value); \ + return (type)-1; \ + } \ + return (type)value; \ + } while (0) + +#endif diff --git a/libc/include/errno.h b/libc/include/errno.h new file mode 100644 index 00000000..5ffee032 --- /dev/null +++ b/libc/include/errno.h @@ -0,0 +1,8 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +extern int errno; + +#include + +#endif diff --git a/libc/include/stdio.h b/libc/include/stdio.h index 746fe3a9..422efb68 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -1,12 +1,42 @@ #ifndef _STDIO_H #define _STDIO_H +#include +#include + +typedef struct +{ + int __unused; +} FILE; + +#define SEEK_SET 0 + +extern FILE* stderr; +#define stderr stderr + #ifdef __cplusplus extern "C" { #endif - void console_print(const char*); + int fflush(FILE*); + + FILE* fopen(const char*, const char*); + int fclose(FILE*); + + size_t fread(void*, size_t, size_t, FILE*); + size_t fwrite(const void*, size_t, size_t, FILE*); + + int fseek(FILE*, long, int); + long ftell(FILE*); + + void setbuf(FILE*, char*); + + int fprintf(FILE*, const char*, ...); + int vfprintf(FILE*, const char*, va_list); + int sprintf(char*, const char*, ...); + + int console_print(const char*); #ifdef __cplusplus } diff --git a/libc/include/string.h b/libc/include/string.h new file mode 100644 index 00000000..7fd223ae --- /dev/null +++ b/libc/include/string.h @@ -0,0 +1,31 @@ +#ifndef _STRING_H +#define _STRING_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + void* memcpy(void* dest, const void* src, size_t n); + void* memset(void* buf, int c, size_t n); + int memcmp(const void* a, const void* b, size_t n); + void* memmove(void* dest, const void* src, size_t n); + size_t strlen(const char* str); + + int strcmp(const char* a, const char* b); + __deprecated char* strcpy(char* dest, const char* src); + __deprecated char* strcat(char* dest, const char* src); + char* strchr(const char* str, int c); + + char* strdup(const char* str); + + char* strerror(int errnum); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/include/time.h b/libc/include/time.h new file mode 100644 index 00000000..4c01e32c --- /dev/null +++ b/libc/include/time.h @@ -0,0 +1,4 @@ +#ifndef _TIME_H +#define _TIME_H + +#endif diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 6ad244fa..46e904c2 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -1,11 +1,21 @@ #ifndef _UNISTD_H #define _UNISTD_H +#include +#include + #ifdef __cplusplus extern "C" { #endif + pid_t fork(); + pid_t getpid(); + + int execv(const char*, char* const*); + int execve(const char*, char* const*, char* const*); + int execvp(const char*, char* const*); + long syscall(long, ...); #ifdef __cplusplus diff --git a/libc/src/errno.cpp b/libc/src/errno.cpp new file mode 100644 index 00000000..14a81221 --- /dev/null +++ b/libc/src/errno.cpp @@ -0,0 +1,3 @@ +#include + +int errno = 0; diff --git a/libc/src/stdio.cpp b/libc/src/stdio.cpp index aec92562..cecba48f 100644 --- a/libc/src/stdio.cpp +++ b/libc/src/stdio.cpp @@ -1,11 +1,15 @@ +#include #include #include #include +FILE* stderr = nullptr; + extern "C" { - void console_print(const char* str) + int console_print(const char* str) { - syscall(SYS_console_print, str); + long rc = syscall(SYS_console_print, str); + __errno_return(rc, int); } } diff --git a/libc/src/string.cpp b/libc/src/string.cpp new file mode 100644 index 00000000..0c22b9af --- /dev/null +++ b/libc/src/string.cpp @@ -0,0 +1,14 @@ +#define _LUNA_SYSTEM_ERROR_EXTENSIONS +#include +#include + +extern "C" +{ + // memcpy, memset, memcmp, memmove, strlen, strcmp, strcpy, strchr, strcat and strdup are defined in + // luna/CString.cpp, so the same definitions can be used by both kernel and userspace. + + char* strerror(int errnum) + { + return const_cast(error_string(errnum)); + } +} diff --git a/tools/binutils.patch b/tools/binutils.patch new file mode 100644 index 00000000..d375e06f --- /dev/null +++ b/tools/binutils.patch @@ -0,0 +1,117 @@ +diff --color -rN -u binutils-2.38/bfd/config.bfd build/binutils-2.38/bfd/config.bfd +--- a/binutils-2.38/bfd/config.bfd 2022-01-22 13:14:07.000000000 +0100 ++++ b/binutils-2.38/bfd/config.bfd 2022-10-01 22:12:16.914033792 +0200 +@@ -651,6 +651,11 @@ + targ_selvecs="iamcu_elf32_vec i386_pei_vec" + targ64_selvecs="x86_64_elf64_vec x86_64_elf32_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec" + ;; ++ i[3-7]86-*-luna*) ++ targ_defvec=i386_elf32_vec ++ targ_selvecs= ++ targ64_selvecs=x86_64_elf64_vec ++ ;; + i[3-7]86-*-redox*) + targ_defvec=i386_elf32_vec + targ_selvecs= +@@ -706,6 +711,11 @@ + targ_selvecs="i386_elf32_vec iamcu_elf32_vec x86_64_elf32_vec i386_pei_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec" + want64=true + ;; ++ x86_64-*-luna*) ++ targ_defvec=x86_64_elf64_vec ++ targ_selvecs=i386_elf32_vec ++ want64=true ++ ;; + x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin) + targ_defvec=x86_64_pe_vec + targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_big_vec x86_64_elf64_vec l1om_elf64_vec k1om_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec" +diff --color -rN -u binutils-2.38/gas/configure.tgt build/binutils-2.38/gas/configure.tgt +--- a/binutils-2.38/gas/configure.tgt 2022-01-22 13:14:08.000000000 +0100 ++++ b/binutils-2.38/gas/configure.tgt 2022-10-01 22:12:38.115093972 +0200 +@@ -238,6 +238,7 @@ + x86_64*-linux-gnux32) arch=x86_64:32 ;; + esac ;; + i386-*-lynxos*) fmt=elf em=lynx ;; ++ i386-*-luna*) fmt=elf em=gnu ;; + i386-*-redox*) fmt=elf ;; + i386-*-solaris*) fmt=elf em=solaris ;; + i386-*-freebsd* \ +diff --color -rN -u binutils-2.38/ld/configure.tgt build/binutils-2.38/ld/configure.tgt +--- a/binutils-2.38/ld/configure.tgt 2022-01-22 15:19:36.000000000 +0100 ++++ b/binutils-2.38/ld/configure.tgt 2022-10-01 22:15:04.853571062 +0200 +@@ -329,6 +329,11 @@ + targ64_extra_emuls="elf_x86_64 elf32_x86_64 elf_l1om elf_k1om" + targ64_extra_libpath="elf_x86_64 elf32_x86_64" + ;; ++i[3-7]86-*-luna*) ++ targ_emul=elf_i386_luna ++ targ_extra_emuls=elf_i386 ++ targ64_extra_emuls="elf_x86_64_luna elf_x86_64" ++ ;; + i[3-7]86-*-redox*) targ_emul=elf_i386 + targ_extra_emuls=elf_x86_64 + ;; +@@ -967,6 +972,10 @@ + targ_extra_libpath="elf_i386 elf32_x86_64 elf_l1om elf_k1om" + tdir_elf_i386=`echo ${targ_alias} | sed -e 's/x86_64/i386/'` + ;; ++x86_64-*-luna*) ++ targ_emul=elf_x86_64_luna ++ targ_extra_emuls="elf_i386_luna elf_x86_64 elf_i386" ++ ;; + x86_64-*-redox*) targ_emul=elf_x86_64 + targ_extra_emuls=elf_i386 + ;; +diff --color -rN -u binutils-2.38/ld/emulparams/elf_i386_luna.sh build/binutils-2.38/ld/emulparams/elf_i386_luna.sh +--- a/dev/null 1970-01-01 01:00:00.000000000 +0100 ++++ b/binutils-2.38/ld/emulparams/elf_i386_luna.sh 2022-10-01 21:52:12.394068335 +0200 +@@ -0,0 +1,3 @@ ++source_sh ${srcdir}/emulparams/elf_i386.sh ++TEXT_START_ADDR=0x08000000 ++MAXPAGESIZE=0x1000 +\ No newline at end of file +diff --color -rN -u binutils-2.38/ld/emulparams/elf_x86_64_luna.sh build/binutils-2.38/ld/emulparams/elf_x86_64_luna.sh +--- a/dev/null 1970-01-01 01:00:00.000000000 +0100 ++++ b/binutils-2.38/ld/emulparams/elf_x86_64_luna.sh 2022-10-01 21:53:00.411200592 +0200 +@@ -0,0 +1,2 @@ ++source_sh ${srcdir}/emulparams/elf_x86_64.sh ++MAXPAGESIZE=0x1000 +\ No newline at end of file +diff --color -rN -u binutils-2.38/ld/Makefile.am build/binutils-2.38/ld/Makefile.am +--- a/binutils-2.38/ld/Makefile.am 2022-01-22 13:14:09.000000000 +0100 ++++ b/binutils-2.38/ld/Makefile.am 2022-10-01 22:18:02.660263017 +0200 +@@ -278,6 +278,7 @@ + eelf32xtensa.c \ + eelf32z80.c \ + eelf_i386.c \ ++ eelf_i386_luna.c \ + eelf_i386_be.c \ + eelf_i386_fbsd.c \ + eelf_i386_haiku.c \ +@@ -464,6 +465,7 @@ + eelf_x86_64_fbsd.c \ + eelf_x86_64_haiku.c \ + eelf_x86_64_sol2.c \ ++ eelf_x86_64_luna.c \ + ehppa64linux.c \ + ei386pep.c \ + emmo.c +diff --color -rN -u binutils-2.38/ld/Makefile.in build/binutils-2.38/ld/Makefile.in +--- a/binutils-2.38/ld/Makefile.in 2022-02-09 12:49:03.000000000 +0100 ++++ b/binutils-2.38/ld/Makefile.in 2022-10-01 22:17:46.740196925 +0200 +@@ -769,6 +769,7 @@ + eelf32xtensa.c \ + eelf32z80.c \ + eelf_i386.c \ ++ eelf_i386_luna.c \ + eelf_i386_be.c \ + eelf_i386_fbsd.c \ + eelf_i386_haiku.c \ +@@ -954,6 +955,7 @@ + eelf_x86_64_fbsd.c \ + eelf_x86_64_haiku.c \ + eelf_x86_64_sol2.c \ ++ eelf_x86_64_luna.c \ + ehppa64linux.c \ + ei386pep.c \ + emmo.c diff --git a/tools/env.sh b/tools/env.sh index daf02519..72d65835 100755 --- a/tools/env.sh +++ b/tools/env.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash export LUNA_ROOT=${LUNA_ROOT:-$(realpath $(dirname $0)/..)} export LUNA_BASE=${LUNA_BASE:-$LUNA_ROOT/base} -export PATH=$LUNA_ROOT/toolchain/x86-64-luna/bin:$LUNA_ROOT/toolchain/dist:$PATH +export PATH=$LUNA_ROOT/toolchain/x86_64-luna/bin:$LUNA_ROOT/toolchain/dist:$PATH [ -f "$LUNA_ROOT/env-local.sh" ] && source $LUNA_ROOT/env-local.sh @@ -16,4 +16,4 @@ export BUILD=ninja export CMAKE_GEN="Ninja" fi -export BUILD_DIR=$LUNA_ROOT/build/$BUILD-$ARCH \ No newline at end of file +export BUILD_DIR=$LUNA_ROOT/build/$BUILD-$ARCH diff --git a/tools/gcc.patch b/tools/gcc.patch new file mode 100644 index 00000000..3a984f97 --- /dev/null +++ b/tools/gcc.patch @@ -0,0 +1,134 @@ +diff --color -rN -u gcc-12.2.0/config.sub build/gcc-12.2.0/config.sub +--- a/gcc-12.2.0/config.sub 2022-08-19 10:09:52.128656687 +0200 ++++ b/gcc-12.2.0/config.sub 2022-10-02 11:27:45.660055384 +0200 +@@ -1723,7 +1723,7 @@ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ + | hiux* | abug | nacl* | netware* | windows* \ +- | os9* | macos* | osx* | ios* \ ++ | os9* | macos* | osx* | ios* | luna* \ + | mpw* | magic* | mmixware* | mon960* | lnews* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ +diff --color -rN -u gcc-12.2.0/fixincludes/mkfixinc.sh build/gcc-12.2.0/fixincludes/mkfixinc.sh +--- a/gcc-12.2.0/fixincludes/mkfixinc.sh 2022-08-19 10:09:52.160657095 +0200 ++++ b/gcc-12.2.0/fixincludes/mkfixinc.sh 2022-10-02 11:27:45.662055397 +0200 +@@ -12,6 +12,8 @@ + # Check for special fix rules for particular targets + case $machine in + i?86-*-cygwin* | \ ++ *-luna* | \ ++ *-*-luna* | \ + i?86-*-mingw32* | \ + x86_64-*-mingw32* | \ + powerpc-*-eabisim* | \ +diff --color -rN -u gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel build/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel +--- a/dev/null 1970-01-01 01:00:00.000000000 +0100 ++++ b/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel 2022-10-02 11:45:30.955856133 +0200 +@@ -0,0 +1,4 @@ ++#Add libgcc multilib variant without red-zone requirement, for use in the kernel ++ ++MULTILIB_OPTIONS += mno-red-zone ++MULTILIB_DIRNAMES += no-red-zone +\ No newline at end of file +diff --color -rN -u gcc-12.2.0/gcc/config/luna.h build/gcc-12.2.0/gcc/config/luna.h +--- a/dev/null 1970-01-01 01:00:00.000000000 +0100 ++++ b/gcc-12.2.0/gcc/config/luna.h 2022-10-02 11:27:45.663055404 +0200 +@@ -0,0 +1,36 @@ ++#undef TARGET_LUNA ++#define TARGET_LUNA 1 ++ ++/* Default arguments you want when running your ++ i686-luna-gcc/x86_64-luna-gcc toolchain */ ++#undef LIB_SPEC ++#define LIB_SPEC "-lc" /* link against C standard library */ ++ ++/* Files that are linked before user code. ++ The %s tells GCC to look for these files in the library directory. */ ++#undef STARTFILE_SPEC ++#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s" ++ ++/* Files that are linked after user code. */ ++#undef ENDFILE_SPEC ++#define ENDFILE_SPEC "crtend.o%s crtn.o%s" ++ ++#undef SIZE_TYPE ++#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int") ++ ++/* Ensure that ptrdiff_t matches the actual pointer size */ ++#undef PTRDIFF_TYPE ++#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int") ++ ++/* Additional predefined macros. */ ++#undef TARGET_OS_CPP_BUILTINS ++#define TARGET_OS_CPP_BUILTINS() \ ++ do { \ ++ builtin_define("__luna__"); \ ++ builtin_define("__unix__"); \ ++ builtin_assert("system=luna"); \ ++ builtin_assert("system=unix"); \ ++ builtin_assert("system=posix"); \ ++ } while (0); ++ ++#undef LINK_SPEC ++#define LINK_SPEC "-z max-page-size=4096" +\ No newline at end of file +diff --color -rN -u gcc-12.2.0/gcc/config.gcc build/gcc-12.2.0/gcc/config.gcc +--- a/gcc-12.2.0/gcc/config.gcc 2022-08-19 10:09:52.552662114 +0200 ++++ b/gcc-12.2.0/gcc/config.gcc 2022-10-02 11:45:18.311797546 +0200 +@@ -895,6 +895,12 @@ + ;; + esac + ;; ++*-*-luna*) ++ gas=yes ++ gnu_ld=yes ++ default_use_cxa_atexit=yes ++ use_gcc_stdint=provide ++ ;; + *-*-netbsd*) + tm_p_file="${tm_p_file} netbsd-protos.h" + tmake_file="t-netbsd t-slibgcc" +@@ -1901,6 +1907,13 @@ + x86_64-*-elf*) + tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h" + ;; ++i[34567]86-*-luna*) ++ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h luna.h" ++ ;; ++x86_64-*-luna*) ++ tmake_file="${tmake_file} i386/x86_64-luna-kernel" ++ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h luna.h" ++ ;; + x86_64-*-rtems*) + tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rtemself.h rtems.h" + ;; +diff --color -rN -u gcc-12.2.0/libgcc/config.host build/gcc-12.2.0/libgcc/config.host +--- a/gcc-12.2.0/libgcc/config.host 2022-08-19 10:09:54.664689148 +0200 ++++ b/gcc-12.2.0/libgcc/config.host 2022-10-02 11:27:45.671055461 +0200 +@@ -783,6 +783,14 @@ + ;; + i[34567]86-*-lynxos*) + ;; ++i[34567]86-*-luna*) ++ extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o" ++ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic" ++ ;; ++x86_64-*-luna*) ++ extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o" ++ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic" ++ ;; + i[34567]86-*-nto-qnx*) + tmake_file="$tmake_file i386/t-nto t-libgcc-pic" + extra_parts=crtbegin.o +diff --color -rN -u gcc-12.2.0/libgcc/libgcov.h build/gcc-12.2.0/libgcc/libgcov.h +--- a/gcc-12.2.0/libgcc/libgcov.h 2022-08-19 10:09:54.728689966 +0200 ++++ b/gcc-12.2.0/libgcc/libgcov.h 2022-10-02 11:41:48.571807335 +0200 +@@ -194,6 +194,7 @@ + #endif + + #include "gcov-io.h" ++#include + + /* Structures embedded in coveraged program. The structures generated + by write_profile must match these. */ diff --git a/tools/setup-binutils.sh b/tools/setup-binutils.sh index e7f59b03..e1b98559 100755 --- a/tools/setup-binutils.sh +++ b/tools/setup-binutils.sh @@ -24,7 +24,7 @@ echo Patching Binutils... cd toolchain -patch -u -i $LUNA_ROOT/tools/binutils.patch -p 1 -d build | filter-lines "binutils" "patch" +patch -u -i $LUNA_ROOT/tools/binutils.patch -p 1 -d build cd - @@ -39,12 +39,12 @@ unset CXX unset LD unset AR -../binutils-$LUNA_BINUTILS_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --disable-werror | filter-lines "binutils" "configure" +../binutils-$LUNA_BINUTILS_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --disable-werror echo Building Binutils... -make -j$(nproc) | filter-lines "binutils" "build" +make -j$(nproc) echo Installing Binutils... -make install | filter-lines "binutils" "install" \ No newline at end of file +make install diff --git a/tools/setup-env.sh b/tools/setup-env.sh index 1d3aa3d0..6e92d193 100755 --- a/tools/setup-env.sh +++ b/tools/setup-env.sh @@ -4,6 +4,6 @@ source $(dirname $0)/env.sh export LUNA_GCC_VERSION_REQUIRED=12.2.0 export LUNA_BINUTILS_VERSION_REQUIRED=2.38 -export BUILD_PREFIX=$LUNA_ROOT/toolchain/x86-64-luna +export BUILD_PREFIX=$LUNA_ROOT/toolchain/x86_64-luna export BUILD_TARGET=x86_64-luna -export BUILD_SYSROOT=$LUNA_ROOT/base \ No newline at end of file +export BUILD_SYSROOT=$LUNA_ROOT/base diff --git a/tools/setup-gcc.sh b/tools/setup-gcc.sh index 844509bf..94500386 100755 --- a/tools/setup-gcc.sh +++ b/tools/setup-gcc.sh @@ -32,7 +32,7 @@ echo Patching GCC... cd toolchain -patch -u -i $LUNA_ROOT/tools/gcc.patch -p 1 -d build | filter-lines "gcc" "patch" +patch -u -i $LUNA_ROOT/tools/gcc.patch -p 1 -d build cd - @@ -47,23 +47,14 @@ unset CXX unset LD unset AR -../gcc-$LUNA_GCC_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --enable-languages=c,c++ --without-headers | filter-lines "gcc" "configure" +../gcc-$LUNA_GCC_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --enable-languages=c,c++ --without-headers echo Building GCC... -make all-gcc -j$(nproc) | filter-lines "gcc" "build" -make all-target-libgcc -j$(nproc) CFLAGS_FOR_TARGET='-g -O2 -mcmodel=large -mno-red-zone' | filter-lines "libgcc" "build" +make all-gcc -j$(nproc) +make all-target-libgcc -j$(nproc) CFLAGS_FOR_TARGET='-g -O2 -mcmodel=large -mno-red-zone' echo Installing GCC... -make install-gcc | filter-lines "gcc" "install" -make install-target-libgcc | filter-lines "libgcc" "install" - -echo Building libstdc++... - -$LUNA_ROOT/tools/sync-libc.sh # libstdc++ needs libc to be built -make all-target-libstdc++-v3 CXXFLAGS_FOR_TARGET="-fno-exceptions" -j$(nproc) | filter-lines "libstdc++" "build" - -echo Installing libstdc++... - -make install-target-libstdc++-v3 | filter-lines "libstdc++" "install" \ No newline at end of file +make install-gcc +make install-target-libgcc From bdfe7dac17ece66fc74ddf4eed20b8a9042717f1 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 17:59:54 +0100 Subject: [PATCH 382/407] libc: Remove crti.o and crtn.o Looks like these are now provided by the compiler. --- libc/CMakeLists.txt | 14 +------------- libc/src/arch/x86_64/crti.S | 13 ------------- libc/src/arch/x86_64/crtn.S | 9 --------- 3 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 libc/src/arch/x86_64/crti.S delete mode 100644 libc/src/arch/x86_64/crtn.S diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index da64b048..cb407399 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -22,18 +22,6 @@ add_custom_command( COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crt0.o ) -add_library(crti STATIC src/arch/${ARCH}/crti.S) -add_custom_command( - TARGET crti - COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crti.o -) - -add_library(crtn STATIC src/arch/${ARCH}/crtn.S) -add_custom_command( - TARGET crtn - COMMAND "${CMAKE_COMMAND}" -E copy $ ${LUNA_BASE}/usr/lib/crtn.o -) - add_library(bare_libc STATIC ${SOURCES}) target_link_libraries(bare_libc PUBLIC luna) @@ -52,7 +40,7 @@ add_custom_target(libc COMMAND ${CMAKE_AR} -rcs ${CMAKE_CURRENT_BINARY_DIR}/libc.a *.o COMMAND rm *.o WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS bare_libc luna crti crtn crt0 + DEPENDS bare_libc luna crt0 ) add_custom_command( diff --git a/libc/src/arch/x86_64/crti.S b/libc/src/arch/x86_64/crti.S deleted file mode 100644 index 03ad2f91..00000000 --- a/libc/src/arch/x86_64/crti.S +++ /dev/null @@ -1,13 +0,0 @@ -.section .init -.global _init -_init: - push %rbp - movq %rsp, %rbp - /* gcc will nicely put the contents of crtbegin.o's .init section here. */ - -.section .fini -.global _fini -_fini: - push %rbp - movq %rsp, %rbp - /* gcc will nicely put the contents of crtbegin.o's .fini section here. */ diff --git a/libc/src/arch/x86_64/crtn.S b/libc/src/arch/x86_64/crtn.S deleted file mode 100644 index 762c7f6c..00000000 --- a/libc/src/arch/x86_64/crtn.S +++ /dev/null @@ -1,9 +0,0 @@ -.section .init - /* gcc will nicely put the contents of crtend.o's .init section here. */ - popq %rbp - ret - -.section .fini - /* gcc will nicely put the contents of crtend.o's .fini section here. */ - popq %rbp - ret From 83651b4b904bb14e360590cb22c6ec1ef6668b77 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 18:59:59 +0100 Subject: [PATCH 383/407] CMake: Respect the ARCH env variable --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d4e5b69..78c72f8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ set(LUNA_BASE ${CMAKE_CURRENT_LIST_DIR}/base) set(ARCH $ENV{ARCH}) -if(NOT DEFINED $ENV{ARCH}) +if(NOT DEFINED ARCH) set(ARCH "x86_64") endif() From 0a472000beefa99da06d88442dbfa281f37b9687 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 19:00:32 +0100 Subject: [PATCH 384/407] Fix CI by providing a host C++ compiler --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 2636d74a..6853c6de 100644 --- a/.drone.yml +++ b/.drone.yml @@ -11,7 +11,7 @@ steps: image: ubuntu commands: - apt update - - apt install cmake ninja-build wget nasm -y + - apt install build-essential cmake ninja-build wget nasm -y - wget https://pub.cloudapio.eu/luna/toolchains/ci-toolchain-arm64.tar.gz --quiet - tar xf ci-toolchain-arm64.tar.gz - rm ci-toolchain-arm64.tar.gz From 65d2f1c04179f67be19425986f5c7abd82c2edf3 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 19:03:35 +0100 Subject: [PATCH 385/407] Update c_cpp_properties.json --- .vscode/c_cpp_properties.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index c40fe288..19a1cc12 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -6,7 +6,11 @@ "cStandard": "c17", "cppStandard": "c++20", "intelliSenseMode": "gcc-x64", - "configurationProvider": "ms-vscode.cmake-tools" + "configurationProvider": "ms-vscode.cmake-tools", + "includePath": [ + "${default}", + "${workspaceFolder}/base/usr/include" + ] } ], "version": 4 From 50509baea6cd8372eaaaf583ccd71211849b78fb Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 19:06:47 +0100 Subject: [PATCH 386/407] More c_cpp_properties.json --- .vscode/c_cpp_properties.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 19a1cc12..6f53357b 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -9,7 +9,8 @@ "configurationProvider": "ms-vscode.cmake-tools", "includePath": [ "${default}", - "${workspaceFolder}/base/usr/include" + "${workspaceFolder}/base/usr/include", + "${workspaceFolder}/libc/include" ] } ], From c3653cd4e6de49d21b6ba6ab83b8db6291abc06f Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 19:40:25 +0100 Subject: [PATCH 387/407] More stdlib.h implementation + commenting + atexit() --- apps/app.c | 9 ++++- libc/CMakeLists.txt | 1 + libc/include/stdlib.h | 52 ++++++++++++++++++++++------ libc/src/atexit.cpp | 28 +++++++++++++++ libc/src/stdlib.cpp | 80 ++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 155 insertions(+), 15 deletions(-) create mode 100644 libc/src/atexit.cpp diff --git a/apps/app.c b/apps/app.c index 4f1419f1..30759530 100644 --- a/apps/app.c +++ b/apps/app.c @@ -1,9 +1,16 @@ #include #include +void bye() +{ + console_print("byeee!\n"); +} + int main() { - for (int i = 0; i < strtol("010", NULL, 0); i++) { console_print("."); } + atexit(bye); + + for (int i = 0; i < atoi("8"); i++) { console_print("."); } console_print("\n"); } diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index cb407399..331380c0 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES src/unistd.cpp src/errno.cpp src/string.cpp + src/atexit.cpp ) if(${ARCH} STREQUAL "x86_64") diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 7e6a0f56..736c2f93 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -1,21 +1,26 @@ +/* stdlib.h: General utilities header. */ + #ifndef _STDLIB_H #define _STDLIB_H #include #include +/* The result of a division operation on two integers. */ typedef struct { int quot; int rem; } div_t; +/* The result of a division operation on two long integers. */ typedef struct { long quot; long rem; } ldiv_t; +/* The result of a division operation on two long long integers. */ typedef struct { long long quot; @@ -27,12 +32,22 @@ extern "C" { #endif - int abs(int); - long labs(long); - long long llabs(long long); + /* Returns the absolute value of v. */ + int abs(int v); - div_t div(int, int); + /* Returns the absolute value of v. */ + long labs(long v); + + /* Returns the absolute value of v. */ + long long llabs(long long v); + + /* Returns the result of dividing num by den, including the remainder. */ + div_t div(int num, int den); + + /* Returns the result of dividing num by den, including the remainder. */ ldiv_t ldiv(long, long); + + /* Returns the result of dividing num by den, including the remainder. */ lldiv_t lldiv(long long, long long); void* malloc(size_t); @@ -40,25 +55,42 @@ extern "C" void* realloc(void*, size_t); void free(void*); + /* Aborts the program without performing any normal cleanup. */ __noreturn void abort(); - int atexit(void (*)(void)); - int atoi(const char*); - long atol(const char*); - long long atoll(const char*); + /* Registers a handler to be run at normal program termination. */ + int atexit(void (*func)(void)); + + /* Parses a decimal integer from the provided string. */ + int atoi(const char* s); + + /* Parses a decimal integer from the provided string. */ + long atol(const char* s); + + /* Parses a decimal integer from the provided string. */ + long long atoll(const char* s); double atof(const char*); double strtod(const char*, char**); - long strtol(const char*, char**, int); - unsigned long strtoul(const char*, char**, int); + /* Parses an integer of the specified base from the string str, storing the first non-number character in endptr if + * nonnull. */ + long strtol(const char* str, char** endptr, int base); + + /* Parses an unsigned integer of the specified base from the string str, storing the first non-number character in + * endptr if nonnull. */ + unsigned long strtoul(const char* str, char** endptr, int base); int rand(); void srand(int); + /* Exits the program normally, performing any registered cleanup actions. */ __noreturn void exit(int); + /* Exits the program abnormally, without performing any registered cleanup actions. */ + __noreturn void _Exit(int); + int system(const char*); char* getenv(const char*); diff --git a/libc/src/atexit.cpp b/libc/src/atexit.cpp new file mode 100644 index 00000000..94f86e08 --- /dev/null +++ b/libc/src/atexit.cpp @@ -0,0 +1,28 @@ +#include + +typedef void (*atexit_func_t)(void); + +const int ATEXIT_MAX_FUNCS = 48; + +int atexit_registered_funcs = 0; + +atexit_func_t atexit_funcs[ATEXIT_MAX_FUNCS]; + +extern "C" +{ + int atexit(atexit_func_t func) + { + if (atexit_registered_funcs == ATEXIT_MAX_FUNCS) return -1; + + atexit_funcs[atexit_registered_funcs++] = func; + + return 0; + } + + __noreturn void exit(int status) + { + while (atexit_registered_funcs--) { atexit_funcs[atexit_registered_funcs](); } + + _Exit(status); + } +} diff --git a/libc/src/stdlib.cpp b/libc/src/stdlib.cpp index 87fb244d..12f338a4 100644 --- a/libc/src/stdlib.cpp +++ b/libc/src/stdlib.cpp @@ -1,19 +1,91 @@ +#include #include #include #include #include +template static inline ResultT __generic_div(ArgT a, ArgT b) +{ + ResultT result; + result.quot = a / b; + result.rem = a % b; + + if (a >= 0 && result.rem < 0) + { + result.quot++; + result.rem -= b; + } + + return result; +} + extern "C" { - // FIXME: Check for overflow in both strtol() and strtoul(). + int abs(int v) + { + return __builtin_abs(v); + } + + long labs(long v) + { + return __builtin_labs(v); + } + + long long llabs(long long v) + { + return __builtin_llabs(v); + } + + div_t div(int num, int den) + { + return __generic_div(num, den); + } + + ldiv_t ldiv(long num, long den) + { + return __generic_div(num, den); + } + + lldiv_t lldiv(long long num, long long den) + { + return __generic_div(num, den); + } + + int atoi(const char* s) + { + return (int)strtol(s, NULL, 10); + } + + long atol(const char* s) + { + return strtol(s, NULL, 10); + } + + // Assuming LP64, long long == long. + long long atoll(const char* s) + { + return (long long)strtol(s, NULL, 10); + } + + // These checks are only necessary on LLP64 platforms, where long won't match size_t/ssize_t. Probably redundant + // then (since Luna follows the regular LP64 model), but oh well... long strtol(const char* str, char** endptr, int base) { - return (long)parse_signed_integer(str, const_cast(endptr), base); + isize rc = parse_signed_integer(str, const_cast(endptr), base); + + if (rc > (isize)LONG_MAX) return LONG_MAX; + if (rc < (isize)LONG_MIN) return LONG_MIN; + + return rc; } unsigned long strtoul(const char* str, char** endptr, int base) { - return (unsigned long)parse_unsigned_integer(str, const_cast(endptr), base); + usize rc = parse_unsigned_integer(str, const_cast(endptr), base); + + if (rc > (usize)ULONG_MAX) return ULONG_MAX; + + return rc; } __noreturn void abort() @@ -22,7 +94,7 @@ extern "C" __builtin_unreachable(); } - __noreturn void exit(int) + __noreturn void _Exit(int) { syscall(SYS_exit); __builtin_unreachable(); From 367a2ce5216f7c45638736c65986add05273e645 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 20:02:07 +0100 Subject: [PATCH 388/407] libc: header documentation for supported functions --- libc/include/errno.h | 3 +++ libc/include/stdio.h | 5 ++++- libc/include/stdlib.h | 30 +++++++++++++++--------------- libc/include/string.h | 20 ++++++++++++++++++++ libc/include/unistd.h | 8 +++++++- 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/libc/include/errno.h b/libc/include/errno.h index 5ffee032..fa751e89 100644 --- a/libc/include/errno.h +++ b/libc/include/errno.h @@ -1,6 +1,9 @@ +/* errno.h: Error management header. */ + #ifndef _ERRNO_H #define _ERRNO_H +/* The last error encountered after a call to a system or library function. */ extern int errno; #include diff --git a/libc/include/stdio.h b/libc/include/stdio.h index 422efb68..f99fc754 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -1,3 +1,5 @@ +/* stdio.h: Standard input/output header. */ + #ifndef _STDIO_H #define _STDIO_H @@ -36,7 +38,8 @@ extern "C" int vfprintf(FILE*, const char*, va_list); int sprintf(char*, const char*, ...); - int console_print(const char*); + /* Output a message to the console. */ + int console_print(const char* msg); #ifdef __cplusplus } diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 736c2f93..38cb7095 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -32,22 +32,22 @@ extern "C" { #endif - /* Returns the absolute value of v. */ + /* Return the absolute value of an integer. */ int abs(int v); - /* Returns the absolute value of v. */ + /* Return the absolute value of a long integer. */ long labs(long v); - /* Returns the absolute value of v. */ + /* Return the absolute value of a long long integer. */ long long llabs(long long v); - /* Returns the result of dividing num by den, including the remainder. */ + /* Return the result of dividing two integers, including the remainder. */ div_t div(int num, int den); - /* Returns the result of dividing num by den, including the remainder. */ + /* Return the result of dividing two long integers, including the remainder. */ ldiv_t ldiv(long, long); - /* Returns the result of dividing num by den, including the remainder. */ + /* Return the result of dividing two long long integers, including the remainder. */ lldiv_t lldiv(long long, long long); void* malloc(size_t); @@ -55,40 +55,40 @@ extern "C" void* realloc(void*, size_t); void free(void*); - /* Aborts the program without performing any normal cleanup. */ + /* Abort the program without performing any normal cleanup. */ __noreturn void abort(); - /* Registers a handler to be run at normal program termination. */ + /* Register a handler to be run at normal program termination. */ int atexit(void (*func)(void)); - /* Parses a decimal integer from the provided string. */ + /* Parse a decimal integer from the a string. */ int atoi(const char* s); - /* Parses a decimal integer from the provided string. */ + /* Parse a decimal integer from the a string. */ long atol(const char* s); - /* Parses a decimal integer from the provided string. */ + /* Parse a decimal integer from the a string. */ long long atoll(const char* s); double atof(const char*); double strtod(const char*, char**); - /* Parses an integer of the specified base from the string str, storing the first non-number character in endptr if + /* Parse an integer of the specified base from a string, storing the first non-number character in endptr if * nonnull. */ long strtol(const char* str, char** endptr, int base); - /* Parses an unsigned integer of the specified base from the string str, storing the first non-number character in + /* Parse an unsigned integer of the specified base from a string, storing the first non-number character in * endptr if nonnull. */ unsigned long strtoul(const char* str, char** endptr, int base); int rand(); void srand(int); - /* Exits the program normally, performing any registered cleanup actions. */ + /* Exit the program normally, performing any registered cleanup actions. */ __noreturn void exit(int); - /* Exits the program abnormally, without performing any registered cleanup actions. */ + /* Exit the program abnormally, without performing any registered cleanup actions. */ __noreturn void _Exit(int); int system(const char*); diff --git a/libc/include/string.h b/libc/include/string.h index 7fd223ae..c2c59102 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -1,3 +1,5 @@ +/* string.h: String manipulation header. */ + #ifndef _STRING_H #define _STRING_H @@ -9,19 +11,37 @@ extern "C" { #endif + /* Copy n bytes of memory from src to dest. */ void* memcpy(void* dest, const void* src, size_t n); + + /* Set n bytes of memory to the character c. */ void* memset(void* buf, int c, size_t n); + + /* Compare n bytes of two memory locations. */ int memcmp(const void* a, const void* b, size_t n); + + /* Copy n bytes of memory from src to dest, where src and dest may overlap. */ void* memmove(void* dest, const void* src, size_t n); + + /* Return the length of a null-terminated string. */ size_t strlen(const char* str); + /* Compare two null-terminated strings. */ int strcmp(const char* a, const char* b); + + /* Copy the null-terminated string src into dest. Should be avoided to prevent buffer overflow attacks. */ __deprecated char* strcpy(char* dest, const char* src); + + /* Concatenate the null-terminated string src onto dest. Should be avoided to prevent buffer overflow attacks. */ __deprecated char* strcat(char* dest, const char* src); + + /* Return a pointer to the first occurrence of the character c in str, or NULL if it could not be found. */ char* strchr(const char* str, int c); + /* Return a heap-allocated copy of a string. */ char* strdup(const char* str); + /* Return the human-readable description of an error number. */ char* strerror(int errnum); #ifdef __cplusplus diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 46e904c2..218be84d 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -1,6 +1,11 @@ +/* unistd.h: POSIX constants and functions. */ + #ifndef _UNISTD_H #define _UNISTD_H +#define __need_NULL +#include + #include #include @@ -16,7 +21,8 @@ extern "C" int execve(const char*, char* const*, char* const*); int execvp(const char*, char* const*); - long syscall(long, ...); + /* Calls the operating system kernel for a specific service. */ + long syscall(long num, ...); #ifdef __cplusplus } From 80f5c790f85f649b87972dc4ff1c6d8182aa26b3 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 20:15:43 +0100 Subject: [PATCH 389/407] Implement string formatting into libc :) Of course, using makes it so simple. No need for duplicate code! --- apps/app.c | 5 +++++ libc/include/stdio.h | 13 ++++++++++++- libc/src/stdio.cpp | 36 ++++++++++++++++++++++++++++++++++++ luna/src/Alloc.cpp | 12 ++++++++++-- 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/apps/app.c b/apps/app.c index 30759530..9caf3a4d 100644 --- a/apps/app.c +++ b/apps/app.c @@ -10,6 +10,11 @@ int main() { atexit(bye); + char buffer[64]; + snprintf(buffer, sizeof(buffer), "Welcome to %s!\n", "Luna"); + + console_print(buffer); + for (int i = 0; i < atoi("8"); i++) { console_print("."); } console_print("\n"); diff --git a/libc/include/stdio.h b/libc/include/stdio.h index f99fc754..06b6216c 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -36,7 +36,18 @@ extern "C" int fprintf(FILE*, const char*, ...); int vfprintf(FILE*, const char*, va_list); - int sprintf(char*, const char*, ...); + + /* Write formatted output into a buffer. */ + int sprintf(char* buf, const char* format, ...); + + /* Write up to max bytes of formatted output into a buffer. */ + int snprintf(char* buf, size_t max, const char* format, ...); + + /* Write formatted output into a buffer. */ + int vsprintf(char*, const char*, va_list); + + /* Write up to max bytes of formatted output into a buffer. */ + int vsnprintf(char*, size_t, const char*, va_list); /* Output a message to the console. */ int console_print(const char* msg); diff --git a/libc/src/stdio.cpp b/libc/src/stdio.cpp index cecba48f..44788b06 100644 --- a/libc/src/stdio.cpp +++ b/libc/src/stdio.cpp @@ -1,4 +1,6 @@ +#define _LUNA_SYSTEM_ERROR_EXTENSIONS #include +#include #include #include #include @@ -12,4 +14,38 @@ extern "C" long rc = syscall(SYS_console_print, str); __errno_return(rc, int); } + + int vsnprintf(char* buf, size_t max, const char* format, va_list ap) + { + return (int)vstring_format(buf, max, format, ap); + } + + int snprintf(char* buf, size_t max, const char* format, ...) + { + va_list ap; + va_start(ap, format); + + int rc = vsnprintf(buf, max, format, ap); + + va_end(ap); + + return rc; + } + + int vsprintf(char* buf, const char* format, va_list ap) + { + return vsnprintf(buf, (size_t)-1, format, ap); + } + + int sprintf(char* buf, const char* format, ...) + { + va_list ap; + va_start(ap, format); + + int rc = vsnprintf(buf, (size_t)-1, format, ap); + + va_end(ap); + + return rc; + } } diff --git a/luna/src/Alloc.cpp b/luna/src/Alloc.cpp index 23f80e6c..65d8c609 100644 --- a/luna/src/Alloc.cpp +++ b/luna/src/Alloc.cpp @@ -10,7 +10,9 @@ char* const rc = new (std::nothrow) char[size]; return (void*)rc; #else - return malloc(size); + // return malloc(size); + (void)size; + return NULL; #endif } @@ -20,11 +22,17 @@ void raw_free(void* ptr) char* const arr = (char*)ptr; delete[] arr; #else - return free(ptr); + // return free(ptr); + (void)ptr; #endif } void operator delete(void* ptr, usize size, std::align_val_t) noexcept { +#ifdef USE_FREESTANDING operator delete(ptr, size); +#else + (void)ptr; + (void)size; +#endif } From 8891304509981af88d2b2c8870a3e3d7af51a134 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 20:48:08 +0100 Subject: [PATCH 390/407] libc: Add ctype.h --- libc/CMakeLists.txt | 1 + libc/include/ctype.h | 31 +++++++++++++++++++++++++++++++ libc/src/ctype.cpp | 31 +++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 libc/include/ctype.h create mode 100644 libc/src/ctype.cpp diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 331380c0..11823c69 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -8,6 +8,7 @@ set(SOURCES src/errno.cpp src/string.cpp src/atexit.cpp + src/ctype.cpp ) if(${ARCH} STREQUAL "x86_64") diff --git a/libc/include/ctype.h b/libc/include/ctype.h new file mode 100644 index 00000000..c5a96941 --- /dev/null +++ b/libc/include/ctype.h @@ -0,0 +1,31 @@ +/* ctype.h: Character handling functions. */ + +#ifndef _CTYPE_H +#define _CTYPE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + int isalnum(int c); + int isalpha(int c); + int isascii(int c); + int iscntrl(int c); + int isdigit(int c); + int isxdigit(int c); + int isspace(int c); + int ispunct(int c); + int isprint(int c); + int isgraph(int c); + int islower(int c); + int isupper(int c); + int isblank(int c); + int tolower(int c); + int toupper(int c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/src/ctype.cpp b/libc/src/ctype.cpp new file mode 100644 index 00000000..daec56d5 --- /dev/null +++ b/libc/src/ctype.cpp @@ -0,0 +1,31 @@ +#include +#include + +#define ctype_wrapper(a, b) \ + int a(int c) \ + { \ + return b(c); \ + } + +// clang-format off + +extern "C" +{ + ctype_wrapper(isalnum, _isalnum) + ctype_wrapper(isalpha, _isalpha) + ctype_wrapper(isascii, _isascii) + ctype_wrapper(iscntrl, _iscntrl) + ctype_wrapper(isdigit, _isdigit) + ctype_wrapper(isxdigit, _isxdigit) + ctype_wrapper(isspace, _isspace) + ctype_wrapper(ispunct, _ispunct) + ctype_wrapper(isprint, _isprint) + ctype_wrapper(isgraph, _isgraph) + ctype_wrapper(islower, _islower) + ctype_wrapper(isupper, _isupper) + ctype_wrapper(isblank, _isblank) + ctype_wrapper(tolower, _tolower) + ctype_wrapper(toupper, _toupper) +} + +// clang-format on From b851dcf9b90fb4dc49d2ced76857bfce9e67d9a4 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 6 Jan 2023 21:01:37 +0100 Subject: [PATCH 391/407] libc: Implement mbstowcs() using Utf8StringDecoder --- libc/include/stdlib.h | 5 +++++ libc/src/stdlib.cpp | 18 ++++++++++++++++++ luna/include/luna/Utf8.h | 4 ++++ luna/src/Utf8.cpp | 25 +++++++++++++++++++------ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 38cb7095..4e4b3e56 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -27,6 +27,8 @@ typedef struct long long rem; } lldiv_t; +#define MB_CUR_MAX 4 + #ifdef __cplusplus extern "C" { @@ -98,6 +100,9 @@ extern "C" void qsort(void*, size_t, size_t, int (*)(const void*, const void*)); void* bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*)); + /* Convert a multibyte character string to a wide character string. */ + size_t mbstowcs(wchar_t* buf, const char* src, size_t max); + #ifdef __cplusplus } #endif diff --git a/libc/src/stdlib.cpp b/libc/src/stdlib.cpp index 12f338a4..b84dda9c 100644 --- a/libc/src/stdlib.cpp +++ b/libc/src/stdlib.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -99,4 +100,21 @@ extern "C" syscall(SYS_exit); __builtin_unreachable(); } + + size_t mbstowcs(wchar_t* buf, const char* src, size_t max) + { + if (max == 0) return 0; + + Utf8StringDecoder decoder(src); + + auto rc = decoder.decode(buf, max); + + if (rc.has_error()) return (size_t)-1; + + size_t code_points = decoder.code_points().value_or(0); + + if (code_points >= max) return max - 1; + + return code_points; + } } diff --git a/luna/include/luna/Utf8.h b/luna/include/luna/Utf8.h index 280d29ed..2f5b1b45 100644 --- a/luna/include/luna/Utf8.h +++ b/luna/include/luna/Utf8.h @@ -18,6 +18,8 @@ class Utf8StringDecoder // The caller must ensure that 'buf' is at least code_points() + a NULL wide. Result decode(wchar_t* buf) const; + Result decode(wchar_t* buf, size_t max) const; + private: const char* m_str; usize m_byte_length; @@ -38,6 +40,8 @@ class Utf8StringEncoder // The caller must ensure that 'buf' is at least byte_length() + a NULL wide. Result encode(char* buf) const; + Result encode(char* buf, size_t max) const; + private: const wchar_t* m_str; usize m_code_points; diff --git a/luna/src/Utf8.cpp b/luna/src/Utf8.cpp index 3a84df36..5ebb880d 100644 --- a/luna/src/Utf8.cpp +++ b/luna/src/Utf8.cpp @@ -32,7 +32,9 @@ static inline usize wide_char_length_as_utf8_unchecked(wchar_t c) static Result encode_wide_char_as_utf8(wchar_t c, char* result, usize& len) { - len = TRY(wide_char_length_as_utf8(c)); + usize utf8_len = TRY(wide_char_length_as_utf8(c)); + + if (utf8_len > len) { return err(EILSEQ); } u8* buf = (u8*)result; @@ -144,11 +146,11 @@ Result Utf8StringDecoder::code_points() const return len; } -Result Utf8StringDecoder::decode(wchar_t* buf) const +Result Utf8StringDecoder::decode(wchar_t* buf, size_t max) const { const char* it = m_str; - while ((usize)(it - m_str) < m_byte_length) + while ((usize)(it - m_str) < m_byte_length && max--) { usize len = m_byte_length - (usize)(it - m_str); // Remaining space *buf = TRY(encode_utf8_as_wide_char(it, len)); @@ -161,6 +163,11 @@ Result Utf8StringDecoder::decode(wchar_t* buf) const return {}; } +Result Utf8StringDecoder::decode(wchar_t* buf) const +{ + return decode(buf, (size_t)-1); +} + Utf8StringEncoder::Utf8StringEncoder(const wchar_t* str) : m_str(str), m_code_points(wcslen(str)) { } @@ -179,15 +186,16 @@ Result Utf8StringEncoder::byte_length() const return len; } -Result Utf8StringEncoder::encode(char* buf) const +Result Utf8StringEncoder::encode(char* buf, size_t max) const { const wchar_t* it = m_str; - while (*it) + while (*it && max > 1) { - usize len = 0; + usize len = max - 1; TRY(encode_wide_char_as_utf8(*it, buf, len)); buf += len; + max -= len; it++; } @@ -196,6 +204,11 @@ Result Utf8StringEncoder::encode(char* buf) const return {}; } +Result Utf8StringEncoder::encode(char* buf) const +{ + return encode(buf, (size_t)-1); +} + Utf8StateDecoder::Utf8StateDecoder() : m_state_len(0), m_state_index(0) { } From 6e9b4491a6846703a113be1660fa98acfd09ee80 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 00:17:16 +0100 Subject: [PATCH 392/407] MemoryManager: Add copy_to_user() and copy_to_user_typed() --- kernel/src/memory/MemoryManager.cpp | 29 +++++++++++++++++++++++++++++ kernel/src/memory/MemoryManager.h | 7 +++++++ 2 files changed, 36 insertions(+) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 9a834af2..5c73c96a 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -364,6 +364,35 @@ namespace MemoryManager return true; } + bool copy_to_user(void* user, const void* kernel, usize size) + { + uintptr_t user_ptr = (uintptr_t)user; + uintptr_t user_page = align_down(user_ptr); + + const char* kernel_ptr = (const char*)kernel; + + // Userspace pointer not aligned on page boundary + if (user_ptr != user_page) + { + // FIXME: Validate that this page is writable by the user, not just the kernel. + if (!validate_writable_page(user_page)) return false; + } + + while (size--) + { + // Crossed a page boundary, gotta check the page tables again before touching any memory!! + if (user_ptr % ARCH_PAGE_SIZE) + { + if (!validate_writable_page(user_ptr)) return false; + } + + *(char*)user_ptr = *kernel_ptr++; + user_ptr++; + } + + return true; + } + usize free() { return free_mem; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index b2f72a84..6ce8d001 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -22,6 +22,13 @@ namespace MemoryManager bool validate_userspace_string(u64 address); + bool copy_to_user(void* user, const void* kernel, usize size); + + template bool copy_to_user_typed(T* user, const T* kernel) + { + return copy_to_user(user, kernel, sizeof(T)); + } + Result map_frames_at(u64 virt, u64 phys, usize count, int flags); Result alloc_at(u64 virt, usize count, int flags); From a8a64863c8ad3377fc7dbdf0d6ac17e4417b505c Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 00:21:08 +0100 Subject: [PATCH 393/407] kernel, libc: Add clock_gettime() --- apps/CMakeLists.txt | 1 + apps/app.c | 7 +++++++ kernel/CMakeLists.txt | 2 ++ kernel/src/arch/Timer.cpp | 1 + kernel/src/sys/clock_gettime.cpp | 34 ++++++++++++++++++++++++++++++++ libc/CMakeLists.txt | 3 ++- libc/include/bits/clockid.h | 12 +++++++++++ libc/include/bits/timespec.h | 12 +++++++++++ libc/include/sys/types.h | 2 ++ libc/include/time.h | 15 ++++++++++++++ libc/src/stdlib.cpp | 1 + libc/src/time.cpp | 13 ++++++++++++ luna/CMakeLists.txt | 2 +- luna/include/luna/Syscall.h | 2 +- 14 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 kernel/src/sys/clock_gettime.cpp create mode 100644 libc/include/bits/clockid.h create mode 100644 libc/include/bits/timespec.h create mode 100644 libc/src/time.cpp diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 4c4a143a..8f0cdef2 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,6 +1,7 @@ function(luna_app SOURCE_FILE APP_NAME) add_executable(${APP_NAME} ${SOURCE_FILE}) add_dependencies(${APP_NAME} libc) + target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include) install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin) endfunction() diff --git a/apps/app.c b/apps/app.c index 9caf3a4d..73a9dbff 100644 --- a/apps/app.c +++ b/apps/app.c @@ -1,5 +1,6 @@ #include #include +#include void bye() { @@ -15,6 +16,12 @@ int main() console_print(buffer); + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + snprintf(buffer, sizeof(buffer), "Realtime clock: %ld s, %ld ns\n", ts.tv_sec, ts.tv_nsec); + + console_print(buffer); + for (int i = 0; i < atoi("8"); i++) { console_print("."); } console_print("\n"); diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index d8498225..edaa76f0 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -18,6 +18,7 @@ set(SOURCES src/sys/Syscall.cpp src/sys/exit.cpp src/sys/console_print.cpp + src/sys/clock_gettime.cpp src/InitRD.cpp src/ELF.cpp ) @@ -78,6 +79,7 @@ target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x10 set_target_properties(moon PROPERTIES CXX_STANDARD 20) target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) +target_include_directories(moon PRIVATE ${LUNA_BASE}/usr/include) configure_file(src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/gen/config.h @ONLY) diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 6314427b..8df3c058 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -3,6 +3,7 @@ #include "arch/Serial.h" #include "boot/bootboot.h" +// FIXME: Storing these values as unsigned integers doesn't allow for pre-epoch times. static u64 timer_ticks = 0; static u64 boot_timestamp; diff --git a/kernel/src/sys/clock_gettime.cpp b/kernel/src/sys/clock_gettime.cpp new file mode 100644 index 00000000..d46a388d --- /dev/null +++ b/kernel/src/sys/clock_gettime.cpp @@ -0,0 +1,34 @@ +#include "arch/Timer.h" +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include +#include + +Result sys_clock_gettime(Registers*, SyscallArgs args) +{ + clockid_t id = (clockid_t)args[0]; + struct timespec* ts = (struct timespec*)args[1]; + + switch (id) + { + case CLOCK_MONOTONIC: { + usize ticks = Timer::ticks_ns(); + struct timespec kernel_ts; + kernel_ts.tv_sec = (time_t)(ticks / NS_PER_SECOND); + kernel_ts.tv_nsec = (long)(ticks % NS_PER_SECOND); + if (!MemoryManager::copy_to_user_typed(ts, &kernel_ts)) return err(EFAULT); + break; + } + case CLOCK_REALTIME: { + usize clock = Timer::clock_ns(); + struct timespec kernel_ts; + kernel_ts.tv_sec = (time_t)(clock / NS_PER_SECOND); + kernel_ts.tv_nsec = (long)(clock % NS_PER_SECOND); + if (!MemoryManager::copy_to_user_typed(ts, &kernel_ts)) return err(EFAULT); + break; + } + default: return err(EINVAL); + } + + return 0; +} diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 11823c69..270ecf41 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -9,6 +9,7 @@ set(SOURCES src/string.cpp src/atexit.cpp src/ctype.cpp + src/time.cpp ) if(${ARCH} STREQUAL "x86_64") @@ -30,7 +31,7 @@ target_link_libraries(bare_libc PUBLIC luna) target_include_directories(bare_libc PUBLIC include/) -target_compile_options(bare_libc PRIVATE -Wall -Wextra -Werror -pedantic -nostdlib) +target_compile_options(bare_libc PRIVATE -Wall -Wextra -Werror -pedantic -nostdlib -fno-exceptions -fno-rtti) target_link_options(bare_libc PRIVATE -nostdlib) diff --git a/libc/include/bits/clockid.h b/libc/include/bits/clockid.h new file mode 100644 index 00000000..110886fb --- /dev/null +++ b/libc/include/bits/clockid.h @@ -0,0 +1,12 @@ +#ifndef _BITS_CLOCKID_H +#define _BITS_CLOCKID_H + +typedef int clockid_t; + +enum __clockid +{ + CLOCK_REALTIME, + CLOCK_MONOTONIC +}; + +#endif diff --git a/libc/include/bits/timespec.h b/libc/include/bits/timespec.h new file mode 100644 index 00000000..c171d708 --- /dev/null +++ b/libc/include/bits/timespec.h @@ -0,0 +1,12 @@ +#ifndef _BITS_TIMESPEC_H +#define _BITS_TIMESPEC_H + +#include + +struct timespec +{ + time_t tv_sec; + long tv_nsec; +}; + +#endif diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h index 25b16927..e4768a32 100644 --- a/libc/include/sys/types.h +++ b/libc/include/sys/types.h @@ -6,4 +6,6 @@ typedef int pid_t; +typedef long time_t; + #endif diff --git a/libc/include/time.h b/libc/include/time.h index 4c01e32c..9a951da0 100644 --- a/libc/include/time.h +++ b/libc/include/time.h @@ -1,4 +1,19 @@ #ifndef _TIME_H #define _TIME_H +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Get the current value of a system clock. */ + int clock_gettime(clockid_t id, struct timespec* ts); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/libc/src/stdlib.cpp b/libc/src/stdlib.cpp index b84dda9c..d92a45bf 100644 --- a/libc/src/stdlib.cpp +++ b/libc/src/stdlib.cpp @@ -101,6 +101,7 @@ extern "C" __builtin_unreachable(); } + // FIXME: This is walking a UTF-8 string twice. Once to decode, and another to count code points. size_t mbstowcs(wchar_t* buf, const char* src, size_t max) { if (max == 0) return 0; diff --git a/libc/src/time.cpp b/libc/src/time.cpp new file mode 100644 index 00000000..aaa33f57 --- /dev/null +++ b/libc/src/time.cpp @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +extern "C" +{ + int clock_gettime(clockid_t id, struct timespec* ts) + { + long rc = syscall(SYS_clock_gettime, id, ts); + __errno_return(rc, int); + } +} diff --git a/luna/CMakeLists.txt b/luna/CMakeLists.txt index 9e301eb1..4fbc5114 100644 --- a/luna/CMakeLists.txt +++ b/luna/CMakeLists.txt @@ -41,7 +41,7 @@ target_compile_options(luna PRIVATE -Wall -Wextra -Werror -Wvla) target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) -target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20) +target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20 -fno-rtti -fno-exceptions) target_include_directories(luna PUBLIC include/) target_include_directories(luna PUBLIC ${LUNA_BASE}/usr/include) diff --git a/luna/include/luna/Syscall.h b/luna/include/luna/Syscall.h index 30551cfa..aeb98f95 100644 --- a/luna/include/luna/Syscall.h +++ b/luna/include/luna/Syscall.h @@ -1,6 +1,6 @@ #pragma once -#define enumerate_syscalls(_e) _e(exit) _e(console_print) +#define enumerate_syscalls(_e) _e(exit) _e(console_print) _e(clock_gettime) enum Syscalls { From 7fb2807d0c270fe15f9734cb9bb0b239f7df8975 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 00:27:23 +0100 Subject: [PATCH 394/407] libc: Implement time() using clock_gettime(). The cool POSIX kids use clock_gettime() now because it has NANOSECONDS (and different clocks!), but ANSI C prefers this function. We can still implement it based on clock_gettime(), we just have to discard the NANOSECONDS. --- apps/app.c | 5 ++--- libc/include/time.h | 3 +++ libc/src/time.cpp | 10 ++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/app.c b/apps/app.c index 73a9dbff..2e185b9b 100644 --- a/apps/app.c +++ b/apps/app.c @@ -16,9 +16,8 @@ int main() console_print(buffer); - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - snprintf(buffer, sizeof(buffer), "Realtime clock: %ld s, %ld ns\n", ts.tv_sec, ts.tv_nsec); + time_t now = time(NULL); + snprintf(buffer, sizeof(buffer), "Realtime clock: %ld s\n", now); console_print(buffer); diff --git a/libc/include/time.h b/libc/include/time.h index 9a951da0..82eb7884 100644 --- a/libc/include/time.h +++ b/libc/include/time.h @@ -12,6 +12,9 @@ extern "C" /* Get the current value of a system clock. */ int clock_gettime(clockid_t id, struct timespec* ts); + /* Get the current wall clock time. */ + time_t time(time_t* tp); + #ifdef __cplusplus } #endif diff --git a/libc/src/time.cpp b/libc/src/time.cpp index aaa33f57..b33a3c6c 100644 --- a/libc/src/time.cpp +++ b/libc/src/time.cpp @@ -10,4 +10,14 @@ extern "C" long rc = syscall(SYS_clock_gettime, id, ts); __errno_return(rc, int); } + + time_t time(time_t* tp) + { + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) < 0) return (time_t)-1; + + if (tp) *tp = ts.tv_sec; + + return ts.tv_sec; + } } From 29bd8a69fabdde1ee5077059dfbc1771f251001f Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 01:39:33 +0100 Subject: [PATCH 395/407] MemoryManager: Add helper functions to validate arbitrary ranges of userspace memory --- kernel/src/memory/MemoryManager.cpp | 61 ++++++++++++++++++++++++++--- kernel/src/memory/MemoryManager.h | 16 ++++++++ 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 5c73c96a..61eb24e4 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -347,23 +347,74 @@ namespace MemoryManager return false; } - // FIXME: Replace this with some kind of strdup_from_user() function. + bool validate_user_readable_page(u64 address) + { + auto rc = MMU::get_flags(address); + if (rc.has_error()) return false; + if (rc.value() & MMU::User) return true; + return false; + } + + bool validate_user_writable_page(u64 address) + { + auto rc = MMU::get_flags(address); + if (rc.has_error()) return false; + if ((rc.value() & MMU::User) && (rc.value() && MMU::ReadWrite)) return true; + return false; + } + bool validate_userspace_string(u64 address) { - if (!validate_readable_page(address)) return false; + if (!validate_user_readable_page(address)) return false; while (*(char*)address != 0) { address++; if (address % ARCH_PAGE_SIZE) { - if (!validate_readable_page(address)) return false; + if (!validate_user_readable_page(address)) return false; } } return true; } + bool validate_user_write(void* user, usize size) + { + uintptr_t user_ptr = (uintptr_t)user; + uintptr_t user_page = align_down(user_ptr); + + uintptr_t diff = user_ptr - user_page; + + usize pages = get_blocks_from_size(size + diff, ARCH_PAGE_SIZE); + + while (pages--) + { + if (!validate_user_writable_page(user_page)) return false; + user_page += ARCH_PAGE_SIZE; + } + + return true; + } + + bool validate_user_read(const void* user, usize size) + { + uintptr_t user_ptr = (uintptr_t)user; + uintptr_t user_page = align_down(user_ptr); + + uintptr_t diff = user_ptr - user_page; + + usize pages = get_blocks_from_size(size + diff, ARCH_PAGE_SIZE); + + while (pages--) + { + if (!validate_user_readable_page(user_page)) return false; + user_page += ARCH_PAGE_SIZE; + } + + return true; + } + bool copy_to_user(void* user, const void* kernel, usize size) { uintptr_t user_ptr = (uintptr_t)user; @@ -375,7 +426,7 @@ namespace MemoryManager if (user_ptr != user_page) { // FIXME: Validate that this page is writable by the user, not just the kernel. - if (!validate_writable_page(user_page)) return false; + if (!validate_user_writable_page(user_page)) return false; } while (size--) @@ -383,7 +434,7 @@ namespace MemoryManager // Crossed a page boundary, gotta check the page tables again before touching any memory!! if (user_ptr % ARCH_PAGE_SIZE) { - if (!validate_writable_page(user_ptr)) return false; + if (!validate_user_writable_page(user_ptr)) return false; } *(char*)user_ptr = *kernel_ptr++; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 6ce8d001..76bcf9e4 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -20,8 +20,24 @@ namespace MemoryManager bool validate_readable_page(u64 address); bool validate_writable_page(u64 address); + bool validate_user_readable_page(u64 address); + bool validate_user_writable_page(u64 address); + bool validate_userspace_string(u64 address); + bool validate_user_write(void* user, usize size); + bool validate_user_read(const void* user, usize size); + + template bool validate_user_write_typed(T* user) + { + return validate_user_write(user, sizeof(T)); + } + + template bool validate_user_read_typed(const T* user) + { + return validate_user_read(user, sizeof(T)); + } + bool copy_to_user(void* user, const void* kernel, usize size); template bool copy_to_user_typed(T* user, const T* kernel) From 7e377ef71271f1d99ddf2207cffdf06088d9f210 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 01:49:26 +0100 Subject: [PATCH 396/407] Implement printf() --- apps/app.c | 16 +++++----------- kernel/CMakeLists.txt | 2 +- kernel/src/sys/console_print.cpp | 12 ------------ kernel/src/sys/console_write.cpp | 15 +++++++++++++++ libc/include/stdio.h | 8 +++++++- libc/src/stdio.cpp | 26 ++++++++++++++++++++++++-- luna/include/luna/Syscall.h | 2 +- 7 files changed, 53 insertions(+), 28 deletions(-) delete mode 100644 kernel/src/sys/console_print.cpp create mode 100644 kernel/src/sys/console_write.cpp diff --git a/apps/app.c b/apps/app.c index 2e185b9b..f87ff701 100644 --- a/apps/app.c +++ b/apps/app.c @@ -4,24 +4,18 @@ void bye() { - console_print("byeee!\n"); + printf("byeee!\n"); } int main() { atexit(bye); - - char buffer[64]; - snprintf(buffer, sizeof(buffer), "Welcome to %s!\n", "Luna"); - - console_print(buffer); + printf("Welcome to %s!\n", "Luna"); time_t now = time(NULL); - snprintf(buffer, sizeof(buffer), "Realtime clock: %ld s\n", now); + printf("Realtime clock: %ld s\n", now); - console_print(buffer); + for (int i = 0; i < atoi("8"); i++) { console_write(".", 1); } - for (int i = 0; i < atoi("8"); i++) { console_print("."); } - - console_print("\n"); + console_write("\n", 1); } diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index edaa76f0..12840186 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -17,7 +17,7 @@ set(SOURCES src/thread/Scheduler.cpp src/sys/Syscall.cpp src/sys/exit.cpp - src/sys/console_print.cpp + src/sys/console_write.cpp src/sys/clock_gettime.cpp src/InitRD.cpp src/ELF.cpp diff --git a/kernel/src/sys/console_print.cpp b/kernel/src/sys/console_print.cpp deleted file mode 100644 index b112c5b2..00000000 --- a/kernel/src/sys/console_print.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "memory/MemoryManager.h" -#include "sys/Syscall.h" -#include "video/TextConsole.h" - -Result sys_console_print(Registers*, SyscallArgs args) -{ - if (!MemoryManager::validate_userspace_string(args[0])) return err(EFAULT); - - TextConsole::print((char*)args[0]); - - return { 0 }; -} diff --git a/kernel/src/sys/console_write.cpp b/kernel/src/sys/console_write.cpp new file mode 100644 index 00000000..4c00d560 --- /dev/null +++ b/kernel/src/sys/console_write.cpp @@ -0,0 +1,15 @@ +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include "video/TextConsole.h" + +Result sys_console_write(Registers*, SyscallArgs args) +{ + char* ptr = (char*)args[0]; + usize size = (usize)args[1]; + + if (!MemoryManager::validate_user_read(ptr, size)) return err(EFAULT); + + while (size--) { TextConsole::putchar(*ptr++); } + + return { 0 }; +} diff --git a/libc/include/stdio.h b/libc/include/stdio.h index 06b6216c..25d99540 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -49,8 +49,14 @@ extern "C" /* Write up to max bytes of formatted output into a buffer. */ int vsnprintf(char*, size_t, const char*, va_list); + /* Write formatted output to standard output. */ + int printf(const char*, ...); + + /* Write a string followed by a newline to standard output. */ + int puts(const char* s); + /* Output a message to the console. */ - int console_print(const char* msg); + int console_write(const char* msg, size_t size); #ifdef __cplusplus } diff --git a/libc/src/stdio.cpp b/libc/src/stdio.cpp index 44788b06..0d4102f0 100644 --- a/libc/src/stdio.cpp +++ b/libc/src/stdio.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -9,9 +10,9 @@ FILE* stderr = nullptr; extern "C" { - int console_print(const char* str) + int console_write(const char* str, size_t size) { - long rc = syscall(SYS_console_print, str); + long rc = syscall(SYS_console_write, str, size); __errno_return(rc, int); } @@ -48,4 +49,25 @@ extern "C" return rc; } + + int printf(const char* format, ...) + { + va_list ap; + va_start(ap, format); + + int rc = (int)pure_cstyle_format( + format, [](char c, void*) { console_write(&c, 1); }, nullptr, ap); + + va_end(ap); + + return rc; + } + + int puts(const char* s) + { + if (console_write(s, strlen(s)) < 0) return -1; + if (console_write("\n", 1) < 0) return -1; + + return 0; + } } diff --git a/luna/include/luna/Syscall.h b/luna/include/luna/Syscall.h index aeb98f95..2b36b2e9 100644 --- a/luna/include/luna/Syscall.h +++ b/luna/include/luna/Syscall.h @@ -1,6 +1,6 @@ #pragma once -#define enumerate_syscalls(_e) _e(exit) _e(console_print) _e(clock_gettime) +#define enumerate_syscalls(_e) _e(exit) _e(console_write) _e(clock_gettime) enum Syscalls { From b70bbc0ba6a4c511d5e843e388838d90975bcd60 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 11:21:53 +0100 Subject: [PATCH 397/407] More libc commenting --- libc/include/bits/attrs.h | 2 ++ libc/include/bits/clockid.h | 2 ++ libc/include/bits/errno-return.h | 2 ++ libc/include/bits/timespec.h | 2 ++ libc/include/sys/syscall.h | 3 +++ libc/include/sys/types.h | 2 ++ libc/include/time.h | 2 ++ 7 files changed, 15 insertions(+) diff --git a/libc/include/bits/attrs.h b/libc/include/bits/attrs.h index e8d28f34..c9f6cf58 100644 --- a/libc/include/bits/attrs.h +++ b/libc/include/bits/attrs.h @@ -1,3 +1,5 @@ +/* bits/attrs.h: Macros wrapping GCC attributes for use in the standard library. */ + #ifndef _BITS_ATTRS_H #define _BITS_ATTRS_H diff --git a/libc/include/bits/clockid.h b/libc/include/bits/clockid.h index 110886fb..f9827d6e 100644 --- a/libc/include/bits/clockid.h +++ b/libc/include/bits/clockid.h @@ -1,3 +1,5 @@ +/* bits/clockid.h: The clockid_t type and its supported values. */ + #ifndef _BITS_CLOCKID_H #define _BITS_CLOCKID_H diff --git a/libc/include/bits/errno-return.h b/libc/include/bits/errno-return.h index 2a147622..9d60c005 100644 --- a/libc/include/bits/errno-return.h +++ b/libc/include/bits/errno-return.h @@ -1,3 +1,5 @@ +/* bits/errno-return.h: Provides a convenient way of setting errno after a syscall. */ + #ifndef _BITS_ERRNO_RETURN_H #define _BITS_ERRNO_RETURN_H diff --git a/libc/include/bits/timespec.h b/libc/include/bits/timespec.h index c171d708..4b7afe42 100644 --- a/libc/include/bits/timespec.h +++ b/libc/include/bits/timespec.h @@ -1,3 +1,5 @@ +/* bits/timespec.h: Defines the timespec structure. */ + #ifndef _BITS_TIMESPEC_H #define _BITS_TIMESPEC_H diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index b7e75c17..683832f9 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -1,6 +1,9 @@ +/* sys/syscall.h: Defines syscall numbers. */ + #ifndef _SYS_SYSCALL_H #define _SYS_SYSCALL_H +/* This header just forwards to luna/Syscall.h, which is used in the kernel as well. */ #include #endif diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h index e4768a32..0f224f41 100644 --- a/libc/include/sys/types.h +++ b/libc/include/sys/types.h @@ -1,3 +1,5 @@ +/* sys/types.h: System data types. */ + #ifndef _SYS_TYPES_H #define _SYS_TYPES_H diff --git a/libc/include/time.h b/libc/include/time.h index 82eb7884..1698cd48 100644 --- a/libc/include/time.h +++ b/libc/include/time.h @@ -1,3 +1,5 @@ +/* time.h: Time management functions. */ + #ifndef _TIME_H #define _TIME_H From 12dc96b4a57105799ebf95b5aa609a9d233bac8a Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 11:31:08 +0100 Subject: [PATCH 398/407] Fix comment typo My bad :( --- libc/include/stdlib.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 4e4b3e56..8f8cbf07 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -63,13 +63,13 @@ extern "C" /* Register a handler to be run at normal program termination. */ int atexit(void (*func)(void)); - /* Parse a decimal integer from the a string. */ + /* Parse a decimal integer from a string. */ int atoi(const char* s); - /* Parse a decimal integer from the a string. */ + /* Parse a decimal integer from a string. */ long atol(const char* s); - /* Parse a decimal integer from the a string. */ + /* Parse a decimal integer from a string. */ long long atoll(const char* s); double atof(const char*); From 471103e4f3b029b10510a60b0ac9c230c0e14210 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 11:39:15 +0100 Subject: [PATCH 399/407] Remove the word 'header' from libc header descriptions --- libc/include/errno.h | 2 +- libc/include/stdio.h | 2 +- libc/include/stdlib.h | 2 +- libc/include/string.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libc/include/errno.h b/libc/include/errno.h index fa751e89..c5185e06 100644 --- a/libc/include/errno.h +++ b/libc/include/errno.h @@ -1,4 +1,4 @@ -/* errno.h: Error management header. */ +/* errno.h: Error management. */ #ifndef _ERRNO_H #define _ERRNO_H diff --git a/libc/include/stdio.h b/libc/include/stdio.h index 25d99540..3726a8ca 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -1,4 +1,4 @@ -/* stdio.h: Standard input/output header. */ +/* stdio.h: Standard input/output. */ #ifndef _STDIO_H #define _STDIO_H diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 8f8cbf07..fc63632d 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -1,4 +1,4 @@ -/* stdlib.h: General utilities header. */ +/* stdlib.h: General utilities. */ #ifndef _STDLIB_H #define _STDLIB_H diff --git a/libc/include/string.h b/libc/include/string.h index c2c59102..37a0f299 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -1,4 +1,4 @@ -/* string.h: String manipulation header. */ +/* string.h: String manipulation. */ #ifndef _STRING_H #define _STRING_H From 8ee634d19b88924fffd7fe6c15e9c09080744828 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 12:02:14 +0100 Subject: [PATCH 400/407] Kernel/Scheduler: Display addresses starting with 0x when creating threads --- kernel/src/thread/Scheduler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 11b8366a..851e7b47 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -33,7 +33,7 @@ namespace Scheduler g_idle.stack = idle_stack; - kinfoln("CREATED IDLE THREAD: id %lu with ip %lx and sp %lx", g_idle.id, g_idle.ip(), g_idle.sp()); + kinfoln("CREATED IDLE THREAD: id %lu with ip %#lx and sp %#lx", g_idle.id, g_idle.ip(), g_idle.sp()); g_current = &g_idle; } @@ -66,7 +66,7 @@ namespace Scheduler g_threads.append(thread); - kinfoln("CREATED THREAD: id %lu with ip %lx and sp %lx", thread->id, thread->ip(), thread->sp()); + kinfoln("CREATED THREAD: id %lu with ip %#lx and sp %#lx", thread->id, thread->ip(), thread->sp()); return {}; } @@ -148,7 +148,7 @@ namespace Scheduler guard.deactivate(); directory_guard.deactivate(); - kinfoln("CREATED USERSPACE THREAD: id %lu with ip %lx and sp %lx (ksp %lx)", thread->id, thread->ip(), + kinfoln("CREATED USERSPACE THREAD: id %lu with ip %#.16lx and sp %#.16lx (ksp %#lx)", thread->id, thread->ip(), thread->sp(), thread->kernel_stack.top()); g_threads.append(thread); From fde17272180fc72f4daf63bf457e3d5a16c7cb7f Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 12:33:00 +0100 Subject: [PATCH 401/407] KernelVM: Expand the available VM range --- kernel/src/memory/KernelVM.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/src/memory/KernelVM.cpp b/kernel/src/memory/KernelVM.cpp index 0c403f8d..8c9379df 100644 --- a/kernel/src/memory/KernelVM.cpp +++ b/kernel/src/memory/KernelVM.cpp @@ -3,11 +3,11 @@ #include "thread/Spinlock.h" #include -static const u64 KERNEL_VM_RANGE_START = 0xfffffffff0000000; +static const u64 KERNEL_VM_RANGE_START = 0xffffffffc0000000; static LockedValue g_kernelvm_bitmap; -static u8 bitmap_memory[4096]; +static u8 bitmap_memory[4096 * 7]; static const usize KERNEL_VM_RANGE_SIZE = (sizeof(bitmap_memory) * 8) * ARCH_PAGE_SIZE; From c97f588d440155e5ebf31775b210d27f38c570b1 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 20:53:23 +0100 Subject: [PATCH 402/407] Fix TRY() with Option --- luna/include/luna/Option.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/luna/include/luna/Option.h b/luna/include/luna/Option.h index d8ca65f2..db68653b 100644 --- a/luna/include/luna/Option.h +++ b/luna/include/luna/Option.h @@ -113,6 +113,8 @@ template class Option explicit ErrorHandle() { } + + friend class Option; }; Option(const ErrorHandle&) : m_has_value(false) From 0c73d69a7005941ddb47404cb412499f21bda33d Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 20:58:12 +0100 Subject: [PATCH 403/407] Kernel: Fix shadow 12GiB reserved entry when running QEMU without KVM on Fix inspired by: https://github.com/serenityos/serenity/pull/16345 --- README.md | 2 -- kernel/src/memory/MemoryMap.cpp | 12 +++++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6bf71a57..3691993a 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,6 @@ You can choose between 3 run scripts: `tools/debug.sh` will run Luna in QEMU with a port open for GDB to connect to. (run `tools/build-debug.sh`, `tools/gdb.sh`, and then `tools/debug.sh` in a separate terminal for an optimal debugging experience) -Beware that running without hardware acceleration does some weird stuff with the memory map, which is why I don't use it that often. - Essentially, since `run.sh` builds the toolchain if it hasn't been built, builds Luna if it hasn't been built, and runs it, you could just checkout this repo, run `run.sh`, and you're done. No need for the other scripts. Those are included for more fine-grained control/building step-by-step. You can pass any arguments you want to the run scripts, and those will be forwarded to QEMU. Example: `tools/run.sh -m 512M -net none -machine q35`. diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp index 9d9cdca1..3e67fd76 100644 --- a/kernel/src/memory/MemoryMap.cpp +++ b/kernel/src/memory/MemoryMap.cpp @@ -43,7 +43,17 @@ Option MemoryMapIterator::at(usize index) const Option MemoryMapIterator::next() { - return at(m_cur_ent++); + auto entry = TRY(at(m_cur_ent++)); + +#ifdef ARCH_X86_64 + // Workaround for https://gitlab.com/qemu-project/qemu/-/commit/8504f129450b909c88e199ca44facd35d38ba4de + // This invalid 12GiB reserved entry is made up by QEMU (doesn't appear on any real hardware), so we can simply + // ignore it and move on to the next entry. + if (entry.address() == 0x000000fd00000000 && entry.size() == (0x000000ffffffffff - 0x000000fd00000000) + 1) + return at(m_cur_ent++); +#endif + + return entry; } MemoryMapEntry MemoryMapIterator::largest_free() From 0c5a84f932227b6611e03708c15dd40b26fff558 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 21:23:01 +0100 Subject: [PATCH 404/407] toolchain: Update to binutils 2.39 CI will fail, it's normal. Wait for me to build a new toolchain for it. --- tools/binutils.patch | 38 +++++++++++++++++++------------------- tools/setup-binutils.sh | 2 +- tools/setup-env.sh | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tools/binutils.patch b/tools/binutils.patch index d375e06f..d262e7f8 100644 --- a/tools/binutils.patch +++ b/tools/binutils.patch @@ -1,6 +1,6 @@ -diff --color -rN -u binutils-2.38/bfd/config.bfd build/binutils-2.38/bfd/config.bfd ---- a/binutils-2.38/bfd/config.bfd 2022-01-22 13:14:07.000000000 +0100 -+++ b/binutils-2.38/bfd/config.bfd 2022-10-01 22:12:16.914033792 +0200 +diff --color -rN -u binutils-2.39/bfd/config.bfd build/binutils-2.39/bfd/config.bfd +--- a/binutils-2.39/bfd/config.bfd 2022-01-22 13:14:07.000000000 +0100 ++++ b/binutils-2.39/bfd/config.bfd 2022-10-01 22:12:16.914033792 +0200 @@ -651,6 +651,11 @@ targ_selvecs="iamcu_elf32_vec i386_pei_vec" targ64_selvecs="x86_64_elf64_vec x86_64_elf32_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec" @@ -25,9 +25,9 @@ diff --color -rN -u binutils-2.38/bfd/config.bfd build/binutils-2.38/bfd/config. x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin) targ_defvec=x86_64_pe_vec targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_big_vec x86_64_elf64_vec l1om_elf64_vec k1om_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec" -diff --color -rN -u binutils-2.38/gas/configure.tgt build/binutils-2.38/gas/configure.tgt ---- a/binutils-2.38/gas/configure.tgt 2022-01-22 13:14:08.000000000 +0100 -+++ b/binutils-2.38/gas/configure.tgt 2022-10-01 22:12:38.115093972 +0200 +diff --color -rN -u binutils-2.39/gas/configure.tgt build/binutils-2.39/gas/configure.tgt +--- a/binutils-2.39/gas/configure.tgt 2022-01-22 13:14:08.000000000 +0100 ++++ b/binutils-2.39/gas/configure.tgt 2022-10-01 22:12.39.115093972 +0200 @@ -238,6 +238,7 @@ x86_64*-linux-gnux32) arch=x86_64:32 ;; esac ;; @@ -36,9 +36,9 @@ diff --color -rN -u binutils-2.38/gas/configure.tgt build/binutils-2.38/gas/conf i386-*-redox*) fmt=elf ;; i386-*-solaris*) fmt=elf em=solaris ;; i386-*-freebsd* \ -diff --color -rN -u binutils-2.38/ld/configure.tgt build/binutils-2.38/ld/configure.tgt ---- a/binutils-2.38/ld/configure.tgt 2022-01-22 15:19:36.000000000 +0100 -+++ b/binutils-2.38/ld/configure.tgt 2022-10-01 22:15:04.853571062 +0200 +diff --color -rN -u binutils-2.39/ld/configure.tgt build/binutils-2.39/ld/configure.tgt +--- a/binutils-2.39/ld/configure.tgt 2022-01-22 15:19:36.000000000 +0100 ++++ b/binutils-2.39/ld/configure.tgt 2022-10-01 22:15:04.853571062 +0200 @@ -329,6 +329,11 @@ targ64_extra_emuls="elf_x86_64 elf32_x86_64 elf_l1om elf_k1om" targ64_extra_libpath="elf_x86_64 elf32_x86_64" @@ -62,24 +62,24 @@ diff --color -rN -u binutils-2.38/ld/configure.tgt build/binutils-2.38/ld/config x86_64-*-redox*) targ_emul=elf_x86_64 targ_extra_emuls=elf_i386 ;; -diff --color -rN -u binutils-2.38/ld/emulparams/elf_i386_luna.sh build/binutils-2.38/ld/emulparams/elf_i386_luna.sh +diff --color -rN -u binutils-2.39/ld/emulparams/elf_i386_luna.sh build/binutils-2.39/ld/emulparams/elf_i386_luna.sh --- a/dev/null 1970-01-01 01:00:00.000000000 +0100 -+++ b/binutils-2.38/ld/emulparams/elf_i386_luna.sh 2022-10-01 21:52:12.394068335 +0200 ++++ b/binutils-2.39/ld/emulparams/elf_i386_luna.sh 2022-10-01 21:52:12.394068335 +0200 @@ -0,0 +1,3 @@ +source_sh ${srcdir}/emulparams/elf_i386.sh +TEXT_START_ADDR=0x08000000 +MAXPAGESIZE=0x1000 \ No newline at end of file -diff --color -rN -u binutils-2.38/ld/emulparams/elf_x86_64_luna.sh build/binutils-2.38/ld/emulparams/elf_x86_64_luna.sh +diff --color -rN -u binutils-2.39/ld/emulparams/elf_x86_64_luna.sh build/binutils-2.39/ld/emulparams/elf_x86_64_luna.sh --- a/dev/null 1970-01-01 01:00:00.000000000 +0100 -+++ b/binutils-2.38/ld/emulparams/elf_x86_64_luna.sh 2022-10-01 21:53:00.411200592 +0200 ++++ b/binutils-2.39/ld/emulparams/elf_x86_64_luna.sh 2022-10-01 21:53:00.411200592 +0200 @@ -0,0 +1,2 @@ +source_sh ${srcdir}/emulparams/elf_x86_64.sh +MAXPAGESIZE=0x1000 \ No newline at end of file -diff --color -rN -u binutils-2.38/ld/Makefile.am build/binutils-2.38/ld/Makefile.am ---- a/binutils-2.38/ld/Makefile.am 2022-01-22 13:14:09.000000000 +0100 -+++ b/binutils-2.38/ld/Makefile.am 2022-10-01 22:18:02.660263017 +0200 +diff --color -rN -u binutils-2.39/ld/Makefile.am build/binutils-2.39/ld/Makefile.am +--- a/binutils-2.39/ld/Makefile.am 2022-01-22 13:14:09.000000000 +0100 ++++ b/binutils-2.39/ld/Makefile.am 2022-10-01 22:18:02.660263017 +0200 @@ -278,6 +278,7 @@ eelf32xtensa.c \ eelf32z80.c \ @@ -96,9 +96,9 @@ diff --color -rN -u binutils-2.38/ld/Makefile.am build/binutils-2.38/ld/Makefile ehppa64linux.c \ ei386pep.c \ emmo.c -diff --color -rN -u binutils-2.38/ld/Makefile.in build/binutils-2.38/ld/Makefile.in ---- a/binutils-2.38/ld/Makefile.in 2022-02-09 12:49:03.000000000 +0100 -+++ b/binutils-2.38/ld/Makefile.in 2022-10-01 22:17:46.740196925 +0200 +diff --color -rN -u binutils-2.39/ld/Makefile.in build/binutils-2.39/ld/Makefile.in +--- a/binutils-2.39/ld/Makefile.in 2022-02-09 12:49:03.000000000 +0100 ++++ b/binutils-2.39/ld/Makefile.in 2022-10-01 22:17:46.740196925 +0200 @@ -769,6 +769,7 @@ eelf32xtensa.c \ eelf32z80.c \ diff --git a/tools/setup-binutils.sh b/tools/setup-binutils.sh index e1b98559..8360520a 100755 --- a/tools/setup-binutils.sh +++ b/tools/setup-binutils.sh @@ -39,7 +39,7 @@ unset CXX unset LD unset AR -../binutils-$LUNA_BINUTILS_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --disable-werror +../binutils-$LUNA_BINUTILS_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --disable-werror --enable-warn-rwx-segments=no echo Building Binutils... diff --git a/tools/setup-env.sh b/tools/setup-env.sh index 6e92d193..13885c62 100755 --- a/tools/setup-env.sh +++ b/tools/setup-env.sh @@ -2,7 +2,7 @@ source $(dirname $0)/env.sh export LUNA_GCC_VERSION_REQUIRED=12.2.0 -export LUNA_BINUTILS_VERSION_REQUIRED=2.38 +export LUNA_BINUTILS_VERSION_REQUIRED=2.39 export BUILD_PREFIX=$LUNA_ROOT/toolchain/x86_64-luna export BUILD_TARGET=x86_64-luna From 8de59138effb046321f7b031f404aa6761bd9c55 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 7 Jan 2023 21:42:57 +0100 Subject: [PATCH 405/407] We are platform-agnostic now (kind of) Still tied to x86_64, but because there's no other platform implemented. Also making this commit just to test CI with the new toolchain. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3691993a..6ccdd111 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Luna -A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C. [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg?ref=refs/heads/restart)](https://drone.cloudapio.eu/apio/Luna) (rewrite, listed features are currently mostly from the old version) +A simple kernel and userspace for desktop computers, written mostly in C++ and C. [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg?ref=refs/heads/restart)](https://drone.cloudapio.eu/apio/Luna) (rewrite, listed features are currently mostly from the old version) ## Features - x86_64-compatible [kernel](kernel/). (Rewritten) From a620b00b18daf2830e926a2a1c0eb23c50bcde8c Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 8 Jan 2023 15:29:30 +0100 Subject: [PATCH 406/407] Unify libc header descriptions --- libc/include/bits/errno-return.h | 2 +- libc/include/bits/timespec.h | 2 +- libc/include/ctype.h | 2 +- libc/include/sys/syscall.h | 3 ++- libc/include/time.h | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libc/include/bits/errno-return.h b/libc/include/bits/errno-return.h index 9d60c005..aa8d9492 100644 --- a/libc/include/bits/errno-return.h +++ b/libc/include/bits/errno-return.h @@ -1,4 +1,4 @@ -/* bits/errno-return.h: Provides a convenient way of setting errno after a syscall. */ +/* bits/errno-return.h: A convenient way of setting errno after a syscall. */ #ifndef _BITS_ERRNO_RETURN_H #define _BITS_ERRNO_RETURN_H diff --git a/libc/include/bits/timespec.h b/libc/include/bits/timespec.h index 4b7afe42..a5866912 100644 --- a/libc/include/bits/timespec.h +++ b/libc/include/bits/timespec.h @@ -1,4 +1,4 @@ -/* bits/timespec.h: Defines the timespec structure. */ +/* bits/timespec.h: The timespec structure. */ #ifndef _BITS_TIMESPEC_H #define _BITS_TIMESPEC_H diff --git a/libc/include/ctype.h b/libc/include/ctype.h index c5a96941..8bcb16d9 100644 --- a/libc/include/ctype.h +++ b/libc/include/ctype.h @@ -1,4 +1,4 @@ -/* ctype.h: Character handling functions. */ +/* ctype.h: Character handling. */ #ifndef _CTYPE_H #define _CTYPE_H diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 683832f9..856bda76 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -1,9 +1,10 @@ -/* sys/syscall.h: Defines syscall numbers. */ +/* sys/syscall.h: Syscall constants. */ #ifndef _SYS_SYSCALL_H #define _SYS_SYSCALL_H /* This header just forwards to luna/Syscall.h, which is used in the kernel as well. */ #include +#undef enumerate_syscalls #endif diff --git a/libc/include/time.h b/libc/include/time.h index 1698cd48..27979f90 100644 --- a/libc/include/time.h +++ b/libc/include/time.h @@ -1,4 +1,4 @@ -/* time.h: Time management functions. */ +/* time.h: Time management. */ #ifndef _TIME_H #define _TIME_H From b0e5d02c9acfd5d3f9980712cf573d9a7e1a81bb Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 8 Jan 2023 15:32:59 +0100 Subject: [PATCH 407/407] kernel: Turn off console logging before starting the init process --- kernel/src/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index f9ba6a30..a70938cd 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -71,6 +71,9 @@ Result init() CPU::platform_finish_init(); + // Disable console logging before transferring control to userspace. + setup_log(log_debug_enabled(), log_serial_enabled(), false); + CPU::enable_interrupts(); return {};