Merge branch 'feature/rewrite'

This commit is contained in:
c0repwn3r 2022-05-13 21:44:14 -04:00
parent 523443ab90
commit 6c243376ad
Signed by: core
GPG Key ID: FDBF740DADDCEECF
78 changed files with 862 additions and 116 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
i386-elf-toolchain-aur bin/
i386-elf-tools-aur-pkgs obj/

View File

@ -3,7 +3,7 @@
{ {
"name": "Linux", "name": "Linux",
"includePath": [ "includePath": [
"${workspaceFolder}/**" "${workspaceFolder}/include/**"
], ],
"defines": [], "defines": [],
"compilerPath": "/usr/bin/clang", "compilerPath": "/usr/bin/clang",

View File

@ -1,5 +1,5 @@
{ {
"files.associations": { "files.associations": {
"idt.h": "c" "types.h": "c"
} }
} }

View File

@ -1,56 +1,67 @@
# $@ = target file ASM := nasm
# $< = first dependency
# $^ = all dependencies
GDB = gdb CC := x86_64-elf-gcc
CCFLAGS :=
C_FILES = $(shell find src/ -type f -name '*.c') LD := x86_64-elf-ld
CO_FILES = $(patsubst src/%.c, obj/%.o, $(C_FILES)) LDFLAGS :=
ASM_FILES = $(shell find src/kernel/ -type f -name '*.asm')
AO_FILES = $(patsubst src/kernel/%.asm, obj/kernel/%.o, $(ASM_FILES))
ABIN_FILES = $(patsubst src/%.asm, bin/%.bin, $(ASM_FILES))
os-image.bin: bin/boot.bin bin/kernel.bin INCLUDE := include/
cat $^ > $@
bin/boot.bin: src/boot/boot.asm bin/kernel.bin .FORCE # Target: kernel, type: C ASM
sed -i.orig "s@CH_REPLACE_BOOTSECTORCOUNT@$(shell ./getinblocks.py $(shell du -b "bin/kernel.bin" | cut -f 1))@g" src/boot/kernel.asm kernel_c_source_files = $(shell find src/kernel/ -type f -name *.c)
nasm -Isrc/boot/ $< -f bin -o $@ kernel_c_object_files = $(patsubst src/%.c,obj/%.o,$(kernel_c_source_files))
mv src/boot/kernel.asm.orig src/boot/kernel.asm 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)
.FORCE: # Target: libc, type: C 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)
bin/kernel.bin: obj/kernel/entry.o ${CO_FILES} ${AO_FILES} # Target: sboot, type: ASM
i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary # 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)
kernel.elf: obj/kernel/entry.o ${CO_FILES} ${AO_FILES} shade_bin_ldfile = src/linker.ld
i386-elf-ld -o $@ -Ttext 0x1000 $^
run: clean os-image.bin default: run
qemu-system-x86_64 -hdd os-image.bin
debug: clean os-image.bin kernel.elf bin/shade.iso: bin/shade.bin
qemu-system-x86_64 -s -S -hdd os-image.bin & cp bin/shade.bin src/iso/boot/shade.bin
${GDB} os-image.bin -ex "symbol-file kernel.elf" -ex "target remote localhost:1234" grub-mkrescue src/iso/ -o $@
rm src/iso/boot/shade.bin
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)"
i386-elf-gcc -g -ffreestanding -c $< -o $@ $(CC) $(CCFLAGS) -I $(INCLUDE) -ffreestanding -c $< -o $@
# ASM
obj/%.o: src/%.asm obj/%.o: src/%.asm
mkdir -p "$(@D)" mkdir -p "$(@D)"
nasm -f elf $< -o $@ $(ASM) -felf64 $< -o $@
bin/%.bin: src/%.asm # Other
mkdir -p "$(@D)" run: clean bin/shade.iso
nasm -f bin $< -o $@ qemu-system-x86_64 -drive file=bin/shade.iso,index=0,media=disk,format=raw
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

Binary file not shown.

Binary file not shown.

57
bochsrc.txt Normal file
View File

@ -0,0 +1,57 @@
# configuration file generated by Bochs
plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true, pcidev=false, usb_uhci=false
config_interface: textconfig
display_library: x
memory: host=32, guest=32
romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
boot: floppy
floppy_bootsig_check: disabled=0
floppya: type=1_44
# no floppyb
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="bin/shade.iso", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto
ata0-slave: type=none
ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=none
ata1-slave: type=none
ata2: enabled=false
ata3: enabled=false
optromimage1: file=none
optromimage2: file=none
optromimage3: file=none
optromimage4: file=none
optramimage1: file=none
optramimage2: file=none
optramimage3: file=none
optramimage4: file=none
pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none
vga: extension=vbe, update_freq=5, realtime=1, ddc=builtin
cpu: count=1:1:1, ips=4000000, quantum=16, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor"
cpuid: mmx=true, apic=xapic, simd=sse2, sse4a=false, misaligned_sse=false, sep=true
cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, avx_f16c=false
cpuid: avx_fma=false, bmi=0, xop=false, fma4=false, tbm=false, x86_64=true, 1g_pages=false
cpuid: pcid=false, fsgsbase=false, smep=false, smap=false, mwait=true
print_timestamps: enabled=0
debugger_log: -
magic_break: enabled=0
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
log: -
logprefix: %t%e%d
debug: action=ignore
info: action=report
error: action=report
panic: action=ask
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
mouse: type=ps2, enabled=false, toggle=ctrl+mbutton
speaker: enabled=true, mode=system
parport1: enabled=true, file=none
parport2: enabled=false
com1: enabled=true, mode=null
com2: enabled=false
com3: enabled=false
com4: enabled=false

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

56
old/Makefile Normal file
View File

@ -0,0 +1,56 @@
# $@ = target file
# $< = first dependency
# $^ = all dependencies
GDB = gdb
C_FILES = $(shell find src/ -type f -name '*.c')
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))
ABIN_FILES = $(patsubst src/%.asm, bin/%.bin, $(ASM_FILES))
os-image.bin: bin/boot.bin bin/kernel.bin
cat $^ > $@
bin/boot.bin: src/boot/boot.asm bin/kernel.bin .FORCE
sed -i.orig "s@CH_REPLACE_BOOTSECTORCOUNT@$(shell ./getinblocks.py $(shell du -b "bin/kernel.bin" | cut -f 1))@g" src/boot/kernel.asm
nasm -Isrc/boot/ $< -f bin -o $@
mv src/boot/kernel.asm.orig src/boot/kernel.asm
.FORCE:
bin/kernel.bin: obj/kernel/entry.o ${CO_FILES} ${AO_FILES}
i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary
kernel.elf: obj/kernel/entry.o ${CO_FILES} ${AO_FILES}
i386-elf-ld -o $@ -Ttext 0x1000 $^
run: clean os-image.bin
qemu-system-x86_64 -hdd os-image.bin -d int
debug: clean os-image.bin kernel.elf
qemu-system-x86_64 -s -S -hdd os-image.bin &
${GDB} os-image.bin -ex "symbol-file kernel.elf" -ex "target remote localhost:1234"
obj/%.o: src/%.c
mkdir -p "$(@D)"
i386-elf-gcc -g -ffreestanding -c $< -o $@
obj/%.o: src/%.asm
mkdir -p "$(@D)"
nasm -f elf $< -o $@
bin/%.bin: src/%.asm
mkdir -p "$(@D)"
nasm -f bin $< -o $@
clean:
find obj -type f -name '*.o' -exec rm {} +
find obj -type f -name '*.bin' -exec rm {} +
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

BIN
old/os-image.bin Normal file

Binary file not shown.

View File

@ -1,3 +1,4 @@
gdt_start: ; use labels to compute sizes and jumps gdt_start: ; use labels to compute sizes and jumps
; gdt starts with 8 byte null ; gdt starts with 8 byte null
dd 0x0 dd 0x0
@ -14,12 +15,12 @@ gdt_code:
; GDT for data segment ; GDT for data segment
gdt_data: gdt_data:
dw 0xffff dw 0xffff ; segment length
dw 0x0 dw 0x0 ; segment base
db 0x0 db 0x0 ; segment base
db 10010010b db 10010010b ; flags
db 11001111b db 11001111b ; flags + segment length
db 0x0 db 0x0 ; segment base
gdt_end: gdt_end:

54
old/src/kernel/kernel.c Normal file
View File

@ -0,0 +1,54 @@
#include "./platform/drivers/ports.h"
#include "print.h"
#include "./platform/types.h"
#include "./platform/interrupts/int.h"
void dummy_test_entrypoint() {}
void kernel_welcome() {
print_str("Welcome to ");
print_set_color(PRINT_COLOR_CYAN, PRINT_COLOR_BLACK);
print_str("Shade");
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
print_str("!\n");
print_str("shadeOS kernel version ");
print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK);
print_str("0.2.2");
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
print_newline();
print_str("Running on ");
print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK);
print_str("shade-development");
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
print_newline();
}
// kMain
void main() {
// Initialize screen buffer
struct Char* buffer = (struct Char*) 0xb8000;
clear_all(); // Clear screen
set_cursor_pos(0, 0); // Set cursor position
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set print color
// welcome messages
kernel_msg_ok("Initialized display successfully\n");
kernel_welcome();
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("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n");
idt_init();
kernel_msg_ok("Interrupts initialized");
__asm__ __volatile__("int $2");
}

View File

@ -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);

View File

@ -0,0 +1,28 @@
#ifndef GDT_H
#define GDT_H
#include <stdint.h>
// the GDT descriptor format makes literally no sense, who came up with this
typedef struct {
uint16_t limit_low16; // Low 16 bits of limit
uint16_t base_low16; // Low 16 bits of base
uint8_t base_mid8; // Middle 8 bits of base
uint8_t access; // 7: present, 6-5: priv level, 4: type, 3: executable, 2: dc, 1: rw, 0: accessed (zero)
uint8_t limit_flags; // High 4 bits of limit AND flags (?? why). flags: 3: granularity, 2: size, 1: long, 0: reserved
uint8_t base_high8; // High 8 bits of base
} __attribute__((packed)) gdt_entry_t;
typedef struct {
uint16_t size; // GDT size (bytes) - 1
uint32_t offset; // Address of element 0 of the GDT
} __attribute__((packed)) gdt_ptr_t;
static gdt_entry_t gdt[8192];
static gdt_ptr_t gdtr;
void init_gdt();
void gdt_set_segment(int limit, int base, int access);
void load_gdt();
#endif

View File

@ -1,8 +1,14 @@
#include "int.h" #include "int.h"
#include "../../print.h" #include "../../print.h"
void exception_handler() { int count = 0;
void exception_handler(registers_t r) {
print_str("I"); print_str("I");
count++;
if (count > 4) {
__asm__ __volatile__("cli; hlt");
}
} }
void idt_set_descriptor(u8 vector, void* isr, u8 flags) { void idt_set_descriptor(u8 vector, void* isr, u8 flags) {

View File

@ -21,8 +21,15 @@ typedef struct {
static idtr_t idtr; static idtr_t idtr;
typedef struct {
u32 ds; /* Data segment selector */
u32 edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
u32 int_no, err_code; /* Interrupt number and error code (if applicable) */
u32 eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */
} registers_t;
__attribute__((noreturn)) __attribute__((noreturn))
void exception_handler(void); void exception_handler(registers_t r);
void idt_set_descriptor(u8 vector, void* isr, u8 flags); void idt_set_descriptor(u8 vector, void* isr, u8 flags);

View File

@ -0,0 +1,102 @@
%macro isr_err_stub 1
isr_stub_%+%1:
push byte %1 ; Push interrupt no to stack
; 1. Save CPU state
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
mov ax, 0x10 ; kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; 2. Call C handler
call exception_handler
; 3. Restore state
pop eax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
popa
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
%endmacro
; if writing for 64-bit, use iretq instead
%macro isr_no_err_stub 1
isr_stub_%+%1:
push byte 0 ; No error occured
push byte %1 ; Push interrupt no to stack
; 1. Save CPU state
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
mov ax, 0x10 ; kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; 2. Call C handler
call exception_handler
; 3. Restore state
pop eax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
popa
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
%endmacro
extern exception_handler
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
isr_no_err_stub 4
isr_no_err_stub 5
isr_no_err_stub 6
isr_no_err_stub 7
isr_err_stub 8
isr_no_err_stub 9
isr_err_stub 10
isr_err_stub 11
isr_err_stub 12
isr_err_stub 13
isr_err_stub 14
isr_no_err_stub 15
isr_no_err_stub 16
isr_err_stub 17
isr_no_err_stub 18
isr_no_err_stub 19
isr_no_err_stub 20
isr_no_err_stub 21
isr_no_err_stub 22
isr_no_err_stub 23
isr_no_err_stub 24
isr_no_err_stub 25
isr_no_err_stub 26
isr_no_err_stub 27
isr_no_err_stub 28
isr_no_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
global isr_stub_table
isr_stub_table:
%assign i 0
%rep 32
dd isr_stub_%+i ; use DQ instead if targeting 64-bit
%assign i i+1
%endrep

110
old/src/kernel/print.c Normal file
View File

@ -0,0 +1,110 @@
#include "print.h"
#include "./platform/drivers/ports.h"
int row = 0;
int col = 0;
char color = PRINT_COLOR_WHITE | PRINT_COLOR_BLACK << 4;
void clear_row(int row) {
struct Char* buffer = (struct Char*) 0xb8000;
struct Char empty = (struct Char) {
character: ' ',
color: color,
};
for (int x = 0; x < NUM_COLS; x++) {
buffer[x + NUM_COLS * row] = empty;
}
set_cursor_pos(col, row);
}
void clear_all() {
for (int i = 0; i < NUM_ROWS; i++) {
clear_row(i);
}
set_cursor_pos(col, row);
}
void print_newline() {
struct Char* buffer = (struct Char*) 0xb8000;
col = 0;
if (row < NUM_ROWS - 1) {
row++;
return;
}
for (int row = 1; row < NUM_ROWS; row++) {
for (int col = 0; col < NUM_COLS; col++) {
struct Char character = buffer[col + NUM_COLS * row];
buffer[col + NUM_COLS * (row - 1)] = character;
}
}
clear_row(NUM_COLS - 1);
set_cursor_pos(col, row);
}
void print_char(char character) {
struct Char* buffer = (struct Char*) 0xb8000;
if (character == '\n') {
print_newline();
return;
}
if (col > NUM_COLS) {
print_newline();
}
struct Char cr = (struct Char) {
character: character,
color: color,
};
buffer[col + NUM_COLS * row] = cr;
col++;
set_cursor_pos(col, row);
}
void print_str(char* str) {
for (int i = 0; 1; i++) {
char character = (char) str[i];
if (character == '\0') {
return;
}
print_char(character);
}
}
void print_set_color(char foreground, char background) {
color = foreground + (background << 4);
}
void set_cursor_pos(int col, int row) {
int offset = col + NUM_COLS * row;
port_byte_out(REG_SCREEN_CTRL, 14);
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
port_byte_out(REG_SCREEN_CTRL, 15);
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset & 0xff));
}
void kernel_msg_ok(char* msg) {
char ok_p1[] = "[ ";
char ok_p2[] = "OK ";
char ok_p3[] = "] ";
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
print_str(ok_p1);
print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK);
print_str(ok_p2);
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
print_str(ok_p3);
print_str(msg);
}

44
old/src/kernel/print.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef PRINT_H
#define PRINT_H
#define REG_SCREEN_CTRL 0x3d4
#define REG_SCREEN_DATA 0x3d5
enum {
PRINT_COLOR_BLACK = 0,
PRINT_COLOR_BLUE = 1,
PRINT_COLOR_GREEN = 2,
PRINT_COLOR_CYAN = 3,
PRINT_COLOR_RED = 4,
PRINT_COLOR_MAGENTA = 5,
PRINT_COLOR_BROWN = 6,
PRINT_COLOR_LIGHT_GRAY = 7,
PRINT_COLOR_DARK_GRAY = 8,
PRINT_COLOR_LIGHT_BLUE = 9,
PRINT_COLOR_LIGHT_GREEN = 10,
PRINT_COLOR_LIGHT_CYAN = 11,
PRINT_COLOR_LIGHT_RED = 12,
PRINT_COLOR_PINK = 13,
PRINT_COLOR_YELLOW = 14,
PRINT_COLOR_WHITE = 15,
};
const static int NUM_COLS = 80;
const static int NUM_ROWS = 25;
struct Char {
char character;
char color;
};
void clear_row(int row);
void clear_all();
void print_newline();
void print_char(char character);
void print_set_color(char foreground, char background);
void print_str(char* str);
void set_cursor_pos(int col, int row);
void kernel_msg_ok(char* msg);
#endif

10
old/src/kernel/strings.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef STRINGS_H
#define STRINGS_H
void itoa(int n, char str[]);
void strrev(char s[]);
int strlen(char s[]);
char* strcpy(char* strDest, const char* strSrc);
char* strcnc(char* str1, char* str2);
#endif

25
old/src/kernel/util.c Normal file
View File

@ -0,0 +1,25 @@
#include "util.h"
void memcpy(char *source, char *dest, int nbytes) {
int i;
for (i = 0; i < nbytes; i++) {
*(dest + i) = *(source + i);
}
}
void memset(char *dest, char val, int len) {
char *temp = (char *)dest;
for(; len !=0; len--) *temp++ = val;
}
void int_to_ascii(int n, char str[]) {
int i, sign;
if ((sign = n) < 0) n = -n;
i = 0;
do {
str[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
if (sign < 0) str[i++] = '-';
str[i] = '\0';
}

8
old/src/kernel/util.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef UTIL_H
#define UTIL_H
void memcpy(char *source, char *dest, int nbytes);
void memset(char *dest, char val, int len);
void int_to_ascii(int n, char str[]);
#endif

Binary file not shown.

141
src/boot/entry.asm Normal file
View File

@ -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

17
src/boot/entry64.asm Normal file
View File

@ -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

16
src/boot/mb2_header.asm Normal file
View File

@ -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:

View File

@ -0,0 +1,7 @@
set timeout=5
set default=0
menuentry "shadeOS Development Build" {
multiboot2 /boot/shade.bin
boot
}

View File

@ -1,9 +1,5 @@
#include "./platform/drivers/ports.h" #include <shade/platform/ports.h>
#include "print.h" #include <shade/print.h>
#include "./platform/types.h"
#include "./platform/interrupts/int.h"
void dummy_test_entrypoint() {}
void kernel_welcome() { void kernel_welcome() {
print_str("Welcome to "); print_str("Welcome to ");
@ -31,7 +27,7 @@ void kernel_welcome() {
} }
// kMain // kMain
void main() { void kmain() {
// Initialize screen buffer // Initialize screen buffer
struct Char* buffer = (struct Char*) 0xb8000; struct Char* buffer = (struct Char*) 0xb8000;
@ -47,8 +43,4 @@ void main() {
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");
idt_init();
kernel_msg_ok("Interrupts initialized");
__asm__ __volatile__("int $2");
} }

View File

@ -1,54 +0,0 @@
%macro isr_err_stub 1
isr_stub_%+%1:
call exception_handler
iret
%endmacro
; if writing for 64-bit, use iretq instead
%macro isr_no_err_stub 1
isr_stub_%+%1:
call exception_handler
iret
%endmacro
extern exception_handler
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
isr_no_err_stub 4
isr_no_err_stub 5
isr_no_err_stub 6
isr_no_err_stub 7
isr_err_stub 8
isr_no_err_stub 9
isr_err_stub 10
isr_err_stub 11
isr_err_stub 12
isr_err_stub 13
isr_err_stub 14
isr_no_err_stub 15
isr_no_err_stub 16
isr_err_stub 17
isr_no_err_stub 18
isr_no_err_stub 19
isr_no_err_stub 20
isr_no_err_stub 21
isr_no_err_stub 22
isr_no_err_stub 23
isr_no_err_stub 24
isr_no_err_stub 25
isr_no_err_stub 26
isr_no_err_stub 27
isr_no_err_stub 28
isr_no_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
global isr_stub_table
isr_stub_table:
%assign i 0
%rep 32
dd isr_stub_%+i ; use DQ instead if targeting 64-bit
%assign i i+1
%endrep

View File

@ -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));
}

View File

@ -1,5 +1,5 @@
#include "print.h" #include <shade/print.h>
#include "./platform/drivers/ports.h" #include <shade/platform/ports.h>
int row = 0; int row = 0;
int col = 0; int col = 0;

View File

@ -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;

48
src/libc/strings.c Normal file
View File

@ -0,0 +1,48 @@
#include <strings.h>
#include <stddef.h>
void itoa(int n, char str[]) {
int i, sign;
if ((sign = n) < 0) n = -n;
i = 0;
do {
str[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
if (sign < 0) str[i++] = '-';
str[i] = '\0';
strrev(str);
}
/* K&R */
void strrev(char s[]) {
int c, i, j;
for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
/* K&R */
int strlen(char s[]) {
int i = 0;
while (s[i] != '\0') ++i;
return i;
}
char* strcpy(char* strDest, const char* strSrc) {
if ( (strDest == NULL) || (strSrc == NULL) ) {
return NULL;
}
char* strDestCopy = strDest;
while ((*strDest++=*strSrc++)!='\0');
return strDestCopy;
}
char* strcnc(char* str1, char* str2) {
char* str_dest;
strcpy(str_dest, str1);
strcpy(str_dest, str2);
}

30
src/linker.ld Normal file
View File

@ -0,0 +1,30 @@
ENTRY(entry_x86)
SECTIONS {
. = 1M;
.text BLOCK(4K) : ALIGN(4K)
{
*(.mb2_header)
*(.text)
}
/* Read-only data. */
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
/* Read-write data (initialized) */
.data BLOCK(4K) : ALIGN(4K)
{
*(.data)
}
/* Read-write data (uninitialized) and stack */
.bss BLOCK(4K) : ALIGN(4K)
{
*(COMMON)
*(.bss)
}
}