Skip to content

Commit 30b601c

Browse files
committed
Add initial code from Ring Zero and Lower
1 parent 1301335 commit 30b601c

File tree

16 files changed

+776
-0
lines changed

16 files changed

+776
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
kernel
2+
iso
3+
14
# Prerequisites
25
*.d
36

CREDITS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Thanks to Ring Zero and Lower for providing the base for this project:
2+
http://ringzeroandlower.com/2017/08/08/x86-64-kernel-boot.html

Makefile

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Based on code by Ring Zero and Lower: http://ringzeroandlower.com/2017/08/08/x86-64-kernel-boot.html
2+
3+
CC = x86_64-elf-g++
4+
AS = x86_64-elf-gcc
5+
SHARED_FLAGS = -fno-builtin -O2 -nostdinc -nostdlib -ffreestanding -g -Wall -Wextra -Werror -I. -MMD -mno-red-zone\
6+
-mcmodel=kernel -fno-pie
7+
CFLAGS = $(SHARED_FLAGS) -fno-exceptions -fno-rtti
8+
ASFLAGS = $(SHARED_FLAGS) -Wa,--divide
9+
GRUB ?= grub
10+
11+
ASSEMBLED := boot.o
12+
COMPILED := kernel.o
13+
14+
DFILES = $(patsubst %.o,%.d,$(ASSEMBLED) $(COMPILED))
15+
OBJS = $(ASSEMBLED) $(COMPILED)
16+
ISO_FILE := kernel.iso
17+
18+
all: kernel
19+
20+
define COMPILED_TEMPLATE
21+
$(1): $(patsubst %.o,%.cpp,$(1))
22+
$(CC) $(CFLAGS) -c $$< -o $$@
23+
endef
24+
25+
define ASSEMBLED_TEMPLATE
26+
$(1): $(patsubst %.o,%.S,$(1))
27+
$(AS) $(ASFLAGS) -c $$< -o $$@
28+
endef
29+
30+
$(foreach fname,$(COMPILED),$(eval $(call COMPILED_TEMPLATE,$(fname))))
31+
$(foreach fname,$(ASSEMBLED),$(eval $(call ASSEMBLED_TEMPLATE,$(fname))))
32+
33+
kernel: $(OBJS) kernel.ld Makefile
34+
$(CC) -z max-page-size=0x1000 $(CFLAGS) -no-pie -Wl,--build-id=none -T kernel.ld -o $@ $(OBJS)
35+
36+
iso: $(ISO_FILE)
37+
38+
$(ISO_FILE): kernel
39+
mkdir -p iso/boot/grub
40+
cp grub.cfg iso/boot/grub/
41+
cp kernel iso/boot/
42+
$(GRUB)-mkrescue -o $(ISO_FILE) iso
43+
44+
run: $(ISO_FILE)
45+
qemu-system-x86_64 -cdrom $(ISO_FILE) -serial stdio -m 1024M
46+
47+
clean:
48+
find -name "*~" -delete
49+
rm -rf *.o **/*.o $(DFILES) kernel iso
50+
51+
$(OBJS): Makefile
52+
53+
-include $(DFILES)

arch/x86_64/control_register.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef _ARCH_X86_64_CONTROL_REGISTER_H_
2+
#define _ARCH_X86_64_CONTROL_REGISTER_H_
3+
4+
#define CONTROL_REGISTER0_PROTECTED_MODE_ENABLED (1 << 0)
5+
#define CONTROL_REGISTER0_EXTENSION_TYPE (1 << 4)
6+
#define CONTROL_REGISTER0_PAGE (1 << 31)
7+
8+
#define CONTROL_REGISTER4_PAGE_SIZE_EXTENSION (1 << 4)
9+
#define CONTROL_REGISTER4_PHYSICAL_ADDRESS_EXTENSION (1 << 5)
10+
11+
#endif // _ARCH_X86_64_CONTROL_REGISTER_H_

arch/x86_64/gdt.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef _ARCH_X86_64_GDT_H_
2+
#define _ARCH_X86_64_GDT_H_
3+
4+
#define GDT_ENTRY_SIZE 8
5+
6+
#define GDT_FLAG_FOUR_KILOBYTE_GRANULARITY (1 << 3)
7+
#define GDT_FLAG_32BIT_PROTECTED_MODE (1 << 2)
8+
#define GDT_FLAG_64BIT_MODE (1 << 1)
9+
10+
#define GDT_ACCESS_PRESENT (1 << 7)
11+
#define GDT_ACCESS_PRIVILEGE_RING0 (0x0 << 5)
12+
#define GDT_ACCESS_PRIVILEGE_RING1 (0x1 << 5)
13+
#define GDT_ACCESS_PRIVILEGE_RING2 (0x2 << 5)
14+
#define GDT_ACCESS_PRIVILEGE_RING3 (0x3 << 5)
15+
#define GDT_ACCESS_EXECUTABLE (1 << 3)
16+
#define GDT_ACCESS_DIRECTION_DOWN (1 << 2)
17+
#define GDT_ACCESS_READABLE_WRITABLE (1 << 1)
18+
19+
#define DECLARE_GDT_ENTRY(base, limit, flags, access) \
20+
( \
21+
(((((base)) >> 24) & 0xFF) << 56) | \
22+
((((flags)) & 0xF) << 52) | \
23+
(((((limit)) >> 16) & 0xF) << 48) | \
24+
(((((access) | (1 << 4))) & 0xFF) << 40) | \
25+
((((base)) & 0xFFF) << 16) | \
26+
(((limit)) & 0xFFFF) \
27+
)
28+
29+
#define GDT_FIRST_ENTRY 0
30+
31+
#define GDT_KERNEL_ENTRY \
32+
DECLARE_GDT_ENTRY(0, 0, \
33+
GDT_FLAG_64BIT_MODE, \
34+
GDT_ACCESS_PRESENT | \
35+
GDT_ACCESS_PRIVILEGE_RING0 | \
36+
GDT_ACCESS_EXECUTABLE) \
37+
38+
#define GDT_TABLE_ALIGNMENT 0x1000
39+
#define GDT_TABLE_SIZE 0x800
40+
41+
#endif // _ARCH_X86_64_GDT_H_

arch/x86_64/kernel.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef _ARCH_X86_64_KERNEL_H_
2+
#define _ARCH_X86_64_KERNEL_H_
3+
4+
#include <arch/x86_64/control_register.h>
5+
6+
// START macros must have the same value in the kernel linker script
7+
#define KERNEL_PHYSICAL_START 0x0000000000400000
8+
#define KERNEL_VIRTUAL_START 0xFFFFFFFF80400000
9+
10+
#define KERNEL_GDT_ENTRY 1
11+
12+
#define KERNEL_CR0 \
13+
( \
14+
CONTROL_REGISTER0_PAGE | \
15+
CONTROL_REGISTER0_PROTECTED_MODE_ENABLED | \
16+
CONTROL_REGISTER0_EXTENSION_TYPE \
17+
)
18+
#define KERNEL_CR4 (CONTROL_REGISTER4_PHYSICAL_ADDRESS_EXTENSION)
19+
20+
#endif // _ARCH_X86_64_KERNEL_H_

arch/x86_64/mmu.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef _ARCH_X86_64_MMU_H_
2+
#define _ARCH_X86_64_MMU_H_
3+
4+
#define BOOT_PHYSICAL_VIRTUAL_OFFSET \
5+
(KERNEL_VIRTUAL_START - KERNEL_PHYSICAL_START)
6+
7+
#define KERNEL_VIRTUAL_START_PAGE_DIRECTORY_ENTRY \
8+
(KERNEL_VIRTUAL_START / LEVEL_TWO_PAGE_SIZE)
9+
10+
#define PML4_SIZE 0x1000
11+
#define PML4_ALIGNMENT 0x1000
12+
#define PML4_ENTRY_SIZE 8
13+
#define PML4_ADDR_TO_ENTRY_INDEX(addr) (((addr) >> 39) & 0x1FF)
14+
15+
#define PDPT_SIZE 0x1000
16+
#define PDPT_ALIGNMENT 0x1000
17+
#define PDPT_ENTRY_SIZE 8
18+
#define PDPT_ADDR_TO_ENTRY_INDEX(addr) (((addr) >> 30) & 0x1FF)
19+
20+
#define PAGE_DIRECTORY_SIZE 0x1000
21+
#define PAGE_DIRECTORY_ALIGNMENT 0x1000
22+
#define PAGE_DIRECTORY_ENTRY_SIZE 8
23+
24+
#define PAGE_TABLE_SIZE 0x1000
25+
#define PAGE_TABLE_ALIGNMENT 0x1000
26+
#define PAGE_TABLE_ENTRY_SIZE 8
27+
28+
#define MMU_PRESENT (1 << 0)
29+
#define MMU_WRITABLE (1 << 1)
30+
#define MMU_USER_MEMORY (1 << 2)
31+
#define MMU_PDE_TWO_MB (1 << 7)
32+
33+
34+
#endif // _ARCH_X86_64_MMU_H_

arch/x86_64/msr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#ifndef _ARCH_I386_MSR_H_
2+
#define _ARCH_I386_MSR_H_
3+
4+
#define MSR_EFER 0xC0000080
5+
#define MSR_EFER_LME (1 << 8)
6+
7+
#endif // _ARCH_I386_MSR_H_

boot.S

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Based on code by Ring Zero and Lower: http://ringzeroandlower.com/2017/08/08/x86-64-kernel-boot.html
2+
3+
#include "arch/x86_64/gdt.h"
4+
#include "arch/x86_64/mmu.h"
5+
#include "kernel.h"
6+
#include "sizes.h"
7+
#include "multiboot2.h"
8+
#include "arch/x86_64/msr.h"
9+
10+
.SET HEADER_LENGTH, header_end - header_start
11+
.SET CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH)
12+
.section .multiboot
13+
header_start:
14+
.long MULTIBOOT2_HEADER_MAGIC
15+
.long MULTIBOOT_ARCHITECTURE_I386
16+
.long HEADER_LENGTH
17+
.long CHECKSUM
18+
19+
# multiboot tags go here.
20+
21+
.short MULTIBOOT_HEADER_TAG_END
22+
.short 0 # flags, none set
23+
.long 8 # size, including itself (short + short + long)
24+
header_end:
25+
26+
.code32
27+
28+
.section .bss
29+
.comm pml4, PML4_SIZE, PML4_ALIGNMENT
30+
.comm low_pdpt, PDPT_SIZE, PDPT_ALIGNMENT
31+
.comm high_pdpt, PDPT_SIZE, PDPT_ALIGNMENT
32+
.comm low_page_directory_table, PAGE_DIRECTORY_SIZE, PAGE_DIRECTORY_ALIGNMENT
33+
.comm high_page_directory_table, PAGE_DIRECTORY_SIZE, PAGE_DIRECTORY_ALIGNMENT
34+
.comm tmp_stack, KERNEL_BOOT_STACK_SIZE, KERNEL_BOOT_STACK_ALIGNMENT
35+
36+
.data
37+
.align GDT_TABLE_ALIGNMENT
38+
gdt_table:
39+
.8byte GDT_FIRST_ENTRY
40+
.8byte GDT_KERNEL_ENTRY
41+
42+
gdt_table_end:
43+
.skip (GDT_TABLE_SIZE - (gdt_table_end - gdt_table))
44+
45+
gdt_ptr:
46+
.short GDT_TABLE_SIZE - 1
47+
.long gdt_table
48+
49+
50+
.section .text
51+
.global _start
52+
.type _start, @function
53+
_start:
54+
movl $tmp_stack + KERNEL_BOOT_STACK_SIZE, %esp
55+
56+
movl $low_pdpt, %eax
57+
or $(MMU_PRESENT | MMU_WRITABLE), %eax
58+
movl %eax, pml4 + (PML4_ADDR_TO_ENTRY_INDEX(KERNEL_PHYSICAL_START) * PML4_ENTRY_SIZE)
59+
60+
movl $high_pdpt, %eax
61+
or $(MMU_PRESENT | MMU_WRITABLE), %eax
62+
movl %eax, pml4 + (PML4_ADDR_TO_ENTRY_INDEX(KERNEL_VIRTUAL_START) * PML4_ENTRY_SIZE)
63+
64+
movl $low_page_directory_table, %eax
65+
or $(MMU_PRESENT | MMU_WRITABLE), %eax
66+
movl %eax, low_pdpt + (PDPT_ADDR_TO_ENTRY_INDEX(KERNEL_PHYSICAL_START) * PDPT_ENTRY_SIZE)
67+
68+
movl $high_page_directory_table, %eax
69+
or $(MMU_PRESENT | MMU_WRITABLE), %eax
70+
movl %eax, high_pdpt + (PDPT_ADDR_TO_ENTRY_INDEX(KERNEL_VIRTUAL_START) * PDPT_ENTRY_SIZE)
71+
72+
mov $0, %ecx
73+
74+
movl $_kernel_physical_end, %esi
75+
shrl $TWO_MEGABYTES_SHIFT, %esi
76+
addl $1, %esi
77+
78+
page_directory_table_loop:
79+
movl $TWO_MEGABYTES, %eax
80+
mul %ecx
81+
or $(MMU_PRESENT | MMU_WRITABLE | MMU_PDE_TWO_MB), %eax
82+
movl %eax, low_page_directory_table(, %ecx, PAGE_DIRECTORY_ENTRY_SIZE)
83+
movl %eax, high_page_directory_table(, %ecx, PAGE_DIRECTORY_ENTRY_SIZE)
84+
85+
inc %ecx
86+
cmp %esi, %ecx
87+
jne page_directory_table_loop # If not equal, redo loop
88+
89+
movl $pml4, %eax
90+
movl %eax, %cr3
91+
92+
movl $KERNEL_CR4, %eax
93+
movl %eax, %cr4
94+
95+
movl $MSR_EFER, %ecx
96+
rdmsr
97+
or $MSR_EFER_LME, %eax
98+
wrmsr
99+
100+
movl $KERNEL_CR0, %eax
101+
movl %eax, %cr0
102+
103+
lgdt gdt_ptr
104+
105+
ljmp $(KERNEL_GDT_ENTRY * GDT_ENTRY_SIZE), $_start64
106+
107+
cli
108+
hlt
109+
110+
.code64
111+
112+
.global _start64
113+
.type _start64, @function
114+
_start64:
115+
# Setup segment selectors
116+
movw $0, %ax
117+
movw %ax, %ds
118+
movw %ax, %es
119+
movw %ax, %fs
120+
movw %ax, %gs
121+
movw %ax, %ss
122+
123+
call _Z11kernel_mainv
124+
125+
# Should never reach here
126+
cli
127+
hlt
128+
1:
129+
jmp 1b

grub.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
set timeout=0
2+
set default=0
3+
menuentry "kernel" {
4+
multiboot2 /boot/kernel
5+
}

0 commit comments

Comments
 (0)