diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 32 | ||||
-rw-r--r-- | compile_commands.json | 113 | ||||
-rw-r--r-- | kernel/amd64/io/com1.cxx | 44 | ||||
-rw-r--r-- | kernel/amd64/io/com1.h | 17 | ||||
-rw-r--r-- | kernel/amd64/io/ports.S | 24 | ||||
-rw-r--r-- | kernel/amd64/io/ports.h | 12 | ||||
-rw-r--r-- | kernel/entry.cxx | 23 | ||||
-rw-r--r-- | kernel/io/font.h | 15 | ||||
-rw-r--r-- | kernel/io/logger/base.cxx | 11 | ||||
-rw-r--r-- | kernel/io/logger/base.h | 31 | ||||
-rw-r--r-- | kernel/io/logger/base.ipp | 145 | ||||
-rw-r--r-- | kernel/io/psf2.h | 37 | ||||
-rw-r--r-- | kernel/io/tamsyn.psf | bin | 0 -> 4677 bytes | |||
-rw-r--r-- | kernel/utils.cxx | 27 | ||||
-rw-r--r-- | kernel/utils.h | 21 | ||||
-rw-r--r-- | version.h | 9 |
17 files changed, 554 insertions, 9 deletions
@@ -1,3 +1,4 @@ +.cache/ bin/ iso/ toolchain/ @@ -5,4 +6,5 @@ vendor/ *.iso *.o +*.d *.swp @@ -22,9 +22,21 @@ KERNEL := bin/core K_OBJS := \ kernel/entry.o \ kernel/cxx/constructors.o \ - kernel/cxx/icxxabi.o + kernel/cxx/icxxabi.o \ + kernel/utils.o \ + kernel/io/logger/base.o \ + kernel/amd64/io/com1.o +K_SRCS := $(patsubst %.o,%.cxx,$(K_OBJS)) +K_ASM_OBJS := \ + kernel/amd64/io/ports.o K_LINKSCRIPT := kernel/ldscript +CPPSTDDIRS := \ + vendor/x86_64-elf/include/c++/14.2.0 \ + vendor/x86_64-elf/include/c++/14.2.0/x86_64-elf \ + vendor/x86_64-elf/include/c++/14.2.0/backward +CPPSTD := $(addprefix -I ,$(CPPSTDDIRS)) + BINARIES := \ $(KERNEL) @@ -35,10 +47,11 @@ OVMF_ROOT := /usr/share/qemu all: hinterOS.iso run: - qemu-system-x86_64 --bios $(OVMF_ROOT)/ovmf-x86_64.bin -cdrom hinterOS.iso + qemu-system-x86_64 --serial stdio --bios $(OVMF_ROOT)/ovmf-x86_64.bin -cdrom hinterOS.iso clean: - find kernel -type f -name '*.o' -exec rm {} + + - find kernel -type f -name '*.d' -exec rm {} + - rm hinterOS.iso - rm $(BINARIES) @@ -59,10 +72,19 @@ hinterOS.iso: $(BINARIES) iso -o $@ vendor/limine/limine bios-install $@ -$(KERNEL): $(K_OBJS) +$(KERNEL): $(K_OBJS) $(K_ASM_OBJS) rm -rf bin mkdir -p bin - $(LD) -o $@ -T$(K_LINKSCRIPT) $^ + $(LD) -o $@ -T $(K_LINKSCRIPT) $^ + +.SECONDEXPANSION: +$(K_OBJS): %.o: %.cxx %.d + $(CC) -c $(CFLAGS) -MT $@ -MMD -MP -MF $(basename $<).d -I kernel $(CPPSTD) $< -o $@ -$(K_OBJS): %.o: %.cxx +$(K_ASM_OBJS): %.o: %.S $(CC) -c $(CFLAGS) $^ -o $@ + +DEPFILES := $(K_SRCS:%.cxx=%.d) +$(DEPFILES): + +-include $(wildcard $(DEPFILES)) diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..ad143de --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,113 @@ +[ + { + "arguments": [ + "vendor/bin/x86_64-elf-g++", + "-c", + "-g", + "-O2", + "-pipe", + "-Wall", + "-Wextra", + "-std=c++17", + "-ffreestanding", + "-mno-red-zone", + "-msoft-float", + "-mno-sse", + "-fno-stack-protector", + "-fno-stack-check", + "-fno-rtti", + "-fno-exceptions", + "-ffunction-sections", + "-fdata-sections", + "-mcmodel=kernel", + "-I", + "kernel", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0/x86_64-elf", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0/backward", + "-o", + "kernel/entry.o", + "kernel/entry.cxx" + ], + "directory": "/home/samuelj/Documents/repos/hinteros", + "file": "/home/samuelj/Documents/repos/hinteros/kernel/entry.cxx", + "output": "/home/samuelj/Documents/repos/hinteros/kernel/entry.o" + }, + { + "arguments": [ + "vendor/bin/x86_64-elf-g++", + "-c", + "-g", + "-O2", + "-pipe", + "-Wall", + "-Wextra", + "-std=c++17", + "-ffreestanding", + "-mno-red-zone", + "-msoft-float", + "-mno-sse", + "-fno-stack-protector", + "-fno-stack-check", + "-fno-rtti", + "-fno-exceptions", + "-ffunction-sections", + "-fdata-sections", + "-mcmodel=kernel", + "-I", + "kernel", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0/x86_64-elf", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0/backward", + "-o", + "kernel/cxx/constructors.o", + "kernel/cxx/constructors.cxx" + ], + "directory": "/home/samuelj/Documents/repos/hinteros", + "file": "/home/samuelj/Documents/repos/hinteros/kernel/cxx/constructors.cxx", + "output": "/home/samuelj/Documents/repos/hinteros/kernel/cxx/constructors.o" + }, + { + "arguments": [ + "vendor/bin/x86_64-elf-g++", + "-c", + "-g", + "-O2", + "-pipe", + "-Wall", + "-Wextra", + "-std=c++17", + "-ffreestanding", + "-mno-red-zone", + "-msoft-float", + "-mno-sse", + "-fno-stack-protector", + "-fno-stack-check", + "-fno-rtti", + "-fno-exceptions", + "-ffunction-sections", + "-fdata-sections", + "-mcmodel=kernel", + "-I", + "kernel", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0/x86_64-elf", + "-I", + "vendor/x86_64-elf/include/c++/14.2.0/backward", + "-o", + "kernel/cxx/icxxabi.o", + "kernel/cxx/icxxabi.cxx" + ], + "directory": "/home/samuelj/Documents/repos/hinteros", + "file": "/home/samuelj/Documents/repos/hinteros/kernel/cxx/icxxabi.cxx", + "output": "/home/samuelj/Documents/repos/hinteros/kernel/cxx/icxxabi.o" + } +] diff --git a/kernel/amd64/io/com1.cxx b/kernel/amd64/io/com1.cxx new file mode 100644 index 0000000..fc67b65 --- /dev/null +++ b/kernel/amd64/io/com1.cxx @@ -0,0 +1,44 @@ +#include <amd64/io/com1.h> +#include <amd64/io/ports.h> +#include <utils.h> + +#define COM1 0x3f8 + +int is_transmit_empty () +{ + return hos::io::inb(COM1 + 5) & 0x20; +} + +namespace hos::io +{ + com_logger::com_logger (enum log_level level) + : logger (level) + { + outb(COM1 + 1, 0x00); + outb(COM1 + 3, 0x80); + outb(COM1 + 0, 0x03); + outb(COM1 + 1, 0x00); + outb(COM1 + 3, 0x03); + outb(COM1 + 2, 0xc7); + outb(COM1 + 4, 0x0b); + outb(COM1 + 4, 0x1e); + outb(COM1 + 0, 0xae); + + if (inb(COM1 + 0) != 0xae) + { + return; + } + + outb(COM1 + 4, 0x0f); + } + + void com_logger::flush () + { + std::size_t len = strlen(this->buffer); + for (std::size_t i = 0; i < len; i++) + { + while (is_transmit_empty() == 0); + outb(COM1 + 0, this->buffer[i]); + } + } +} diff --git a/kernel/amd64/io/com1.h b/kernel/amd64/io/com1.h new file mode 100644 index 0000000..0ee04ac --- /dev/null +++ b/kernel/amd64/io/com1.h @@ -0,0 +1,17 @@ +#ifndef HOS_AMD64_IO_COM1_H +#define HOS_AMD64_IO_COM1_H + +#include <amd64/io/ports.h> +#include <io/logger/base.h> + +namespace hos::io +{ + class com_logger : public hos::io::logger<com_logger> + { + public: + com_logger (enum log_level level); + void flush (); + }; +} + +#endif diff --git a/kernel/amd64/io/ports.S b/kernel/amd64/io/ports.S new file mode 100644 index 0000000..37301a4 --- /dev/null +++ b/kernel/amd64/io/ports.S @@ -0,0 +1,24 @@ +.section .text +.global inb, outb + +inb: + push %rbp + mov %rsp, %rbp + sub $0x10, %rsp + mov %rdi, %rdx + xor %rax, %rax + in (%dx), %al + add $0x10, %rsp + pop %rbp + ret + +outb: + push %rbp + mov %rsp, %rbp + sub $0x10, %rsp + mov %rdi, %rdx + mov %rsi, %rax + out %al, (%dx) + add $0x10, %rsp + pop %rbp + ret diff --git a/kernel/amd64/io/ports.h b/kernel/amd64/io/ports.h new file mode 100644 index 0000000..6de2acb --- /dev/null +++ b/kernel/amd64/io/ports.h @@ -0,0 +1,12 @@ +#ifndef HOS_AMD64_IO_PORTS_H +#define HOS_AMD64_IO_PORTS_H + +#include <cstdint> + +namespace hos::io +{ + extern "C" std::uint8_t inb (std::uint16_t port); + extern "C" void outb (std::uint16_t port, std::uint8_t value); +} + +#endif diff --git a/kernel/entry.cxx b/kernel/entry.cxx index b5bc210..643fbc0 100644 --- a/kernel/entry.cxx +++ b/kernel/entry.cxx @@ -1,6 +1,15 @@ #include "../vendor/limine/limine.h" +#include "../version.h" + +#include <io/logger/base.h> #include <cstdint> +#if defined (__x86_64__) +#include <amd64/io/com1.h> +#endif + +using namespace hos::io; + __attribute__ ((used, section(".requests"))) static volatile LIMINE_BASE_REVISION(3); @@ -30,20 +39,26 @@ void init (void); extern "C" void _launch (void); void _launch (void) { + // Global C++ Constructors + init(); + + logger<com_logger> logger(log_level::DEBUG); + logger.write(log_level::INFO, "Welcome to HinterOS %s!", HOS_CORE_VERSION); + if (LIMINE_BASE_REVISION_SUPPORTED == false) { + logger.write(log_level::FATAL, "Limine revision mismatch."); hcf(); } + logger.write(log_level::DEBUG, "Limine... ok"); + struct limine_framebuffer *fb = framebuffer_request.response->framebuffers[0]; for (std::size_t i = 0; i < (fb->width - 1) * (fb->height - 1); i += 2) { volatile std::uint32_t *fbptr = static_cast<std::uint32_t *>(fb->address); - fbptr[i] = 0xffffff; + fbptr[i] = 0xffffff00; } - // Global C++ constructors - init(); - hcf(); } diff --git a/kernel/io/font.h b/kernel/io/font.h new file mode 100644 index 0000000..e4f72ca --- /dev/null +++ b/kernel/io/font.h @@ -0,0 +1,15 @@ +#ifndef HOS_IO_FONT_H +#define HOS_IO_FONT_H + +#include <cstdint> + +namespace hos::io +{ + class font + { + public: + virtual void write (unsigned char character, void *fb_addr, std::uint16_t bpp) = 0; + }; +} + +#endif diff --git a/kernel/io/logger/base.cxx b/kernel/io/logger/base.cxx new file mode 100644 index 0000000..bb1e3c4 --- /dev/null +++ b/kernel/io/logger/base.cxx @@ -0,0 +1,11 @@ +#include <io/logger/base.ipp> + +#if defined (__x86_64__) +#include <amd64/io/com1.h> + +namespace hos::io +{ + template class logger<com_logger>; +} + +#endif diff --git a/kernel/io/logger/base.h b/kernel/io/logger/base.h new file mode 100644 index 0000000..7aa9e2d --- /dev/null +++ b/kernel/io/logger/base.h @@ -0,0 +1,31 @@ +#ifndef HOS_IO_BASE_H +#define HOS_IO_BASE_H + +namespace hos::io +{ + enum log_level + { + DEBUG, + INFO, + WARN, + ERROR, + FATAL + }; + + /// Ah, the glorious CRTP... + template <typename concrete_logger> + class logger + { + public: + logger (enum log_level level); + + void set_level (enum log_level level); + void write (enum log_level level, const char *message, ...); + protected: + char buffer[512]; + private: + enum log_level level; + }; +} + +#endif diff --git a/kernel/io/logger/base.ipp b/kernel/io/logger/base.ipp new file mode 100644 index 0000000..b48a132 --- /dev/null +++ b/kernel/io/logger/base.ipp @@ -0,0 +1,145 @@ +#ifndef HOS_IO_BASE_IMPL +#define HOS_IO_BASE_IMPL + +#include <io/logger/base.h> +#include <utils.h> + +#include <stdarg.h> + +namespace hos::io +{ + template <typename concrete_logger> + logger<concrete_logger>::logger (enum log_level level) + { + this->set_level(level); + } + + template <typename concrete_logger> + void logger<concrete_logger>::set_level (enum log_level level) + { + this->level = level; + } + + template <typename concrete_logger> + void logger<concrete_logger>::write (enum log_level level, const char *message, ...) + { + if (level < this->level) + { + return; + } + + char *bufferptr = this->buffer; + memset(bufferptr, 0, sizeof(this->buffer)); + + const char *logtypes[] = { + "DEBUG: ", + "INFO: ", + "WARN: ", + "ERROR: ", + "FATAL: " + }; + + int len = 0; + switch (level) + { + case log_level::DEBUG: { + len = strlen(logtypes[0]); + + memcpy(bufferptr, logtypes[0], len); + bufferptr += len; + break; + } + case log_level::INFO: { + len = strlen(logtypes[1]); + + memcpy(bufferptr, logtypes[1], len); + bufferptr += len; + break; + } + case log_level::WARN: { + len = strlen(logtypes[2]); + + memcpy(bufferptr, logtypes[2], len); + bufferptr += len; + break; + } + case log_level::ERROR: { + len = strlen(logtypes[3]); + + memcpy(bufferptr, logtypes[3], len); + bufferptr += len; + break; + } + case log_level::FATAL: { + len = strlen(logtypes[4]); + + memcpy(bufferptr, logtypes[4], len); + bufferptr += len; + break; + } + } + + len = strlen(message); + if (bufferptr + len >= this->buffer + 510) { + const char failed[] = "LOGGER: Message longer than display buffer."; + memcpy(bufferptr, failed, strlen(failed)); + static_cast<concrete_logger*>(this)->flush(); + } + + va_list args; + va_start(args, message); + + char temp_buffer[this->buffer + 510 - bufferptr]; + char *tempptr = temp_buffer; + memset(tempptr, 0, sizeof(temp_buffer)); + + char next; + while ((next = *message++) != 0) + { + if (next == '%') + { + next = *message++; + switch (next) + { + case 'c': { + char c = va_arg(args, int); + + if (!((tempptr + 1) - temp_buffer > (long int) sizeof(temp_buffer))) + { + memcpy(tempptr, &c, 1); + tempptr++; + } + + break; + } + case 's': { + char *string = va_arg(args, char *); + + len = strlen(string); + if (!((tempptr + len) - temp_buffer > (long int) sizeof(temp_buffer))) + { + memcpy(tempptr, string, len); + tempptr += len; + } + + break; + } + } + } else { + memcpy(tempptr, &next, 1); + tempptr++; + } + } + + va_end(args); + + len = strlen(temp_buffer); + memcpy(bufferptr, temp_buffer, len); + bufferptr += len; + + memcpy(bufferptr, "\n", 1); + static_cast<concrete_logger*>(this)->flush(); + } +} + +#endif diff --git a/kernel/io/psf2.h b/kernel/io/psf2.h new file mode 100644 index 0000000..e8dda44 --- /dev/null +++ b/kernel/io/psf2.h @@ -0,0 +1,37 @@ +#ifndef HOS_IO_PSF2_H +#define HOS_IO_PSF2_H + +#include <cstdint> +#include <io/font.h> + +#define PSF2_MAGIC0 0x72 +#define PSF2_MAGIC1 0xb5 +#define PSF2_MAGIC2 0x4a +#define PSF2_MAGIC3 0x86 + +#define PSF2_HAS_UNICODE_TABLE 0x01 + +#define PSF2_SEPARATOR 0xff +#define PSF2_STARTSEQ 0xfe + +namespace hos::io +{ + class psf2 : public font + { + public: + psf2 (void *font_start_addr); + + void write (unsigned char character, void *fb_addr, std::uint16_t bpp); + private: + unsigned char magic[4]; + unsigned int version; + unsigned int header_size; + unsigned int flags; + unsigned int length; + unsigned int charsize; + unsigned int height; + unsigned int width; + }; +} + +#endif diff --git a/kernel/io/tamsyn.psf b/kernel/io/tamsyn.psf Binary files differnew file mode 100644 index 0000000..6fd82c1 --- /dev/null +++ b/kernel/io/tamsyn.psf diff --git a/kernel/utils.cxx b/kernel/utils.cxx new file mode 100644 index 0000000..8a131d1 --- /dev/null +++ b/kernel/utils.cxx @@ -0,0 +1,27 @@ +#include <utils.h> + +void *memset (void *bufferptr, int value, std::size_t size) +{ + unsigned char *buffer = (unsigned char *) bufferptr; + + for (std::size_t i = 0; i < size; i++) + { + buffer[i] = (unsigned char) value; + } + + return bufferptr; +} + +void *memcpy (void *destptr, const void *srcptr, std::size_t size) +{ + unsigned char *dest = (unsigned char *) destptr; + const unsigned char *src = (const unsigned char *) srcptr; + + for (std::size_t i = 0; i < size; i++) + { + dest[i] = src[i]; + } + + return destptr; +} + diff --git a/kernel/utils.h b/kernel/utils.h new file mode 100644 index 0000000..aaf342f --- /dev/null +++ b/kernel/utils.h @@ -0,0 +1,21 @@ +#ifndef HOS_UTILS_H +#define HOS_UTILS_H + +#include <cstddef> + +void *memset (void *buffer, int value, std::size_t size); +void *memcpy (void *destptr, const void *srcptr, std::size_t size); + +constexpr std::size_t strlen (const char *in) +{ + std::size_t len = 0; + + while (in[len]) + { + len++; + } + + return len; +} + +#endif diff --git a/version.h b/version.h new file mode 100644 index 0000000..ffb2783 --- /dev/null +++ b/version.h @@ -0,0 +1,9 @@ +#ifndef HOS_SUITE_VERSION_H +#define HOS_SUITE_VERSION_H + +#define HOS_CORE_MAJOR "0" +#define HOS_CORE_MINOR "1" +#define HOS_CORE_PATCH "0" +#define HOS_CORE_VERSION HOS_CORE_MAJOR "." HOS_CORE_MINOR "." HOS_CORE_PATCH + +#endif |