aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-02-05 23:15:37 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-02-05 23:15:37 +0200
commit919ad9d1022edec7fdd97f74ef50de26dde6aebb (patch)
tree2787aa63255b0ba6c682e4547a2030e591a6a55e
parentRewrite boot.s to use clang instead of nasm (diff)
downloadkernel.cpp-919ad9d1022edec7fdd97f74ef50de26dde6aebb.tar.xz
Add IntegerView
-rw-r--r--.clang-format6
-rw-r--r--kernel.cc104
-rw-r--r--libk/makefile7
-rw-r--r--libk/stdlib.h31
-rw-r--r--libk/stdlib/console.cc8
-rw-r--r--libk/string.cc22
-rw-r--r--libk/string.h106
-rw-r--r--libk/type_traits.h12
-rw-r--r--libk/type_traits/test.cc17
-rw-r--r--libk/types.h1
-rw-r--r--makefile10
-rw-r--r--vga.cc41
-rw-r--r--vga.h10
13 files changed, 221 insertions, 154 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..ee8a219
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,6 @@
+---
+BasedOnStyle: Chromium
+ColumnLimit: '120'
+AccessModifierOffset: '-2'
+
+...
diff --git a/kernel.cc b/kernel.cc
index b2e2b01..3045374 100644
--- a/kernel.cc
+++ b/kernel.cc
@@ -8,10 +8,10 @@
#error "This tutorial needs to be compiled with a ix86-elf compiler"
#endif
-#include "multiboot2.h"
-#include "vga.h"
#include <stdlib.h>
#include <types.h>
+#include "multiboot2.h"
+#include "vga.h"
extern "C" void kernel_main(uint32_t mb_magic, uint32_t mb_addr) {
VGA terminal;
@@ -19,69 +19,57 @@ extern "C" void kernel_main(uint32_t mb_magic, uint32_t mb_addr) {
printk("Hello, kernel World!\n");
- printk("multiboot magic: 0x", mb_magic,
- mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC ? " is valid" : " is invalid",
- '\n');
- printk("multiboot addr: 0x", mb_addr, '\n');
+ printk("multiboot magic: ", uhex{mb_magic}, mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC ? " valid" : " invalid", '\n');
+ printk("multiboot addr: ", uhex{mb_addr}, !(mb_addr & 7) ? " is aligned" : " is not aligned", '\n');
- if (mb_addr & 7) {
- printk("unaligned mbi\n");
- }
+ struct multiboot_tag* tag;
+ const uint32_t size = *(unsigned*)mb_addr;
+ printk("Announced mbi size ", size, '\n');
- struct multiboot_tag *tag;
- const uint32_t size = *(unsigned *)mb_addr;
- printk("Announced mbi size 0x", size, '\n');
+ for (tag = (struct multiboot_tag*)(mb_addr + 8); tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = (struct multiboot_tag*)((multiboot_uint8_t*)tag + ((tag->size + 7) & ~7))) {
+ switch (tag->type) {
+ case MULTIBOOT_TAG_TYPE_CMDLINE: {
+ auto* t = reinterpret_cast<multiboot_tag_string*>(tag);
+ printk("Command line = [", t->string, "]\n");
+ } break;
- for (tag = (struct multiboot_tag *)(mb_addr + 8);
- tag->type != MULTIBOOT_TAG_TYPE_END;
- tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag +
- ((tag->size + 7) & ~7))) {
+ case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: {
+ auto* t = reinterpret_cast<multiboot_tag_string*>(tag);
+ printk("Boot loader name = [", t->string, "]\n");
+ } break;
- switch (tag->type) {
- case MULTIBOOT_TAG_TYPE_CMDLINE:
- printk("Command line = [", ((struct multiboot_tag_string *)tag)->string,
- "]\n");
- break;
- case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
- printk("Boot loader name = [",
- ((struct multiboot_tag_string *)tag)->string, "]\n");
- break;
- case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
- printk("mem_lower = ",
- ((struct multiboot_tag_basic_meminfo *)tag)->mem_lower, "KB\n",
- "mem_upper = ",
- ((struct multiboot_tag_basic_meminfo *)tag)->mem_upper, "KB\n");
- break;
- case MULTIBOOT_TAG_TYPE_BOOTDEV:
- printk("Boot device 0x", ((struct multiboot_tag_bootdev *)tag)->biosdev,
- " slice ", ((struct multiboot_tag_bootdev *)tag)->slice, " part ",
- ((struct multiboot_tag_bootdev *)tag)->part, '\n');
- break;
- case MULTIBOOT_TAG_TYPE_MMAP: {
- multiboot_memory_map_t *mmap;
+ case MULTIBOOT_TAG_TYPE_BOOTDEV: {
+ auto* t = reinterpret_cast<multiboot_tag_bootdev*>(tag);
+ printk("Boot device ", uhex{t->biosdev}, " slice ", t->slice, " part ", t->part, '\n');
+ } break;
+
+ case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: {
+ auto* t = reinterpret_cast<multiboot_tag_basic_meminfo*>(tag);
+ printk("mem_lower = ", t->mem_lower, "KB\n", "mem_upper = ", t->mem_upper, "KB\n");
+ } break;
+
+ case MULTIBOOT_TAG_TYPE_MMAP: {
+ auto* t = reinterpret_cast<multiboot_tag_mmap*>(tag);
+ multiboot_memory_map_t* mmap;
- printk("mmap\n");
+ printk("memory map\n");
+ for (mmap = t->entries; (multiboot_uint8_t*)mmap < (multiboot_uint8_t*)tag + tag->size;
+ mmap = (multiboot_memory_map_t*)((unsigned long)mmap + ((struct multiboot_tag_mmap*)tag)->entry_size)) {
+ printk(" base_addr = ", uhex{(unsigned)(mmap->addr >> 32)}, ' ', uhex{(unsigned)(mmap->addr & 0xffffffff)});
+ printk(" length = ", (unsigned)(mmap->len >> 32), ' ', (unsigned)(mmap->len & 0xffffffff));
+ printk(" type = ", (unsigned)mmap->type, '\n');
+ }
+ } break;
- for (mmap = ((struct multiboot_tag_mmap *)tag)->entries;
- (multiboot_uint8_t *)mmap < (multiboot_uint8_t *)tag + tag->size;
- mmap = (multiboot_memory_map_t *)((unsigned long)mmap +
- ((struct multiboot_tag_mmap *)tag)
- ->entry_size))
- printk(" base_addr = 0x", (unsigned)(mmap->addr >> 32), ' ',
- (unsigned)(mmap->addr & 0xffffffff), " length = 0x",
- (unsigned)(mmap->len >> 32), ' ',
- (unsigned)(mmap->len & 0xffffffff), " type = 0x",
- (unsigned)mmap->type, '\n');
- } break;
- default:
- printk("Tag 0x", tag->type, ", Size 0x", tag->size, '\n');
- break;
- } // switch(tag->type)
- } // for(each tag)
+ default:
+ printk("Tag ", tag->type, ", Size ", tag->size, '\n');
+ break;
+ } // switch(tag->type)
+ } // for(each tag)
- tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag +
- ((tag->size + 7) & ~7));
- printk("Total mbi size 0x", (unsigned)tag - mb_addr, '\n');
+ tag = (struct multiboot_tag*)((multiboot_uint8_t*)tag + ((tag->size + 7) & ~7));
+ printk("Total mbi size ", (unsigned)tag - mb_addr, '\n');
abort();
}
diff --git a/libk/makefile b/libk/makefile
index faf5b79..941d93d 100644
--- a/libk/makefile
+++ b/libk/makefile
@@ -1,11 +1,14 @@
CXX_OBJ := string.o stdlib/console.o
+CXX_TEST_OBJ := type_traits/test.o
libk.a: $(CXX_OBJ)
$(AR) rcs $@ $(CXX_OBJ)
-$(CXX_OBJ): %.o : %.cc
+test: $(CXX_TEST_OBJ)
+
+$(CXX_OBJ) $(CXX_TEST_OBJ): %.o : %.cc
$(CXX) -target $(TARGET) $(CXX_FLAGS) -I$(CURDIR) -c $^ -o $@
clean:
- rm libk.a $(CXX_OBJ)
+ rm -f libk.a $(CXX_OBJ) $(CXX_TEST_OBJ)
diff --git a/libk/stdlib.h b/libk/stdlib.h
index 44bacf4..f031408 100644
--- a/libk/stdlib.h
+++ b/libk/stdlib.h
@@ -4,27 +4,34 @@
#include <type_traits.h>
class Console {
-public:
+ public:
virtual void write(char c) = 0;
- virtual void write(const String &msg) = 0;
- virtual void write(int n) = 0;
- virtual void write(unsigned int n) = 0;
+ virtual void write(ViewIterator& msg) = 0;
- static void set(Console *ptr);
- static Console *get();
+ static void set(Console* ptr);
+ static Console* get();
};
-template <typename T> void printk(const T &a) {
- if (auto *c = Console::get()) {
- if constexpr (is_same<T, const char *>())
- c->write(String(a));
- else
+template <typename T>
+void printk(const T& a) {
+ if (auto* c = Console::get()) {
+ if constexpr (is_same<T, char>()) {
+ c->write(a);
+ } else if constexpr (requires { StringView(a); }) {
+ StringView v(a);
+ auto iter = v.begin();
+ c->write(iter);
+ } else if constexpr (requires { IntegerView(a); }) {
+ IntegerView v(a);
+ auto iter = v.begin();
+ c->write(iter);
+ } else
c->write(a);
}
}
template <typename T, typename... Args>
-void printk(const T &a, const Args &...x) {
+void printk(const T& a, const Args&... x) {
printk(a);
printk(x...);
}
diff --git a/libk/stdlib/console.cc b/libk/stdlib/console.cc
index dee6a8f..308f055 100644
--- a/libk/stdlib/console.cc
+++ b/libk/stdlib/console.cc
@@ -1,14 +1,16 @@
#include "stdlib.h"
-static Console *global_console = nullptr;
+static Console* global_console = nullptr;
-void Console::set(Console *ptr) {
+void Console::set(Console* ptr) {
if (ptr != nullptr) {
global_console = ptr;
}
}
-Console *Console::get() { return global_console; }
+Console* Console::get() {
+ return global_console;
+}
void abort() {
/*
diff --git a/libk/string.cc b/libk/string.cc
index 5cd4bb2..c75feb1 100644
--- a/libk/string.cc
+++ b/libk/string.cc
@@ -8,19 +8,19 @@
// int strncmp(const char *s1, const char *s2, int c);
/* strcmp - compare two C-strings */
-constexpr int strcmp(const char *s1, const char *s2)
-{
- const auto s1_len = strlen(s1);
- for(size_t i = 0; i < s1_len; ++i) {
- if(s1[i] == s2[i]) continue;
- if(s1[i] > s2[i]) return 1;
- if(s1[i] < s2[i]) return -1;
- }
- return 0;
+constexpr int strcmp(const char* s1, const char* s2) {
+ const auto s1_len = strlen(s1);
+ for (size_t i = 0; i < s1_len; ++i) {
+ if (s1[i] == s2[i])
+ continue;
+ if (s1[i] > s2[i])
+ return 1;
+ if (s1[i] < s2[i])
+ return -1;
+ }
+ return 0;
}
static_assert(strcmp("one", "one") == 0);
static_assert(strcmp("one", "two") < 0);
static_assert(strcmp("foo", "bar") > 0);
-
-
diff --git a/libk/string.h b/libk/string.h
index deb6fde..0675cea 100644
--- a/libk/string.h
+++ b/libk/string.h
@@ -1,19 +1,24 @@
#pragma once
-#include "types.h"
-
-constexpr size_t strlen(const char *str) {
- int len = 0;
+#include <type_traits.h>
+#include <types.h>
+
+/**
+ * Calculate the length of the string (in bytes) pointed to by str, excluding
+ * the terminating null character.
+ */
+constexpr size_t strlen(const char* str) {
+ size_t len = 0;
while (str[len])
++len;
return len;
}
/* reverse: reverse string s in place */
-constexpr void reverse(char s[]) {
+constexpr void reverse(char s[], int strlen) {
int i, j;
char c;
- for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
+ for (i = 0, j = strlen - 1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
@@ -21,49 +26,100 @@ constexpr void reverse(char s[]) {
}
/* itoa: convert n to characters in s */
-template <int base = 10> constexpr void itoa(int n, char s[]) {
- int i, sign;
-
- if ((sign = n) < 0) /* record sign */
- n = -n; /* make n positive */
+template <typename T, int base = 10>
+constexpr size_t itoa(T n, char s[]) {
+ const bool is_negative = (n < 0);
+ if constexpr (!is_unsigned<T>()) {
+ if (n < 0)
+ n = -n;
+ }
- i = 0;
- do { /* generate digits in reverse order */
+ int i = 0;
+ do { /* generate digits in reverse order */
s[i++] = "0123456789abcdef"[n % base]; /* get next digit */
} while ((n /= base) > 0); /* delete it */
- if (sign < 0)
+ if (is_negative)
s[i++] = '-';
s[i] = '\0';
- reverse(s);
+ reverse(s, i);
+ return i;
}
-class String {
+class ViewIterator {
public:
- class Iterator {
- friend class String;
+ virtual char next() = 0;
+ virtual operator bool() const = 0;
+};
+
+class StringView {
+public:
+ class Iterator : public ViewIterator {
+ friend class StringView;
public:
- char next() { return p->buffer[pos++]; }
- operator bool() const { return (pos < p->m_length); }
+ char next() override { return p->buffer[pos++]; }
+ operator bool() const override { return (pos < p->m_length); }
private:
- Iterator(const String *s) : p(s) {}
+ Iterator(const StringView* s) : p(s) {}
size_t pos = 0;
- const String *p;
+ const StringView* p;
};
friend class Iterator;
- String(const char *d) : buffer{d}, m_length{strlen(d)} {}
- String(const char *d, size_t l) : buffer{d}, m_length{l} {}
+ StringView(const char* d) : buffer{d}, m_length{strlen(d)} {}
+ StringView(const char* d, size_t l) : buffer{d}, m_length{l} {}
Iterator begin() const { return Iterator(this); }
private:
- const char *const buffer;
+ const char* const buffer;
const size_t m_length;
};
+
+class IntegerView {
+public:
+ template <typename T>
+ struct HexFormat {
+ T n;
+ };
+
+ class Iterator : public ViewIterator {
+ friend class IntegerView;
+
+ public:
+ char next() override { return _p->buffer[pos++]; };
+ operator bool() const override { return (pos < _p->length); }
+
+ private:
+ Iterator(const IntegerView* v) : _p(v) {}
+
+ size_t pos = 0;
+ const IntegerView* _p;
+ };
+
+ IntegerView(int32_t n) { length = itoa(n, buffer); }
+
+ template <typename T>
+ IntegerView(HexFormat<T> f) {
+ buffer[0] = '0';
+ buffer[1] = 'x';
+ length = itoa<T, 16>(f.n, buffer + 2) + 2;
+ }
+
+ Iterator begin() const { return Iterator(this); }
+
+private:
+ char buffer[128];
+ size_t length = 0;
+};
+
+using hex = IntegerView::HexFormat<int32_t>;
+using uhex = IntegerView::HexFormat<uint32_t>;
+
+using hex_addr = IntegerView::HexFormat<uint64_t>; // TODO causes crash
diff --git a/libk/type_traits.h b/libk/type_traits.h
index cef30c1..dc70339 100644
--- a/libk/type_traits.h
+++ b/libk/type_traits.h
@@ -1,10 +1,16 @@
#pragma once
-template <class T, T v> struct integral_constant {
+template <class T, T v>
+struct integral_constant {
constexpr T operator()() const { return v; }
constexpr operator T() const { return v; }
};
-template <class T, class U> struct is_same : integral_constant<bool, false> {};
+template <class T, class U>
+struct is_same : integral_constant<bool, false> {};
-template <class T> struct is_same<T, T> : integral_constant<bool, true> {};
+template <class T>
+struct is_same<T, T> : integral_constant<bool, true> {};
+
+template <typename T>
+struct is_unsigned : integral_constant<bool, (T{0} < static_cast<T>(-1))> {};
diff --git a/libk/type_traits/test.cc b/libk/type_traits/test.cc
new file mode 100644
index 0000000..1aa11df
--- /dev/null
+++ b/libk/type_traits/test.cc
@@ -0,0 +1,17 @@
+#include <type_traits.h>
+#include <types.h>
+
+// is_same
+static_assert(is_same<int, int>() == true);
+static_assert(is_same<int, unsigned int>() == false);
+
+// is_unsigned
+static_assert(is_unsigned<uint8_t>() == true);
+static_assert(is_unsigned<uint16_t>() == true);
+static_assert(is_unsigned<uint32_t>() == true);
+static_assert(is_unsigned<uint64_t>() == true);
+
+static_assert(is_unsigned<int8_t>() == false);
+static_assert(is_unsigned<int16_t>() == false);
+static_assert(is_unsigned<int32_t>() == false);
+static_assert(is_unsigned<int64_t>() == false);
diff --git a/libk/types.h b/libk/types.h
index be38cb0..fc20d22 100644
--- a/libk/types.h
+++ b/libk/types.h
@@ -3,7 +3,6 @@
typedef unsigned short size_t;
static_assert(sizeof(size_t) >= 2);
-
typedef unsigned char uint8_t;
static_assert(sizeof(uint8_t) == 1);
diff --git a/makefile b/makefile
index 9c2728c..f45d65a 100644
--- a/makefile
+++ b/makefile
@@ -35,19 +35,21 @@ $(CXX_OBJ): %.o : %.cc
libk/libk.a:
$(MAKE) -C libk libk.a
+libk/test:
+ $(MAKE) -C libk test
+test: libk/test
+
iso: glitch.elf
mkdir -p isodir/boot/grub
cp glitch.elf isodir/boot/glitch.elf
cp grub.cfg isodir/boot/grub/grub.cfg
grub-mkrescue -o myos.iso isodir
-run: glitch.elf
- qemu-system-i386 -kernel glitch.elf
-run-iso: iso
+run: iso
qemu-system-i386 -cdrom myos.iso
clean:
- rm boot.o $(CXX_OBJ) glitch.elf
+ rm -f boot.o $(CXX_OBJ) glitch.elf
$(MAKE) -C libk clean
clean-iso:
diff --git a/vga.cc b/vga.cc
index a696d77..83d0060 100644
--- a/vga.cc
+++ b/vga.cc
@@ -11,7 +11,7 @@ constexpr uint16_t vga_entry(unsigned char uc, uint8_t color) {
VGA::VGA(vga_color fg, vga_color bg, uint32_t address) {
color = vga_entry_color(fg, bg);
- buffer = (uint16_t *)address;
+ buffer = (uint16_t*)address;
// clear buffer
for (size_t y = 0; y < max_rows; y++) {
@@ -22,20 +22,17 @@ VGA::VGA(vga_color fg, vga_color bg, uint32_t address) {
}
}
-void VGA::put_char(char c, size_t x, size_t y, uint8_t color) {
- const size_t index = y * max_columns + x;
- buffer[index] = vga_entry(c, (color == 0) ? this->color : color);
-}
-
void VGA::write(char c) {
switch (c) {
- case '\n':
- column = 0;
- ++row;
- break;
- default:
- put_char(c, column, row, color);
- ++column;
+ case '\n':
+ column = 0;
+ ++row;
+ break;
+ default: {
+ const size_t index = row * max_columns + column;
+ buffer[index] = vga_entry(c, (color == 0) ? this->color : color);
+ ++column;
+ }
}
if (column == max_columns) {
@@ -57,20 +54,8 @@ void VGA::write(char c) {
}
}
-void VGA::write(const String &data) {
- auto it = data.begin();
- while (it) {
- write(it.next());
+void VGA::write(ViewIterator& iter) {
+ while (iter) {
+ write(iter.next());
}
}
-
-void VGA::write(int n) {
- char buffer[max_columns];
- itoa<16>(n, buffer);
- write(buffer);
-}
-
-void VGA::write(unsigned int n) {
- // TODO
- write((int)n);
-}
diff --git a/vga.h b/vga.h
index f6fbbef..3052dbc 100644
--- a/vga.h
+++ b/vga.h
@@ -23,15 +23,11 @@ public:
VGA_COLOR_WHITE = 15,
};
- VGA(vga_color fg = VGA_COLOR_BLACK, vga_color bg = VGA_COLOR_LIGHT_GREY,
- uint32_t address = 0xB8000);
+ VGA(vga_color fg = VGA_COLOR_BLACK, vga_color bg = VGA_COLOR_LIGHT_GREY, uint32_t address = 0xB8000);
~VGA() = default;
- void put_char(char c, size_t x, size_t y, uint8_t color = 0);
void write(char c) override;
- void write(const String &data) override;
- void write(int n) override;
- void write(unsigned int n) override;
+ void write(ViewIterator& iter) override;
void set_color(vga_color fg, vga_color bg) { color = (fg | bg << 4); }
@@ -39,5 +35,5 @@ private:
const size_t max_columns = 80, max_rows = 25;
size_t column = 0, row = 0;
uint8_t color;
- uint16_t *buffer;
+ uint16_t* buffer;
};