Rewrite finished
This commit is contained in:
parent
fb8fb51cbe
commit
fbd17924e0
83
Makefile
83
Makefile
|
@ -1,54 +1,67 @@
|
||||||
ASM ?= nasm
|
ASM := nasm
|
||||||
|
|
||||||
CC := x86_64-elf-gcc
|
CC := x86_64-elf-gcc
|
||||||
GDB := gdb
|
CCFLAGS :=
|
||||||
|
|
||||||
LD := x86_64-elf-ld
|
LD := x86_64-elf-ld
|
||||||
|
LDFLAGS :=
|
||||||
|
|
||||||
C_FILES = $(shell find src/ -type f -name '*.c')
|
INCLUDE := include/
|
||||||
CO_FILES = $(patsubst src/%.c, obj/%.o, $(C_FILES))
|
|
||||||
ASM_FILES = $(shell find src/kernel/ -type f -name '*.asm')
|
|
||||||
AO_FILES = $(patsubst src/kernel/%.asm, obj/kernel/%.o, $(ASM_FILES))
|
|
||||||
|
|
||||||
KERNEL_O_FILES = ${CO_FILES} ${AO_FILES}
|
# Target: kernel, type: C ASM
|
||||||
|
kernel_c_source_files = $(shell find src/kernel/ -type f -name *.c)
|
||||||
|
kernel_c_object_files = $(patsubst src/%.c,obj/%.o,$(kernel_c_source_files))
|
||||||
|
kernel_asm_source_files = $(shell find src/kernel/ -type f -name *.asm)
|
||||||
|
kernel_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(kernel_asm_source_files))
|
||||||
|
kernel_source_files = $(kernel_c_source_files) $(kernel_asm_object_files)
|
||||||
|
kernel_object_files = $(kernel_c_object_files) $(kernel_asm_object_files)
|
||||||
|
|
||||||
BOOT_O_FILES = obj/entry.o obj/entry64.o obj/mb2.o obj/vga-print.o
|
# Target: libc, type: C ASM
|
||||||
BOOT_SRC_FILES = obj/entry.asm obj/entry64.asm obj/mb2.asm obj/vga-print.asm
|
libc_c_source_files = $(shell find src/libc/ -type f -name *.c)
|
||||||
|
libc_c_object_files = $(patsubst src/%.c,obj/%.o,$(libc_c_source_files))
|
||||||
|
libc_asm_source_files = $(shell find src/libc/ -type f -name *.asm)
|
||||||
|
libc_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(libc_c_object_files))
|
||||||
|
libc_source_files = $(libc_c_source_files) $(libc_asm_source_files)
|
||||||
|
libc_object_files = $(libc_c_object_files) $(libc_asm_object_files)
|
||||||
|
|
||||||
iso: bin/shade.iso
|
# Target: sboot, type: ASM
|
||||||
|
# Override: 32-bit
|
||||||
|
sboot_asm_source_files = $(shell find src/boot/ -type f -name *.asm)
|
||||||
|
sboot_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(sboot_asm_source_files))
|
||||||
|
sboot_source_files = $(sboot_asm_source_files)
|
||||||
|
sboot_object_files = $(sboot_asm_object_files)
|
||||||
|
|
||||||
bin/shade.bin: ${BOOT_O_FILES} ${KERNEL_O_FILES}
|
shade_bin_ldfile = src/linker.ld
|
||||||
mkdir -p bin
|
|
||||||
$(LD) -T src/linker.ld $^ -o $@
|
default: run
|
||||||
grub-file --is-x86-multiboot2 bin/shade.bin
|
|
||||||
|
|
||||||
bin/shade.iso: bin/shade.bin
|
bin/shade.iso: bin/shade.bin
|
||||||
mkdir -p isodir/boot/grub
|
cp bin/shade.bin src/iso/boot/shade.bin
|
||||||
cp bin/shade.bin isodir/boot/shade.bin
|
grub-mkrescue src/iso/ -o $@
|
||||||
cp src/iso/grub.cfg isodir/boot/grub/grub.cfg
|
rm src/iso/boot/shade.bin
|
||||||
grub-mkrescue -o bin/shade.iso isodir
|
|
||||||
rm -rf isodir
|
|
||||||
|
|
||||||
|
bin/shade.bin: $(sboot_object_files) $(kernel_object_files) $(libc_object_files)
|
||||||
|
mkdir -p "$(@D)"
|
||||||
|
$(LD) $(LDFLAGS) -n -T $(shade_bin_ldfile) $^ -o $@
|
||||||
|
grub-file --is-x86-multiboot2 $@
|
||||||
|
|
||||||
|
# Generics
|
||||||
|
# Source file types: C ASM
|
||||||
|
|
||||||
|
# C
|
||||||
obj/%.o: src/%.c
|
obj/%.o: src/%.c
|
||||||
mkdir -p "$(@D)"
|
mkdir -p "$(@D)"
|
||||||
$(CC) -ffreestanding -O2 -Wall -Wextra -c $< -o $@
|
$(CC) $(CCFLAGS) -I $(INCLUDE) -ffreestanding -c $< -o $@
|
||||||
|
|
||||||
|
# ASM
|
||||||
obj/%.o: src/%.asm
|
obj/%.o: src/%.asm
|
||||||
mkdir -p "$(@D)"
|
mkdir -p "$(@D)"
|
||||||
$(ASM) -f elf64 $< -o $@
|
$(ASM) -felf64 $< -o $@
|
||||||
|
|
||||||
|
|
||||||
|
# Other
|
||||||
run: clean bin/shade.iso
|
run: clean bin/shade.iso
|
||||||
qemu-system-x86_64 -hdd bin/shade.iso -d int -no-reboot
|
qemu-system-x86_64 -drive file=bin/shade.iso,index=0,media=disk,format=raw
|
||||||
|
|
||||||
debug: clean bin/shade.iso bin/shade.bin
|
|
||||||
qemu-system-x86_64 -s -S -hdd bin/shade.iso -d int -no-reboot &
|
|
||||||
${GDB} os-image.bin -ex "set arch i386:x86-64" -ex "symbol-file bin/shade.bin" -ex "target remote localhost:1234"
|
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find obj -type f -name '*.o' -exec rm {} +
|
rm -rf bin/*
|
||||||
find obj -type f -name '*.bin' -exec rm {} +
|
rm -rf obj/*
|
||||||
find bin -type f -name '*.o' -exec rm {} +
|
|
||||||
find bin -type f -name '*.bin' -exec rm {} +
|
|
||||||
find . -type f -name '*.dis' -exec rm {} +
|
|
||||||
rm -f kernel.elf
|
|
||||||
rm -rf isodir
|
|
BIN
bin/shade.bin
BIN
bin/shade.bin
Binary file not shown.
BIN
bin/shade.iso
BIN
bin/shade.iso
Binary file not shown.
|
@ -0,0 +1,4 @@
|
||||||
|
unsigned char port_byte_in(unsigned short port);
|
||||||
|
void port_byte_out(unsigned short port, unsigned char data);
|
||||||
|
unsigned short port_word_in(unsigned short port);
|
||||||
|
void port_word_out(unsigned short port, unsigned short data);
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,141 @@
|
||||||
|
|
||||||
|
|
||||||
|
global entry_x86
|
||||||
|
extern entry_x64
|
||||||
|
|
||||||
|
section .text
|
||||||
|
bits 32
|
||||||
|
entry_x86:
|
||||||
|
mov esp, stack_top
|
||||||
|
|
||||||
|
call check_mb2_boot
|
||||||
|
call check_cpuid
|
||||||
|
call check_x64_supported
|
||||||
|
|
||||||
|
call setup_page_tables
|
||||||
|
call enable_paging
|
||||||
|
|
||||||
|
lgdt [gdt64.pointer]
|
||||||
|
jmp gdt64.code_segment:entry_x64 ; Jump into 64 bit entry
|
||||||
|
|
||||||
|
hlt
|
||||||
|
|
||||||
|
check_mb2_boot:
|
||||||
|
cmp eax, 0x36d76289 ; compare eax to mb2 magic number
|
||||||
|
jne .mb2_not_booted
|
||||||
|
ret
|
||||||
|
.mb2_not_booted:
|
||||||
|
mov al, "B" ; err code B - boot error
|
||||||
|
jmp error
|
||||||
|
|
||||||
|
check_cpuid:
|
||||||
|
pushfd ; Put flags on stack so we can mess with them
|
||||||
|
pop eax ; then put the stack into EAX so we can easily modify it
|
||||||
|
mov ecx, eax ; Make a copy of eax in ecx for comparison
|
||||||
|
xor eax, 1 << 21 ; Attempt to flip the CPUID bit which is bit 21
|
||||||
|
push eax ; Put eax back onto stack
|
||||||
|
popfd ; Write flags back
|
||||||
|
pushfd ; Copy flags onto stack so we can check if the bit did flip
|
||||||
|
pop eax ; Put stack into EAX for comparison
|
||||||
|
push ecx ; Put original flags into stack so we can make sure they remain unchanged
|
||||||
|
popfd; Push original flags back onto the flags register
|
||||||
|
cmp eax, ecx ; Compare the modifided? flags to the original flags
|
||||||
|
je .cpuid_unsupported ; Flags were not changed, cpuid not supported
|
||||||
|
ret
|
||||||
|
|
||||||
|
.cpuid_unsupported:
|
||||||
|
mov al, "C" ; err code C - cpuid unsupported
|
||||||
|
jmp error
|
||||||
|
|
||||||
|
check_x64_supported:
|
||||||
|
mov eax, 0x80000000 ; Magic code that i dont understand
|
||||||
|
cpuid ; Magic code that i dont understand
|
||||||
|
cmp eax, 0x80000001 ; Magic code that i dont undetstand
|
||||||
|
jb .x64_unsupported ; Something went wrong so x64 isnt supported
|
||||||
|
|
||||||
|
mov eax, 0x80000001 ; Set magic value 0x80000001 into EAX for cpuid
|
||||||
|
cpuid ; Get "extended features list" from CPU info
|
||||||
|
test edx, 1 << 29 ; Check if x64 is supported by checking bit 29
|
||||||
|
jz .x64_unsupported ; If zero, x64 unsupported so jump to no x64
|
||||||
|
|
||||||
|
ret
|
||||||
|
.x64_unsupported:
|
||||||
|
mov al, "L" ; err code L, long mode/x64 unsupported
|
||||||
|
jmp error
|
||||||
|
|
||||||
|
; Magic paging code that I don't understand
|
||||||
|
setup_page_tables:
|
||||||
|
mov eax, page_table_l3
|
||||||
|
or eax, 0b11 ; present, writable
|
||||||
|
mov [page_table_l4], eax
|
||||||
|
|
||||||
|
mov eax, page_table_l2
|
||||||
|
or eax, 0b11 ; present, writable
|
||||||
|
mov [page_table_l3], eax
|
||||||
|
|
||||||
|
mov ecx, 0 ; counter
|
||||||
|
.loop:
|
||||||
|
|
||||||
|
mov eax, 0x200000 ; 2MiB
|
||||||
|
mul ecx
|
||||||
|
or eax, 0b10000011 ; present, writable, huge page
|
||||||
|
mov [page_table_l2 + ecx * 8], eax
|
||||||
|
|
||||||
|
inc ecx ; increment counter
|
||||||
|
cmp ecx, 512 ; checks if the whole table is mapped
|
||||||
|
jne .loop ; if not, continue
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
enable_paging:
|
||||||
|
; pass page table location to cpu
|
||||||
|
mov eax, page_table_l4
|
||||||
|
mov cr3, eax
|
||||||
|
|
||||||
|
; enable PAE
|
||||||
|
mov eax, cr4
|
||||||
|
or eax, 1 << 5
|
||||||
|
mov cr4, 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
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
error:
|
||||||
|
; print "ERR: X" where X is the error code
|
||||||
|
mov dword [0xb8000], 0x4f524f45
|
||||||
|
mov dword [0xb8004], 0x4f3a4f52
|
||||||
|
mov dword [0xb8008], 0x4f204f20
|
||||||
|
mov byte [0xb800a], al
|
||||||
|
hlt
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 4096
|
||||||
|
page_table_l4:
|
||||||
|
resb 4096
|
||||||
|
page_table_l3:
|
||||||
|
resb 4096
|
||||||
|
page_table_l2:
|
||||||
|
resb 4096
|
||||||
|
stack_bottom:
|
||||||
|
resb 4096 * 4
|
||||||
|
stack_top:
|
||||||
|
|
||||||
|
section .rodata
|
||||||
|
gdt64:
|
||||||
|
dd 0 ; zero entry
|
||||||
|
dd 0
|
||||||
|
.code_segment: equ $ - gdt64
|
||||||
|
dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) ; code segment
|
||||||
|
.pointer:
|
||||||
|
dw $ - gdt64 - 1 ; length
|
||||||
|
dq gdt64 ; address
|
|
@ -0,0 +1,17 @@
|
||||||
|
global entry_x64
|
||||||
|
extern kmain
|
||||||
|
|
||||||
|
section .text
|
||||||
|
bits 64
|
||||||
|
entry_x64:
|
||||||
|
; Nullify all data registers
|
||||||
|
mov ax, 0
|
||||||
|
mov ss, ax
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
call kmain ; Jump into C kernel entry
|
||||||
|
|
||||||
|
hlt
|
|
@ -0,0 +1,16 @@
|
||||||
|
section .mb2_header
|
||||||
|
header_start:
|
||||||
|
; https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html for more information, section 3.1.1
|
||||||
|
dd 0xe85250d6 ; multiboot2 magic number
|
||||||
|
|
||||||
|
dd 0 ; i386 protected 32 bit mode
|
||||||
|
|
||||||
|
dd header_end - header_start ; Header length
|
||||||
|
|
||||||
|
dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) ; Checksum, total is 0
|
||||||
|
|
||||||
|
; Ending tag
|
||||||
|
dw 0
|
||||||
|
dw 0
|
||||||
|
dd 8
|
||||||
|
header_end:
|
|
@ -0,0 +1,7 @@
|
||||||
|
set timeout=5
|
||||||
|
set default=0
|
||||||
|
|
||||||
|
menuentry "shadeOS Development Build" {
|
||||||
|
multiboot2 /boot/shade.bin
|
||||||
|
boot
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
set timeout=0
|
|
||||||
set default=0
|
|
||||||
|
|
||||||
menuentry "shadeOS Dev Build" {
|
|
||||||
multiboot /boot/shade.bin
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include "./platform/ports.h"
|
#include <shade/platform/ports.h>
|
||||||
#include "print.h"
|
#include <shade/print.h>
|
||||||
|
|
||||||
void dummy_test_entrypoint() {}
|
|
||||||
|
|
||||||
void kernel_welcome() {
|
void kernel_welcome() {
|
||||||
print_str("Welcome to ");
|
print_str("Welcome to ");
|
||||||
|
@ -44,4 +42,5 @@ void kmain() {
|
||||||
print_str("Copyright (c) e3team 2022. All rights reserved.\n");
|
print_str("Copyright (c) e3team 2022. All rights reserved.\n");
|
||||||
print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n");
|
print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n");
|
||||||
print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n");
|
print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n");
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Read 1 byte from specified port
|
||||||
|
*/
|
||||||
|
unsigned char port_byte_in(unsigned short port) {
|
||||||
|
unsigned char result;
|
||||||
|
// source and dest are backwards.
|
||||||
|
// "=a (result)" set the C variable to the value of register e'a'x
|
||||||
|
// '"d" (port) map the C variable port into e'd'x register
|
||||||
|
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_byte_out(unsigned short port, unsigned char data) {
|
||||||
|
// both regs are C vars, nothing is returned, so no '=' in asm syntax
|
||||||
|
// comma because two vars in input area and none in return area
|
||||||
|
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short port_word_in(unsigned short port) {
|
||||||
|
unsigned short result;
|
||||||
|
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_word_out(unsigned short port, unsigned short data) {
|
||||||
|
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
#include "print.h"
|
#include <shade/print.h>
|
||||||
#include "./platform/ports.h"
|
#include <shade/platform/ports.h>
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
int col = 0;
|
int col = 0;
|
||||||
|
@ -87,10 +87,10 @@ void print_set_color(char foreground, char background) {
|
||||||
|
|
||||||
void set_cursor_pos(int col, int row) {
|
void set_cursor_pos(int col, int row) {
|
||||||
int offset = col + NUM_COLS * row;
|
int offset = col + NUM_COLS * row;
|
||||||
outb(REG_SCREEN_CTRL, 14);
|
port_byte_out(REG_SCREEN_CTRL, 14);
|
||||||
outb(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
|
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
|
||||||
outb(REG_SCREEN_CTRL, 15);
|
port_byte_out(REG_SCREEN_CTRL, 15);
|
||||||
outb(REG_SCREEN_DATA, (unsigned char)(offset & 0xff));
|
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
void kernel_msg_ok(char* msg) {
|
void kernel_msg_ok(char* msg) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "util.h"
|
#include <shade/util.h>
|
||||||
|
|
||||||
void memcpy(char *source, char *dest, int nbytes) {
|
void memcpy(char *source, char *dest, int nbytes) {
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "strings.h"
|
#include <strings.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
void itoa(int n, char str[]) {
|
void itoa(int n, char str[]) {
|
|
@ -1,23 +1,30 @@
|
||||||
|
|
||||||
ENTRY(entry_x86)
|
ENTRY(entry_x86)
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS {
|
||||||
{
|
|
||||||
. = 1M;
|
. = 1M;
|
||||||
|
|
||||||
.boot :
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
|
||||||
KEEP(*(.mb2_header))
|
|
||||||
}
|
|
||||||
|
|
||||||
.text :
|
|
||||||
{
|
{
|
||||||
|
*(.mb2_header)
|
||||||
*(.text)
|
*(.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
.idt BLOCK(0x1000) : ALIGN(0x1000)
|
/* Read-only data. */
|
||||||
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
_idt = .;
|
*(.rodata)
|
||||||
. = . + 0x1000;
|
}
|
||||||
|
|
||||||
|
/* Read-write data (initialized) */
|
||||||
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-write data (uninitialized) and stack */
|
||||||
|
.bss BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue