summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2009-12-26 21:15:05 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2009-12-26 21:15:05 +0100
commita35e29c07873db467e0ca670290666f8786dab03 (patch)
tree93ca3d311b76a8259f6883d3f32d1eabfefea60b
parentf57cbe8ecdb4f6ecb22618de361d4fcaee3fdcf3 (diff)
First steps reading multiboot info. Added GDT.
-rw-r--r--kernel/SConscript2
-rw-r--r--kernel/entry.c25
-rw-r--r--kernel/gdt.c28
-rw-r--r--kernel/gdt.h28
-rw-r--r--kernel/main.c6
-rw-r--r--kernel/multiboot.h43
6 files changed, 129 insertions, 3 deletions
diff --git a/kernel/SConscript b/kernel/SConscript
index 87fcb1f..d9988ac 100644
--- a/kernel/SConscript
+++ b/kernel/SConscript
@@ -27,4 +27,4 @@ kernel_bld = Builder(
env.Append(BUILDERS = {'Kernel' : kernel_bld})
-kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c'])
+kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c', 'gdt.c'])
diff --git a/kernel/entry.c b/kernel/entry.c
index d040cfb..4dd2ee1 100644
--- a/kernel/entry.c
+++ b/kernel/entry.c
@@ -1,4 +1,5 @@
#include "types.h"
+#include "multiboot.h"
extern void addr_phys;
extern void addr_virt;
@@ -18,13 +19,15 @@ asm(
".globl entry\n"
"entry:\n"
"mov $entry_stack_top,%esp\n"
+ "push %ebx\n"
"push %eax\n"
"call entry_main\n"
);
void entry_serial_out(char* str);
+void entry_serial_out_hex(uint32_t x);
-void entry_main(uint32_t mb_magic, void* mb_info) {
+void entry_main(uint32_t mb_magic, multiboot_info* mb_info) {
entry_serial_out("entry_main()\n");
if(mb_magic != 0x2badb002) {
entry_serial_out("Multiboot magic word is wrong!\n");
@@ -34,6 +37,17 @@ void entry_main(uint32_t mb_magic, void* mb_info) {
// TODO: Copy multiboot information.
+ entry_serial_out("Flags: ");
+ entry_serial_out_hex(mb_info->flags);
+
+ if(mb_info->flags & (1 << 2)) {
+ entry_serial_out(mb_info->cmdline);
+ entry_serial_out("\n");
+ } else {
+ entry_serial_out("No cmdline.\n");
+ }
+
+
// Create initial page tables.
for(unsigned int i = 0; i < 1024; i++) {
// Clear page directory.
@@ -90,3 +104,12 @@ void entry_serial_out(char* str) {
outb(0x3f8, *str++);
}
}
+
+void entry_serial_out_hex(uint32_t x) {
+ char str[] = "00000000\n";
+ for(int i = 0; i < 8; i++) {
+ int z = (x >> (28 - i * 4)) & 0xf;
+ str[i] = z < 10 ? '0' + z : 'a' - 10 + z;
+ }
+ entry_serial_out(str);
+}
diff --git a/kernel/gdt.c b/kernel/gdt.c
new file mode 100644
index 0000000..7d23289
--- /dev/null
+++ b/kernel/gdt.c
@@ -0,0 +1,28 @@
+#include "gdt.h"
+
+gdt_entry gdt[] = {
+ gdt_entry_init(0, 0, 0),
+ gdt_entry_init(0, 0xfffff, 0xc09a), // Code segment.
+ gdt_entry_init(0, 0xfffff, 0xc092), // Data segment.
+ gdt_entry_init(0, 0xfffff, 0xc0fa), // User mode code segment.
+ gdt_entry_init(0, 0xfffff, 0xc0f2), // User mode data segment.
+};
+
+gdt_ptr gdtr = {
+ .base = gdt,
+ .limit = sizeof(gdt) - 1
+};
+
+void gdt_init() {
+ asm volatile(
+ "lgdt (%0)\n"
+ "mov %w1, %%ds\n"
+ "mov %w1, %%es\n"
+ "mov %w1, %%fs\n"
+ "mov %w1, %%gs\n"
+ "mov %w1, %%ss\n"
+ "ljmp $0x08, $.flush\n"
+ ".flush:\n"
+ : : "r" (&gdtr), "r" (0x10)
+ );
+}
diff --git a/kernel/gdt.h b/kernel/gdt.h
new file mode 100644
index 0000000..e2c5b46
--- /dev/null
+++ b/kernel/gdt.h
@@ -0,0 +1,28 @@
+#ifndef GDT_H
+#define GDT_H
+
+#include "types.h"
+
+typedef struct {
+ uint16_t limit_low;
+ uint16_t base_low;
+ uint8_t base_mid;
+ uint16_t flags;
+ uint8_t base_high;
+} __attribute__((packed)) gdt_entry;
+
+typedef struct {
+ uint16_t limit;
+ gdt_entry* base;
+} __attribute__((packed)) gdt_ptr;
+
+#define gdt_entry_init(b, l, f) { \
+ .base_low = (b & 0xffff), \
+ .base_mid = (b >> 16 & 0xff), \
+ .base_high = (b >> 24 & 0xff), \
+ .limit_low = (l & 0xffff), \
+ .flags = (f | (l >> 8 & 0x0f00))}
+
+void gdt_init();
+
+#endif
diff --git a/kernel/main.c b/kernel/main.c
index 513894b..25ad1f1 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -1,3 +1,4 @@
+#include "gdt.h"
void kernel_serial_out(char* str);
@@ -5,7 +6,10 @@ void main() {
kernel_serial_out("main()\n");
- // TODO: GDT.
+ gdt_init();
+ kernel_serial_out("GDT set.\n");
+
+ kernel_serial_out("Halting.\n");
asm volatile(
"cli\n"
diff --git a/kernel/multiboot.h b/kernel/multiboot.h
new file mode 100644
index 0000000..5a9e348
--- /dev/null
+++ b/kernel/multiboot.h
@@ -0,0 +1,43 @@
+#ifndef MULTIBOOT_H
+#define MULTIBOOT_H
+
+#include "types.h"
+
+typedef struct {
+ uint32_t flags;
+
+ uint32_t mem_lower;
+ uint32_t mem_upper;
+
+ uint32_t boot_device;
+
+ char* cmdline;
+
+ uint32_t mods_count;
+ uint32_t mods_addr;
+
+ union {
+ uint32_t foo[3];
+ } syms;
+
+ uint32_t mmap_length;
+ uint32_t mmap_addr;
+
+ uint32_t drives_length;
+ uint32_t drives_addr;
+
+ uint32_t config_table;
+
+ uint32_t boot_loader_name;
+
+ uint32_t apm_table;
+
+ uint32_t vbe_control_info;
+ uint32_t vbe_mode_info;
+ uint32_t vbe_mode;
+ uint32_t vbe_interface_seg;
+ uint32_t vbe_interface_off;
+ uint32_t vbe_interface_len;
+} multiboot_info;
+
+#endif