[BOOT] Multiboot compliant kernel which runs 64 bit code
This commit is contained in:
parent
1f8d5b3482
commit
df86be2973
22
.gdbinit
22
.gdbinit
@ -1 +1,23 @@
|
|||||||
|
file sysroot/boot/kernel
|
||||||
target remote localhost:1234
|
target remote localhost:1234
|
||||||
|
|
||||||
|
define q
|
||||||
|
monitor quit
|
||||||
|
end
|
||||||
|
|
||||||
|
define reg
|
||||||
|
monitor info registers
|
||||||
|
end
|
||||||
|
|
||||||
|
define mm
|
||||||
|
monitor info mem
|
||||||
|
end
|
||||||
|
|
||||||
|
define cpu
|
||||||
|
monitor info cpus
|
||||||
|
end
|
||||||
|
|
||||||
|
define reset
|
||||||
|
monitor system_reset
|
||||||
|
end
|
||||||
|
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,3 +3,5 @@ sysroot/
|
|||||||
*.iso
|
*.iso
|
||||||
*.img
|
*.img
|
||||||
*.log
|
*.log
|
||||||
|
kernel/obj/
|
||||||
|
tags
|
||||||
|
16
Makefile
16
Makefile
@ -4,12 +4,24 @@ ifeq ($(MITTOS64),)
|
|||||||
$(error Build environment is not activated. Please source activate)
|
$(error Build environment is not activated. Please source activate)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean kernel
|
||||||
SHELL := bash
|
SHELL := bash
|
||||||
|
|
||||||
all:
|
CC=$(TARGET)-gcc
|
||||||
|
FLAGS_TO_PASS:= \
|
||||||
|
CC=$(CC)
|
||||||
|
|
||||||
|
all: kernel
|
||||||
|
|
||||||
|
# A trick to only build phony target if necessary
|
||||||
|
kernel:
|
||||||
|
ifeq ($(shell make -sqC kernel || echo 1), 1)
|
||||||
|
@(. util/helpers.sh; print_info "Building kernel")
|
||||||
|
$(MAKE) -C kernel install $(FLAGS_TO_PASS)
|
||||||
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@(. util/helpers.sh; print_info "Cleaning up")
|
@(. util/helpers.sh; print_info "Cleaning up")
|
||||||
|
$(MAKE) -C kernel clean
|
||||||
rm -f mittos64.iso
|
rm -f mittos64.iso
|
||||||
rm -f qemu-error.log
|
rm -f qemu-error.log
|
||||||
|
33
kernel/Link.ld
Normal file
33
kernel/Link.ld
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/* Guidance from http://wiki.osdev.org/Bare_Bones */
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
KERNEL_OFFSET = 0xFFFFFF8000000000;
|
||||||
|
KERNEL_START = 0x100000;
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = KERNEL_START + KERNEL_OFFSET;
|
||||||
|
|
||||||
|
.text : AT(ADDR(.text) - KERNEL_OFFSET)
|
||||||
|
{
|
||||||
|
*(.multiboot) /* Multiboot header must be in first 4k of elf */
|
||||||
|
*(.text)
|
||||||
|
. = ALIGN(4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata BLOCK(4K) :AT(ADDR(.rodata) - KERNEL_OFFSET)
|
||||||
|
{
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data BLOCK(4K) :AT(ADDR(.data) - KERNEL_OFFSET)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss BLOCK(4K) :AT(ADDR(.bss) - KERNEL_OFFSET)
|
||||||
|
{
|
||||||
|
*(.COMMON)
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
}
|
71
kernel/Makefile
Normal file
71
kernel/Makefile
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#
|
||||||
|
# Makefile for mittos64 kernel
|
||||||
|
# (c) Thomas Lovén 2016-2017
|
||||||
|
# mittos64@thomasloven.com
|
||||||
|
#
|
||||||
|
|
||||||
|
ifeq ($(MITTOS64),)
|
||||||
|
$(error Build environment is not activated. Please source activate)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
# Find all source files and corresponding object files
|
||||||
|
KERNEL_SRC := $(wildcard **/*.[cS])
|
||||||
|
KERNEL_OBJS := $(addprefix obj/,$(patsubst %,%.o,$(basename $(KERNEL_SRC))))
|
||||||
|
|
||||||
|
# Kernel object file
|
||||||
|
KERNEL := obj/boot/kernel
|
||||||
|
|
||||||
|
|
||||||
|
# Default compilation flags
|
||||||
|
CFLAGS ?= -Wall -Wextra
|
||||||
|
CFLAGS += -ffreestanding -mcmodel=large
|
||||||
|
CPPFLAGS += -Iinclude
|
||||||
|
# Optimize only if not debugging
|
||||||
|
ifdef NDEBUG
|
||||||
|
CFLAGS += -O2
|
||||||
|
CPPFLAGS += -DNDEBUG
|
||||||
|
else
|
||||||
|
CFLAGS += -ggdb -O0
|
||||||
|
ASFLAGS += -ggdb
|
||||||
|
endif
|
||||||
|
|
||||||
|
KERNEL_DEP := $(KERNEL_OBJS:.o=.d)
|
||||||
|
DEPFLAGS = -MT $@ -MMD -MP -MF obj/$*.d
|
||||||
|
|
||||||
|
all: $(KERNEL)
|
||||||
|
|
||||||
|
# Make sure the object directories exist
|
||||||
|
OBJ_DIRS := $(sort $(dir $(KERNEL_OBJS)))
|
||||||
|
$(KERNEL_OBJS): | $(OBJ_DIRS)
|
||||||
|
$(OBJ_DIRS):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
|
# The kernel needs some special flags
|
||||||
|
$(KERNEL): LDFLAGS += -n -nostdlib -T Link.ld
|
||||||
|
$(KERNEL): LDLIBS := -lgcc
|
||||||
|
$(KERNEL): $(KERNEL_OBJS)
|
||||||
|
$(LINK.c) $^ -o $@
|
||||||
|
|
||||||
|
# Use the default make compilation rules
|
||||||
|
obj/%.o: %.c obj/%.d
|
||||||
|
$(COMPILE.c) $(DEPFLAGS) $< -o $@
|
||||||
|
obj/%.o: %.S obj/%.d
|
||||||
|
$(COMPILE.S) $(DEPFLAGS) $< -o $@
|
||||||
|
obj/%.d: ;
|
||||||
|
|
||||||
|
# For installing stuff
|
||||||
|
${SYSROOT}/%: obj/%
|
||||||
|
mkdir -p $(dir $@)
|
||||||
|
cp $< $@
|
||||||
|
|
||||||
|
install-kernel: ${SYSROOT}/boot/kernel
|
||||||
|
|
||||||
|
install: install-kernel
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf obj/
|
||||||
|
|
||||||
|
-include $(KERNEL_DEP)
|
||||||
|
|
||||||
|
.PHONY: all clean install install-kernel
|
122
kernel/boot/boot.S
Normal file
122
kernel/boot/boot.S
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
#include <mem.h>
|
||||||
|
|
||||||
|
// Some info from here: http://os.phil-opp.com/multiboot-kernel.html
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.code32 // GRUB leaves us in 32 bit mode
|
||||||
|
_start:
|
||||||
|
cli
|
||||||
|
|
||||||
|
|
||||||
|
// Check if long mode is available
|
||||||
|
// Otherwise, there's no point in continuing
|
||||||
|
call check_longmode
|
||||||
|
|
||||||
|
|
||||||
|
// Enable long mode through process described in
|
||||||
|
// AMD64 manual vol. 2 ch. 14
|
||||||
|
|
||||||
|
// Enable Physical Address Extension
|
||||||
|
mov eax, cr4
|
||||||
|
or eax, 1<<5
|
||||||
|
mov cr4, eax
|
||||||
|
|
||||||
|
// Load page directory into cr3
|
||||||
|
mov eax, offset V2P(BootP4)
|
||||||
|
mov cr3, eax
|
||||||
|
|
||||||
|
// Enable long mode
|
||||||
|
mov ecx, 0xC0000080
|
||||||
|
rdmsr
|
||||||
|
or eax, 1<<8
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
// Enable paging
|
||||||
|
mov eax, cr0
|
||||||
|
or eax, 1<<31
|
||||||
|
mov cr0, eax
|
||||||
|
|
||||||
|
|
||||||
|
// We are now in 32 bit long mode
|
||||||
|
// Go to 64 bit mode by loading a GDT
|
||||||
|
// and perforing a far jump
|
||||||
|
lgdt [V2P(BootGDTp)]
|
||||||
|
|
||||||
|
mov eax, 0x10
|
||||||
|
mov ss, eax
|
||||||
|
mov ds, eax
|
||||||
|
mov es, eax
|
||||||
|
|
||||||
|
.extern long_mode_start
|
||||||
|
jmp 0x8:V2P(long_mode_start)
|
||||||
|
|
||||||
|
|
||||||
|
.code64
|
||||||
|
long_mode_start:
|
||||||
|
// We are now in 64 bit long mode
|
||||||
|
// but we are still running code in the identity mapped low memory kernel mirror
|
||||||
|
// Next we jump to code in high memory (> 32 bits)
|
||||||
|
|
||||||
|
movabs rax, offset .upper_memory
|
||||||
|
jmp rax
|
||||||
|
|
||||||
|
|
||||||
|
.upper_memory:
|
||||||
|
// We are now in high memory
|
||||||
|
|
||||||
|
// Set up a stack and set up a fake return address to stop backtracing
|
||||||
|
movabs rsp, offset BootStack
|
||||||
|
push 0
|
||||||
|
mov rbp, rsp
|
||||||
|
|
||||||
|
// Remove identity mapping
|
||||||
|
mov rax, 0x0
|
||||||
|
mov [V2P(BootP4)], rax
|
||||||
|
|
||||||
|
// Call c kernel code
|
||||||
|
.extern kmain
|
||||||
|
call kmain
|
||||||
|
hlt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.code32
|
||||||
|
|
||||||
|
// Check if CPUID is available
|
||||||
|
// Method described in AMD64 manual vol. 3
|
||||||
|
check_cpuid:
|
||||||
|
pushfd
|
||||||
|
pushfd
|
||||||
|
xor dword ptr[esp], 0x00200000
|
||||||
|
popfd
|
||||||
|
pushfd
|
||||||
|
pop eax
|
||||||
|
xor eax, [esp]
|
||||||
|
popfd
|
||||||
|
and eax, 1<<21
|
||||||
|
jz error
|
||||||
|
ret
|
||||||
|
|
||||||
|
// Check if long mode is available using cpuid
|
||||||
|
// AMD manual vol. 3 Appendix E
|
||||||
|
check_longmode:
|
||||||
|
call check_cpuid
|
||||||
|
mov eax, 0x80000000
|
||||||
|
cpuid
|
||||||
|
cmp eax, 0x80000001
|
||||||
|
jb error
|
||||||
|
mov eax, 0x80000001
|
||||||
|
cpuid
|
||||||
|
test edx, 1<<29
|
||||||
|
jz error
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Jump here if something went wrong
|
||||||
|
error:
|
||||||
|
// Print ERR! to screen
|
||||||
|
mov [0xb8000], dword ptr 0x4f524f45
|
||||||
|
mov [0xb8004], dword ptr 0x4f214f52
|
||||||
|
jmp .
|
54
kernel/boot/boot_structures.S
Normal file
54
kernel/boot/boot_structures.S
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
#include <mem.h>
|
||||||
|
#include <gdt.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Hardcode the initial page mapping
|
||||||
|
// Identity map the first GiB of memory
|
||||||
|
// Also map the same memory at KERNEL_OFFSET
|
||||||
|
.section .data
|
||||||
|
.align 0x1000
|
||||||
|
.global BootP4
|
||||||
|
BootP4:
|
||||||
|
.quad V2P(BootP3) + (PAGE_PRESENT | PAGE_WRITE)
|
||||||
|
.rept P4_OFFSET(KERNEL_OFFSET)-1
|
||||||
|
.quad 0x0
|
||||||
|
.endr
|
||||||
|
.quad V2P(BootP3) + (PAGE_PRESENT | PAGE_WRITE)
|
||||||
|
.rept 510 - P4_OFFSET(KERNEL_OFFSET) + 1
|
||||||
|
.quad 0x0
|
||||||
|
.endr
|
||||||
|
BootP3:
|
||||||
|
.quad V2P(BootP2) + (PAGE_PRESENT | PAGE_WRITE)
|
||||||
|
.rept 511
|
||||||
|
.quad 0x0
|
||||||
|
.endr
|
||||||
|
BootP2:
|
||||||
|
.set i, 0
|
||||||
|
.rept 512
|
||||||
|
.quad (i << 21) + (PAGE_PRESENT | PAGE_WRITE | PAGE_HUGE)
|
||||||
|
.set i, (i+1)
|
||||||
|
.endr
|
||||||
|
|
||||||
|
|
||||||
|
// Hardcode initial GDT segments
|
||||||
|
// Only kernel code (0x8) and data (0x10) for now
|
||||||
|
.section .rodata
|
||||||
|
.align 0x1000
|
||||||
|
.global BootGDT
|
||||||
|
.global BootGDTp
|
||||||
|
BootGDT:
|
||||||
|
.quad 0
|
||||||
|
.quad (GDT_PRESENT | GDT_CODEDATA | GDT_WRITE | GDT_EXECUTE | GDT_64BIT)
|
||||||
|
.quad (GDT_PRESENT | GDT_CODEDATA | GDT_WRITE)
|
||||||
|
BootGDTp: // We can't put the gdt pointer in the gdt, it's too big
|
||||||
|
.short 3*8-1
|
||||||
|
.quad V2P(BootGDT)
|
||||||
|
|
||||||
|
|
||||||
|
// Reserved space for the stack
|
||||||
|
.section .bss
|
||||||
|
.global BootStack
|
||||||
|
.align 0x1000
|
||||||
|
.skip 0x1000
|
||||||
|
BootStack:
|
34
kernel/boot/kmain.c
Normal file
34
kernel/boot/kmain.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <mem.h>
|
||||||
|
|
||||||
|
#define VGA_MEMORY 0xb8000
|
||||||
|
#define VGA_ROWS 24
|
||||||
|
#define VGA_COLS 80
|
||||||
|
|
||||||
|
void clear_screen()
|
||||||
|
{
|
||||||
|
// Clear the video memory
|
||||||
|
unsigned char *m = (void *)P2V(VGA_MEMORY);
|
||||||
|
for(int i = 0; i < VGA_ROWS*VGA_COLS*2; i++)
|
||||||
|
{
|
||||||
|
*m++ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void prints(const char *s, unsigned int row, unsigned int col)
|
||||||
|
{
|
||||||
|
// Very simple pure ascii string printing
|
||||||
|
unsigned char *m = (void *)P2V(VGA_MEMORY);
|
||||||
|
m += 2*VGA_COLS*row+2*col;
|
||||||
|
while(*s)
|
||||||
|
{
|
||||||
|
*m++ = *s++;
|
||||||
|
*m++ = 0x7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int kmain(void)
|
||||||
|
{
|
||||||
|
clear_screen();
|
||||||
|
prints("Hello, world!", 0, 0);
|
||||||
|
for(;;)asm("hlt");
|
||||||
|
}
|
23
kernel/boot/multiboot_header.S
Normal file
23
kernel/boot/multiboot_header.S
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
.section .multiboot
|
||||||
|
#include <multiboot.h>
|
||||||
|
|
||||||
|
|
||||||
|
.align 0x1000
|
||||||
|
MultiBootHeader1:
|
||||||
|
.long MBOOT1_MAGIC
|
||||||
|
.long MBOOT1_HEADER_FLAGS
|
||||||
|
.long MBOOT1_HEADER_CHECKSUM
|
||||||
|
|
||||||
|
|
||||||
|
.align 0x1000
|
||||||
|
MultiBootHeader:
|
||||||
|
.long MBOOT2_MAGIC
|
||||||
|
.long MBOOT2_ARCH
|
||||||
|
.long MBOOT2_LENGTH
|
||||||
|
.long MBOOT2_CHECKSUM
|
||||||
|
// Multiboot tags
|
||||||
|
// End tag
|
||||||
|
.short 0
|
||||||
|
.short 0
|
||||||
|
.long 8
|
||||||
|
MultiBootHeaderEnd:
|
12
kernel/include/gdt.h
Normal file
12
kernel/include/gdt.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define GDT_WRITE (1<<41)
|
||||||
|
#define GDT_EXECUTE (1<<43)
|
||||||
|
#define GDT_CODEDATA (1<<44)
|
||||||
|
#define GDT_PRESENT (1<<47)
|
||||||
|
#define GDT_64BIT (1<<53)
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
#include <stdint.h>
|
||||||
|
extern uint64_t BootGDT;
|
||||||
|
#endif
|
27
kernel/include/mem.h
Normal file
27
kernel/include/mem.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define KERNEL_OFFSET 0xFFFFFF8000000000
|
||||||
|
|
||||||
|
#ifdef __ASSEMBLER__
|
||||||
|
#define V2P(a) ((a) - KERNEL_OFFSET)
|
||||||
|
#define P2V(a) ((a) + KERNEL_OFFSET)
|
||||||
|
#define P1_OFFSET(p) (((p) >> 12) & 0x1FF)
|
||||||
|
#define P2_OFFSET(p) (((p) >> 21) & 0x1FF)
|
||||||
|
#define P3_OFFSET(p) (((p) >> 30) & 0x1FF)
|
||||||
|
#define P4_OFFSET(p) (((p) >> 39) & 0x1FF)
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#define V2P(a) ((uintptr_t)(a) - KERNEL_OFFSET)
|
||||||
|
#define P2V(a) ((void *)((uintptr_t)(a) + KERNEL_OFFSET))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Paging
|
||||||
|
#define PAGE_PRESENT 0x001
|
||||||
|
#define PAGE_WRITE 0x002
|
||||||
|
#define PAGE_USER 0x004
|
||||||
|
#define PAGE_WRITETHROUGH 0x008
|
||||||
|
#define PAGE_NOCACHE 0x010
|
||||||
|
#define PAGE_ACCESSED 0x020
|
||||||
|
#define PAGE_DIRTY 0x040
|
||||||
|
#define PAGE_HUGE 0x080
|
||||||
|
#define PAGE_GLOBAL 0x100
|
14
kernel/include/multiboot.h
Normal file
14
kernel/include/multiboot.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#define MBOOT1_MAGIC 0x1BADB002
|
||||||
|
#define MBOOT1_MAGIC2 0x2BADB002
|
||||||
|
#define MBOOT1_FLAG_PAGE_ALIGN 0x01
|
||||||
|
#define MBOOT1_FLAG_MEM_INFO 0x02
|
||||||
|
#define MBOOT1_HEADER_FLAGS (MBOOT1_FLAG_PAGE_ALIGN | MBOOT1_FLAG_MEM_INFO)
|
||||||
|
#define MBOOT1_HEADER_CHECKSUM -(MBOOT1_HEADER_FLAGS + MBOOT1_MAGIC)
|
||||||
|
|
||||||
|
#define MBOOT2_MAGIC 0xE85250D6
|
||||||
|
#define MBOOT2_MAGIC2 0x36D76289
|
||||||
|
#define MBOOT2_ARCH 0
|
||||||
|
#define MBOOT2_LENGTH (MultiBootHeaderEnd - MultiBootHeader)
|
||||||
|
#define MBOOT2_CHECKSUM -(MBOOT2_MAGIC + MBOOT2_ARCH + MBOOT2_LENGTH)
|
||||||
|
|
@ -1,6 +1,9 @@
|
|||||||
set timeout=0
|
set timeout=1
|
||||||
set default=0
|
set default=0
|
||||||
|
|
||||||
menuentry "mittos64" {
|
menuentry "mittos64" {
|
||||||
|
multiboot2 /boot/kernel
|
||||||
|
}
|
||||||
|
menuentry "mittos64 MultiBoot1" {
|
||||||
|
multiboot /boot/kernel
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user