Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions boot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.COMPILER_INFO
26 changes: 26 additions & 0 deletions boot/boot.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
; vi:filetype=nasm

section .text ; start code section
align 4

section .multiboot
dd 0x1BADB002 ; magic number
dd 0x00 ; flags
dd - (0x1BADB002 + 0x00) ; checksum =>
; magic + flags + checksum = zero

extern lmain

global start
start:
cli ; prevent interrupts from waking halted CPU
mov esp, _stack ; initialize stack
push eax ; multiboot magic number
push ebx ; multiboot info
call lmain ; call the lmain function in boot.c
hlt ; halt CPU

section .bss

resb 8192 ; reserve space for stack (8kb)
_stack:
50 changes: 50 additions & 0 deletions boot/boot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <gdt.h>
#include <multiboot.h>
#include <string.h>
#include <elf.h>

void setup_longmode()
{
// TODO(coditva):
}

void jump_to_kernel(void *kernel_entry, multiboot_info_t *multiboot_info)
{
// TODO(coditva):
(void)(kernel_entry);
(void)(multiboot_info);
}

void lmain(multiboot_info_t *multiboot_info, uint32_t multiboot_magic)
{
if (multiboot_magic != MULTIBOOT_EAX_MAGIC) {
return;
}

gdt_init();

void *kernel_entry = 0x0;
char *kernel_mod_name = "kernel";

if (multiboot_info->flags & MULTIBOOT_FLAG_MODS) {
for (uint32_t i = 0; i < multiboot_info->mods_count; i++) {

multiboot_mod_t *module = (multiboot_mod_t *)
(multiboot_info->mods_addr + (i * sizeof(multiboot_mod_t)));

if (strcmp((char *)&module->string, kernel_mod_name) == 0) {
kernel_entry = elf_load((void *)(uintptr_t)module->mod_start,
(void *)(uintptr_t)module->mod_end);
(void)(kernel_entry);

}
}
}

setup_longmode();
jump_to_kernel(kernel_entry, multiboot_info);

while (1) {
; /* nop */
}
}
10 changes: 10 additions & 0 deletions boot/elf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <elf.h>

void * elf_load(void *start_address, void *end_address)
{
// TODO(coditva):
(void)(start_address);
(void)(end_address);
return 0x0;
}

28 changes: 28 additions & 0 deletions boot/gdt.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
; vi:filetype=nasm

gdtr dw 0
dd 0

; TODO: Think about moving to "higher half kernel"

global gdt_load
gdt_load:
mov eax, [esp + 4] ; load gdt address
mov [gdtr + 2], eax
mov ax, [esp + 8] ; load gdt size
mov [gdtr], ax
lgdt [gdtr] ; load idt
ret

global reload_segments
reload_segments:
jmp 0x08:complete_reload_segments ; load 0x08 into code selector (CS)

complete_reload_segments:
mov ax, 0x10 ; load 0x10 into data selector
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
45 changes: 45 additions & 0 deletions boot/gdt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <gdt.h>

gdt_entry_t gdt[GDT_SIZE];
extern void gdt_load(gdt_entry_t *, uint16_t size);

void gdt_set_entry(uint32_t offset, uint32_t base, uint32_t limit,
uint8_t access_byte)
{
if (limit > 65536) { /* adjust granularity */
limit = limit >> 12;
gdt[offset].flags_limit_1 = 0xc0;
} else {
gdt[offset].flags_limit_1 = 0x40;
}

gdt[offset].base_0 = (uint16_t)base & 0xff;
gdt[offset].base_1 = (uint8_t)(base >> 16) & 0xff;
gdt[offset].base_2 = (uint8_t)(base >> 24) & 0xff;

gdt[offset].limit_0 = (uint16_t)limit & 0xff;
gdt[offset].flags_limit_1 |= (uint16_t)(limit >> 16) & 0xf;

gdt[offset].access_byte = access_byte;
}

void gdt_init(void)
{
/* first entry is NULL entry */
gdt_set_entry(0, 0, 0, 0);

/* TODO: Remove sepecial numbers from these statements */
/* kernel code and data segments */
gdt_set_entry(1, CODE_SEGMENT_OFFSET, CODE_SEGMENT_SIZE, 0x9a);
gdt_set_entry(2, DATA_SEGMENT_OFFSET, DATA_SEGMENT_SIZE, 0x92);

/* user code and data segments */
gdt_set_entry(3, CODE_SEGMENT_OFFSET, CODE_SEGMENT_SIZE, 0xfa);
gdt_set_entry(4, DATA_SEGMENT_OFFSET, DATA_SEGMENT_SIZE, 0xf2);

/* TODO: Setup tss (what?) */
/* TODO: Setup ldt? */

gdt_load(gdt, GDT_SIZE * sizeof(gdt_entry_t) - 1);
reload_segments();
}
6 changes: 6 additions & 0 deletions boot/include/elf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef LOAD_ELF_H_O54VNAX7
#define LOAD_ELF_H_O54VNAX7

void * elf_load(void *, void *);

#endif /* end of include guard: LOAD_ELF_H_O54VNAX7 */
34 changes: 34 additions & 0 deletions boot/include/gdt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef GDT_H_9RIWT3SN
#define GDT_H_9RIWT3SN

#include <types.h>

/**
* The structure of the entries in the GDT.
*/
typedef struct _gdt_entry_t {
uint16_t limit_0;
uint16_t base_0;
uint8_t base_1;
uint8_t access_byte;
uint8_t flags_limit_1;
uint8_t base_2;
} __attribute__((packed)) gdt_entry_t;

#define GDT_SIZE 3

typedef struct _gdt_ptr_t {
uint16_t limit;
uint32_t base;
} __attribute__((packed)) gdt_ptr_t;

void gdt_init(void);
void reload_segments(void);

/* Using flat setup. TODO: Separate code and data segments(?) */
#define CODE_SEGMENT_OFFSET 0x0
#define CODE_SEGMENT_SIZE 0xffffffff
#define DATA_SEGMENT_OFFSET 0x0
#define DATA_SEGMENT_SIZE 0xffffffff

#endif /* end of include guard: GDT_H_9RIWT3SN */
143 changes: 143 additions & 0 deletions boot/include/multiboot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#ifndef MULTIBOOT_H_RKNBOMGQ
#define MULTIBOOT_H_RKNBOMGQ

#include <types.h>

/* magic numbers for multiboot. these help us verify that multiboot structure is
* indeed valid. */
#define MULTIBOOT_MAGIC 0x1BADB002
#define MULTIBOOT_EAX_MAGIC 0x2BADB002

#define MULTIBOOT_MOD_ALIGN 0x00001000
#define MULTIBOOT_INFO_ALIGN 0x00000004

/* flags for multiboot_info */
#define MULTIBOOT_FLAG_MEMORY 0x00000001
#define MULTIBOOT_FLAG_BOOTDEV 0x00000002
#define MULTIBOOT_FLAG_CMDLINE 0x00000004
#define MULTIBOOT_FLAG_MODS 0x00000008
#define MULTIBOOT_FLAG_AOUT_SYMS 0x00000010
#define MULTIBOOT_FLAG_ELF_SHDR 0X00000020
#define MULTIBOOT_FLAG_MEM_MAP 0x00000040
#define MULTIBOOT_FLAG_DRIVE_INFO 0x00000080
#define MULTIBOOT_FLAG_CONFIG_TABLE 0x00000100
#define MULTIBOOT_FLAG_BOOT_LOADER_NAME 0x00000200
#define MULTIBOOT_FLAG_APM_TABLE 0x00000400
#define MULTIBOOT_FLAG_VBE_INFO 0x00000800
#define MULTIBOOT_FLAG_FRAMEBUFFER_INFO 0x00001000

/* flags for multiboot framebuffer type */
#define MULTIBOOT_FB_TYPE_INDEXED 0x00000000
#define MULTIBOOT_FB_TYPE_RGB 0x00000001
#define MULTIBOOT_FB_TYPE_EGA_TEXT 0x00000002


typedef struct _multiboot_info_t {
uint32_t flags;

uint32_t mem_lower;
uint32_t mem_upper;

uint32_t boot_device;

uint32_t cmdline;

uint32_t mods_count;
uint32_t mods_addr;

union {
struct {
uint32_t num;
uint32_t size;
uint32_t addr;
uint32_t shndx;
} __attribute__((packed)) efl_sec;

struct {
uint32_t tabsize;
uint32_t strsize;
uint32_t addr;
uint32_t reserved;
} __attribute__((packed)) aout_sym;
};

uint32_t mmap_len;
uint32_t mmap_addr;

uint32_t drives_len;
uint32_t driver_addr;

uint32_t config_table;

uint32_t bootloader_name;

uint32_t apm_table;

struct {
uint32_t control_info;
uint32_t mode_info;
uint16_t mode;
uint16_t interface_seg;
uint16_t interface_off;
uint16_t interface_len;
} __attribute__((packed)) vbe;

struct {
uint64_t addr;
uint32_t pitch;
uint32_t width;
uint32_t height;
uint8_t bpp;
uint8_t type;

union {
struct {
uint32_t addr;
uint16_t num_colors;
} __attribute__((packed)) palette;

struct {
uint8_t red_field_position;
uint8_t red_mask_size;
uint8_t green_field_position;
uint8_t green_mask_size;
uint8_t blue_field_position;
uint8_t blue_mask_size;
} __attribute__((packed));
};
} __attribute__((packed)) framebuffer;
} __attribute__((packed)) multiboot_info_t;


typedef struct _multiboot_memory_map_t {
uint32_t size;
uint32_t base_addr_low;
uint32_t base_addr_high;
uint32_t len_low;
uint32_t len_high;
#define MULTIBOOT_MEM_TYPE_FREE 0x1 /* free memory */
#define MULTIBOOT_MEM_TYPE_RSVD 0x2 /* reserved by system */
#define MULTIBOOT_MEM_TYPE_ACPI 0x3 /* reclaimable ACPI memory */
#define MULTIBOOT_MEM_TYPE_NVS 0x4 /* non-volatile storage */
#define MULTIBOOT_MEM_TYPE_BADR 0x5 /* memory used by bad RAM modules */
uint32_t type;
} __attribute__((packed)) multiboot_memory_map_t;


typedef struct _multiboot_mod_t {
uint16_t mod_start;
uint16_t mod_end;
uint16_t string;
uint16_t reserved;
} __attribute__((packed)) multiboot_mod_t;


#define FOREACH_MEMORY_MAP(MMAP, INFO) \
for(multiboot_memory_map_t *(MMAP) = \
(multiboot_memory_map_t *)(uintptr_t)((INFO)->mmap_addr); \
(uintptr_t)(MMAP) < (INFO)->mmap_addr + (INFO)->mmap_len; \
(MMAP) = (multiboot_memory_map_t *) \
((uintptr_t)(MMAP) + (MMAP)->size + sizeof((MMAP)->size)) \
)

#endif /* end of include guard: MULTIBOOT_H_RKNBOMGQ */
6 changes: 6 additions & 0 deletions boot/include/string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef STRING_H_UQGSNPBM
#define STRING_H_UQGSNPBM

int strcmp(const char*, const char*);

#endif /* end of include guard: STRING_H_UQGSNPBM */
11 changes: 11 additions & 0 deletions boot/include/types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef TYPES_H_AO8U0VTC
#define TYPES_H_AO8U0VTC

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;

typedef uint32_t uintptr_t;

#endif /* end of include guard: TYPES_H_AO8U0VTC */
21 changes: 21 additions & 0 deletions boot/linker.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
ENTRY(start)
SECTIONS
{
. = 0x00000000;

.multiboot : {
*(.multiboot)
}

.text : {
*(.text)
}

.data ALIGN(0x1000) : {
*(.data)
}

.bss : {
*(.bss)
}
}
Loading