aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoraqua <aqua@iserlohn-fortress.net>2022-03-28 20:03:38 +0300
committeraqua <aqua@iserlohn-fortress.net>2022-08-12 10:13:59 +0300
commitedf9e71e2a7b6b89775c29cf28c19c6b89992c25 (patch)
tree3adbf944d9e47a743063487c4facb7eed1fbdee0 /src
downloadkernel-edf9e71e2a7b6b89775c29cf28c19c6b89992c25.tar.xz
Initial commit
x86 kernel that prints a hello world message to com1
Diffstat (limited to 'src')
-rw-r--r--src/boot.h24
-rw-r--r--src/kernel.c24
-rw-r--r--src/mem.h4
-rw-r--r--src/mem/vmm.c49
-rw-r--r--src/mmap.c45
-rw-r--r--src/mmap.h7
-rw-r--r--src/multiboot2.c49
7 files changed, 202 insertions, 0 deletions
diff --git a/src/boot.h b/src/boot.h
new file mode 100644
index 0000000..56ff219
--- /dev/null
+++ b/src/boot.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ // kernel command line
+ char cmdline[64];
+
+ // memory map
+ unsigned bitmap[1024 * 32];
+
+ // module
+ unsigned module_start;
+ unsigned module_end;
+ char module_cmdline[64];
+} boot_info_t;
+
+_Static_assert((1024 * 32 * sizeof(unsigned) * 8) == (1024 * 1024));
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/kernel.c b/src/kernel.c
new file mode 100644
index 0000000..b84d7ee
--- /dev/null
+++ b/src/kernel.c
@@ -0,0 +1,24 @@
+#include "mem.h"
+
+#include <gdt.h>
+#include <stdio.h>
+
+#include "devices/uart_16550.h"
+#include "devices/vga.h"
+
+void kmain() {
+ gdt_install();
+
+ if (uart_init(COM1) != 0) printf("UART self-test failed.\r\n");
+
+ printf("hello %s world\n", "kernel");
+
+ vga_init(vmm_map(0xb8000, 0xc03ff000));
+
+ alloc4M();
+ char *c = (char *)0xc0700000;
+ if (*c == 0) printf("c is 0\r\n");
+
+ while (1)
+ ;
+}
diff --git a/src/mem.h b/src/mem.h
new file mode 100644
index 0000000..e06dd21
--- /dev/null
+++ b/src/mem.h
@@ -0,0 +1,4 @@
+#pragma once
+
+unsigned int vmm_map(unsigned int paddr, unsigned int vaddr);
+void alloc4M();
diff --git a/src/mem/vmm.c b/src/mem/vmm.c
new file mode 100644
index 0000000..431f0df
--- /dev/null
+++ b/src/mem/vmm.c
@@ -0,0 +1,49 @@
+#include "../mem.h"
+#include "paging.h"
+
+extern struct DirectoryEntry k_pagedir[1024];
+extern struct TableEntry k_ptable0x300[1024];
+
+extern const unsigned MULTIBOOT_SIZE;
+extern const unsigned VADDR_BASE;
+
+unsigned
+to_vaddr(unsigned paddr)
+{
+ return paddr + (unsigned)&VADDR_BASE - (unsigned)&MULTIBOOT_SIZE;
+}
+
+unsigned int
+vmm_map(unsigned int paddr, unsigned int vaddr)
+{
+ if (paddr & 0xfff || vaddr & 0xfff) return 0;
+
+ const unsigned table_idx = vaddr >> 22; // high 10 bits
+ const unsigned entry_idx = (vaddr >> 12) & 0x3ff; // low 10 bits
+
+ if (k_pagedir[table_idx].present == 0) return 0;
+ struct TableEntry *table = (struct TableEntry *)to_vaddr(k_pagedir[table_idx].address << 12);
+
+ table[entry_idx].address = paddr >> 12;
+ table[entry_idx].present = 1;
+ table[entry_idx].writeable = 1;
+
+ return vaddr;
+}
+
+void
+alloc4M()
+{
+ // enable pse in cr4
+ asm volatile(R"(
+ movl %cr4, %eax
+ orl $0x10, %eax
+ movl %eax, %cr4
+)");
+
+ struct DirectoryEntry4MB *directory = (struct DirectoryEntry4MB *)&k_pagedir[0x301];
+ directory->address_low = 0x1;
+ directory->present = 1;
+ directory->writeable = 1;
+ directory->pagesize = 1;
+}
diff --git a/src/mmap.c b/src/mmap.c
new file mode 100644
index 0000000..3fe35b5
--- /dev/null
+++ b/src/mmap.c
@@ -0,0 +1,45 @@
+#include "mmap.h"
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+__attribute__((section(".multiboot.text"))) unsigned
+multiboot2_mmap(const struct multiboot_mmap_entry entries[], unsigned entry_count, unsigned bitmap[1024 * 32])
+{
+ // clear out the bitmap
+ for (unsigned i = 0; i < 1024 * 32; ++i) bitmap[i] = 0;
+ unsigned avail_frames = 0;
+
+ // loop through all the mmap_entry structures where type is MULTIBOOT_MEMORY_AVAILABLE
+ for (unsigned i = 0; i < entry_count; ++i) {
+ if (entries[i].type != MULTIBOOT_MEMORY_AVAILABLE) continue;
+
+ // number of frames in this entry
+ unsigned n_frames = entries[i].len / 4096;
+ avail_frames += n_frames;
+
+#ifdef DEBUG
+ printf("mmap_entry: 0x%16llx\tlen=%12llu\t%d frames (%d blocks + %d)\n", entries[i].addr, entries[i].len, n_frames,
+ n_frames / 32, n_frames % 32);
+#endif
+
+ // the bitmap is an array of blocks, each holding 32 (2^5) values
+ unsigned table_idx = (entries[i].addr >> 17); // get the upper 15 bits
+
+ while (n_frames != 0) {
+ if (n_frames >= 32) {
+ bitmap[table_idx] = 0xffffffff;
+ table_idx++;
+ n_frames -= 32;
+ }
+ else {
+ unsigned block = bitmap[table_idx];
+ for (unsigned l = 0; l < n_frames; ++l) block |= (1 << l);
+ bitmap[table_idx] = block;
+ n_frames = 0;
+ }
+ }
+ }
+
+ return avail_frames;
+}
diff --git a/src/mmap.h b/src/mmap.h
new file mode 100644
index 0000000..13f40f2
--- /dev/null
+++ b/src/mmap.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "boot.h"
+#include <multiboot2.h>
+
+__attribute__((section(".multiboot.text"))) unsigned multiboot2_mmap(const struct multiboot_mmap_entry entries[],
+ unsigned entry_count, unsigned bitmap[1024 * 32]);
diff --git a/src/multiboot2.c b/src/multiboot2.c
new file mode 100644
index 0000000..d3e4175
--- /dev/null
+++ b/src/multiboot2.c
@@ -0,0 +1,49 @@
+#include "mmap.h"
+
+#define ADDR(x) ((unsigned)&x - 0xc0000000 + 0x2000)
+
+boot_info_t info __attribute__((section(".init")));
+
+__attribute__((section(".multiboot.text"))) void
+multiboot_strncpy(char *dest, const char *src, unsigned n)
+{
+ for (unsigned i = 0; i < n && src[i] != '\0'; ++i) dest[i] = src[i];
+}
+
+__attribute__((section(".multiboot.text"))) void
+multiboot2_module(struct multiboot_tag_module *tag, boot_info_t *info)
+{
+ info->module_start = tag->mod_start;
+ info->module_end = tag->mod_end;
+ multiboot_strncpy(info->module_cmdline, tag->cmdline, 64);
+}
+
+/**
+ * parse multiboot2 structures
+ */
+__attribute__((section(".multiboot.text"))) void
+__multiboot2(multiboot_uint32_t addr)
+{
+ boot_info_t *__info = (boot_info_t *)ADDR(info);
+
+ struct multiboot_tag *tag;
+ for (tag = (struct multiboot_tag *)(addr + 8); tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag + ((tag->size + 7u) & ~7u))) {
+
+ switch (tag->type) {
+ case MULTIBOOT_TAG_TYPE_CMDLINE:
+ multiboot_strncpy(__info->cmdline, ((struct multiboot_tag_string *)tag)->string, 64);
+ break;
+ case MULTIBOOT_TAG_TYPE_MODULE:
+ multiboot2_module((struct multiboot_tag_module *)tag, __info);
+ break;
+ case MULTIBOOT_TAG_TYPE_MMAP:
+ multiboot2_mmap(((struct multiboot_tag_mmap *)tag)->entries,
+ ((struct multiboot_tag_mmap *)tag)->size / ((struct multiboot_tag_mmap *)tag)->entry_size,
+ __info->bitmap);
+ break;
+ default:
+ break;
+ } // switch
+ } // for
+}