GDT finally works
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
disk.hdd
|
|
||||||
/limine
|
/limine
|
||||||
|
/iso_root
|
||||||
|
*.iso
|
||||||
|
55
Makefile
55
Makefile
@ -1,30 +1,41 @@
|
|||||||
.PHONY: all disk clean
|
.PHONY: all clean prepare cleanall iso
|
||||||
|
|
||||||
disk:
|
all:
|
||||||
|
make -C kernel all
|
||||||
|
|
||||||
|
prepare:
|
||||||
if [ ! -d limine ]; then \
|
if [ ! -d limine ]; then \
|
||||||
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1; \
|
mkdir limine; \
|
||||||
make -C limine; \
|
cd limine; \
|
||||||
|
git init; \
|
||||||
|
git remote add origin https://github.com/limine-bootloader/limine.git; \
|
||||||
|
git fetch origin 9246bb78f446962aae5b0a291db4be32f9866ba6; \
|
||||||
|
git reset --hard FETCH_HEAD; \
|
||||||
|
make; \
|
||||||
fi
|
fi
|
||||||
make -C kernel
|
|
||||||
rm -f disk.hdd
|
cleanall:
|
||||||
dd if=/dev/zero bs=1M count=0 seek=64 of=disk.hdd
|
make clean
|
||||||
PATH=$$PATH:/usr/sbin:/sbin sgdisk disk.hdd -n 1:2048 -t 1:ef00 -m 1
|
rm -rf limine
|
||||||
./limine/limine bios-install disk.hdd
|
|
||||||
mformat -i disk.hdd@@1M
|
|
||||||
mmd -i disk.hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine
|
|
||||||
mcopy -i disk.hdd@@1M kernel/mop2 ::/boot
|
|
||||||
mcopy -i disk.hdd@@1M limine.conf limine/limine-bios.sys ::/boot/limine
|
|
||||||
mcopy -i disk.hdd@@1M limine/BOOTX64.EFI ::/EFI/BOOT
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf limine disk.hdd
|
|
||||||
make -C kernel clean
|
make -C kernel clean
|
||||||
|
rm -f mop2.iso
|
||||||
|
|
||||||
all: disk
|
iso:
|
||||||
|
rm -rf iso_root
|
||||||
run:
|
mkdir -p iso_root/boot
|
||||||
qemu-system-x86_64 \
|
cp -v kernel/mop2 iso_root/boot
|
||||||
-d guest_errors \
|
mkdir -p iso_root/boot/limine
|
||||||
-serial stdio \
|
cp -v limine.conf limine/limine-bios.sys limine/limine-bios-cd.bin \
|
||||||
-hda disk.hdd
|
limine/limine-uefi-cd.bin iso_root/boot/limine
|
||||||
|
mkdir -p iso_root/EFI/BOOT
|
||||||
|
cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT
|
||||||
|
cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT
|
||||||
|
xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin \
|
||||||
|
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
|
||||||
|
-apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \
|
||||||
|
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||||
|
iso_root -o mop2.iso
|
||||||
|
./limine/limine bios-install mop2.iso
|
||||||
|
|
||||||
|
1
kernel/.gitignore
vendored
1
kernel/.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
*.o
|
*.o
|
||||||
mop2
|
mop2
|
||||||
|
*.iso
|
||||||
|
@ -1,53 +1,36 @@
|
|||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
CC := x86_64-elf-gcc
|
ARCH ?= x86_64
|
||||||
LD := x86_64-elf-ld
|
|
||||||
|
|
||||||
override CFLAGS = -Wall \
|
CFLAGS := -ffreestanding -Wall -Wextra -g -fcommon
|
||||||
-Wextra \
|
|
||||||
-ffreestanding \
|
CFLAGS += -I. \
|
||||||
-fno-stack-protector \
|
|
||||||
-fno-stack-check \
|
|
||||||
-fno-lto \
|
|
||||||
-fno-PIC \
|
|
||||||
-ffunction-sections \
|
|
||||||
-fdata-sections \
|
|
||||||
-m64 \
|
|
||||||
-march=x86-64 \
|
|
||||||
-mabi=sysv \
|
|
||||||
-mno-80387 \
|
|
||||||
-mno-mmx \
|
|
||||||
-mno-sse \
|
|
||||||
-mno-sse2 \
|
|
||||||
-mno-red-zone \
|
|
||||||
-mcmodel=kernel \
|
|
||||||
-I. \
|
|
||||||
-I../limine \
|
-I../limine \
|
||||||
-DPRINTF_INCLUDE_CONFIG_H=1
|
-DPRINTF_INCLUDE_CONFIG_H=1
|
||||||
|
|
||||||
override LDFLAGS = \
|
LDFLAGS := -nostdlib -static -T arch/$(ARCH)/link.ld
|
||||||
-m elf_x86_64 \
|
|
||||||
-nostdlib \
|
|
||||||
-static \
|
|
||||||
-z max-page-size=0x1000 \
|
|
||||||
--gc-sections \
|
|
||||||
-T link.ld
|
|
||||||
|
|
||||||
override NASMFLAGS = \
|
include arch/$(ARCH)/$(ARCH).mk
|
||||||
-felf64 \
|
include extconf/extra.mk
|
||||||
-Wall \
|
|
||||||
-F dwarf -g
|
|
||||||
|
|
||||||
override SRCFILES := $(shell find -L . -type f 2>/dev/null | LC_ALL=C sort)
|
SRCFILES := $(wildcard *.c) \
|
||||||
override CFILES := $(filter %.c,$(SRCFILES))
|
$(wildcard printf/*.c) \
|
||||||
override ASFILES := $(filter %.asm,$(SRCFILES))
|
$(wildcard bitmap/*.c) \
|
||||||
override OBJ := $(patsubst %.c,%.o,$(CFILES)) $(patsubst %.asm,%.o,$(ASFILES))
|
$(wildcard pmm/*.c) \
|
||||||
|
$(wildcard bootinfo/*.c) \
|
||||||
|
$(wildcard hal/*.c) \
|
||||||
|
$(wildcard hal/$(ARCH)/*.c) \
|
||||||
|
$(wildcard hal/$(ARCH)/*.S) \
|
||||||
|
$(wildcard *.S)
|
||||||
|
CFILES := $(filter %.c,$(SRCFILES))
|
||||||
|
ASFILES := $(filter %.S,$(SRCFILES))
|
||||||
|
OBJ := $(patsubst %.c,%.o,$(CFILES)) $(patsubst %.S,%.o,$(ASFILES))
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
%.o: %.asm
|
%.o: %.S
|
||||||
nasm $(NASMFLAGS) $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
all: mop2
|
all: mop2
|
||||||
|
|
||||||
|
85
kernel/ansi_colors.h
Normal file
85
kernel/ansi_colors.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#ifndef ANSI_COLORS_H_
|
||||||
|
#define ANSI_COLORS_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
*
|
||||||
|
* For more information, please refer to <https://unlicense.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Regular text
|
||||||
|
#define BLK "\e[0;30m"
|
||||||
|
#define RED "\e[0;31m"
|
||||||
|
#define GRN "\e[0;32m"
|
||||||
|
#define YEL "\e[0;33m"
|
||||||
|
#define BLU "\e[0;34m"
|
||||||
|
#define MAG "\e[0;35m"
|
||||||
|
#define CYN "\e[0;36m"
|
||||||
|
#define WHT "\e[0;37m"
|
||||||
|
|
||||||
|
//Regular bold text
|
||||||
|
#define BBLK "\e[1;30m"
|
||||||
|
#define BRED "\e[1;31m"
|
||||||
|
#define BGRN "\e[1;32m"
|
||||||
|
#define BYEL "\e[1;33m"
|
||||||
|
#define BBLU "\e[1;34m"
|
||||||
|
#define BMAG "\e[1;35m"
|
||||||
|
#define BCYN "\e[1;36m"
|
||||||
|
#define BWHT "\e[1;37m"
|
||||||
|
|
||||||
|
//Regular underline text
|
||||||
|
#define UBLK "\e[4;30m"
|
||||||
|
#define URED "\e[4;31m"
|
||||||
|
#define UGRN "\e[4;32m"
|
||||||
|
#define UYEL "\e[4;33m"
|
||||||
|
#define UBLU "\e[4;34m"
|
||||||
|
#define UMAG "\e[4;35m"
|
||||||
|
#define UCYN "\e[4;36m"
|
||||||
|
#define UWHT "\e[4;37m"
|
||||||
|
|
||||||
|
//Regular background
|
||||||
|
#define BLKB "\e[40m"
|
||||||
|
#define REDB "\e[41m"
|
||||||
|
#define GRNB "\e[42m"
|
||||||
|
#define YELB "\e[43m"
|
||||||
|
#define BLUB "\e[44m"
|
||||||
|
#define MAGB "\e[45m"
|
||||||
|
#define CYNB "\e[46m"
|
||||||
|
#define WHTB "\e[47m"
|
||||||
|
|
||||||
|
//High intensty background
|
||||||
|
#define BLKHB "\e[0;100m"
|
||||||
|
#define REDHB "\e[0;101m"
|
||||||
|
#define GRNHB "\e[0;102m"
|
||||||
|
#define YELHB "\e[0;103m"
|
||||||
|
#define BLUHB "\e[0;104m"
|
||||||
|
#define MAGHB "\e[0;105m"
|
||||||
|
#define CYNHB "\e[0;106m"
|
||||||
|
#define WHTHB "\e[0;107m"
|
||||||
|
|
||||||
|
//High intensty text
|
||||||
|
#define HBLK "\e[0;90m"
|
||||||
|
#define HRED "\e[0;91m"
|
||||||
|
#define HGRN "\e[0;92m"
|
||||||
|
#define HYEL "\e[0;93m"
|
||||||
|
#define HBLU "\e[0;94m"
|
||||||
|
#define HMAG "\e[0;95m"
|
||||||
|
#define HCYN "\e[0;96m"
|
||||||
|
#define HWHT "\e[0;97m"
|
||||||
|
|
||||||
|
//Bold high intensity text
|
||||||
|
#define BHBLK "\e[1;90m"
|
||||||
|
#define BHRED "\e[1;91m"
|
||||||
|
#define BHGRN "\e[1;92m"
|
||||||
|
#define BHYEL "\e[1;93m"
|
||||||
|
#define BHBLU "\e[1;94m"
|
||||||
|
#define BHMAG "\e[1;95m"
|
||||||
|
#define BHCYN "\e[1;96m"
|
||||||
|
#define BHWHT "\e[1;97m"
|
||||||
|
|
||||||
|
//Reset
|
||||||
|
#define reset "\e[0m"
|
||||||
|
#define CRESET "\e[0m"
|
||||||
|
#define COLOR_RESET "\e[0m"
|
||||||
|
|
||||||
|
#endif // ANSI_COLORS_H_
|
@ -1,56 +1,57 @@
|
|||||||
/* Tell the linker that we want an x86_64 ELF64 output file */
|
/* Tell the linker that we want an x86_64 ELF64 output file */
|
||||||
OUTPUT_FORMAT(elf64-x86-64)
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
|
OUTPUT_ARCH(i386:x86-64)
|
||||||
|
|
||||||
/* We want the symbol kmain to be our entry point */
|
/* We want the symbol _start to be our entry point */
|
||||||
ENTRY(kmain)
|
ENTRY(kmain)
|
||||||
|
|
||||||
/* Define the program headers we want so the bootloader gives us the right */
|
/* Define the program headers we want so the bootloader gives us the right */
|
||||||
/* MMU permissions; this also allows us to exert more control over the linking */
|
/* MMU permissions */
|
||||||
/* process. */
|
|
||||||
PHDRS
|
PHDRS
|
||||||
{
|
{
|
||||||
limine_requests PT_LOAD;
|
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
||||||
text PT_LOAD;
|
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
||||||
rodata PT_LOAD;
|
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
||||||
data PT_LOAD;
|
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
|
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
|
||||||
/* and because that is what the Limine spec mandates. */
|
/* and because that is what the Limine spec mandates. */
|
||||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||||
/* that is the beginning of the region. */
|
/* that is the beginning of the region. */
|
||||||
. = 0xffffffff80000000;
|
. = 0xffffffff80000000;
|
||||||
|
|
||||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
kernel_start = .;
|
||||||
.limine_requests : {
|
kernel_text_start = .;
|
||||||
KEEP(*(.limine_requests_start))
|
|
||||||
KEEP(*(.limine_requests))
|
|
||||||
KEEP(*(.limine_requests_end))
|
|
||||||
} :limine_requests
|
|
||||||
|
|
||||||
/* Move to the next memory page for .text */
|
|
||||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
} :text
|
} :text
|
||||||
|
kernel_text_end = .;
|
||||||
|
|
||||||
/* Move to the next memory page for .rodata */
|
/* Move to the next memory page for .rodata */
|
||||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
|
kernel_rodata_start = .;
|
||||||
.rodata : {
|
.rodata : {
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
} :rodata
|
} :rodata
|
||||||
|
kernel_rodata_end = .;
|
||||||
|
|
||||||
/* Move to the next memory page for .data */
|
/* Move to the next memory page for .data */
|
||||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
|
kernel_data_start = .;
|
||||||
.data : {
|
.data : {
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
} :data
|
} :data
|
||||||
|
|
||||||
|
/* Dynamic section for relocations, both in its own PHDR and inside data PHDR */
|
||||||
|
.dynamic : {
|
||||||
|
*(.dynamic)
|
||||||
|
} :data :dynamic
|
||||||
|
|
||||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||||
/* unnecessary zeros will be written to the binary. */
|
/* unnecessary zeros will be written to the binary. */
|
||||||
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
||||||
@ -59,10 +60,13 @@ SECTIONS
|
|||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
} :data
|
} :data
|
||||||
|
kernel_data_end = .;
|
||||||
|
|
||||||
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
*(.eh_frame*)
|
*(.eh_frame)
|
||||||
*(.note .note.*)
|
*(.note .note.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kernel_end = .;
|
||||||
}
|
}
|
22
kernel/arch/x86_64/x86_64.mk
Normal file
22
kernel/arch/x86_64/x86_64.mk
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
CC := x86_64-elf-gcc
|
||||||
|
LD := x86_64-elf-ld
|
||||||
|
|
||||||
|
CFLAGS += -m64 \
|
||||||
|
-fPIE \
|
||||||
|
-mno-80387 \
|
||||||
|
-mno-mmx \
|
||||||
|
-mno-sse \
|
||||||
|
-nostartfiles \
|
||||||
|
-nostdlib \
|
||||||
|
-mno-sse2 \
|
||||||
|
-mno-red-zone \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-stack-check \
|
||||||
|
-fno-lto
|
||||||
|
|
||||||
|
LDFLAGS += -m elf_x86_64 \
|
||||||
|
-pie \
|
||||||
|
--no-dynamic-linker \
|
||||||
|
-z text \
|
||||||
|
-z max-page-size=0x1000
|
||||||
|
|
14
kernel/banner.h
Normal file
14
kernel/banner.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef BANNER_H_
|
||||||
|
#define BANNER_H_
|
||||||
|
|
||||||
|
#define BANNER_TEXT \
|
||||||
|
"___ ___ _____ _____ ______ _ _ \n" \
|
||||||
|
"| \\/ | | _ / ___| | ___ \\ (_) | | \n" \
|
||||||
|
"| . . |_ _ | | | \\ `--. | |_/ / __ ___ _ ___ ___| |_ \n" \
|
||||||
|
"| |\\/| | | | | | | | |`--. \\ | __/ '__/ _ \\| |/ _ \\/ __| __|\n" \
|
||||||
|
"| | | | |_| | \\ \\_/ /\\__/ / | | | | | (_) | | __/ (__| |_ \n" \
|
||||||
|
"\\_| |_/\\__, | \\___/\\____/ \\_| |_| \\___/| |\\___|\\___|\\__|\n" \
|
||||||
|
" __/ | _/ | \n" \
|
||||||
|
" |___/ |__/ \n" \
|
||||||
|
|
||||||
|
#endif // BANNER_H_
|
117
kernel/bitmap/bitmap.c
Normal file
117
kernel/bitmap/bitmap.c
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "bitmap.h"
|
||||||
|
|
||||||
|
#define DIV_ROUNDUP(num, div) ((num + div - 1) / div)
|
||||||
|
|
||||||
|
void *bitmap_toptr(BitMap *bm, size_t block) {
|
||||||
|
uint8_t *ptr = (uint8_t *)(bm->mem_start + (block * BITMAP_BLOCK_SIZE));
|
||||||
|
return (void *)ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bitmap_toblock(BitMap *bm, void *ptr) {
|
||||||
|
uint8_t *p = ptr;
|
||||||
|
return (size_t)(p - bm->mem_start) / BITMAP_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bitmap_toblock_roundup(BitMap *bm, void *ptr) {
|
||||||
|
uint8_t *p = ptr;
|
||||||
|
return (size_t)DIV_ROUNDUP((size_t)(p - bm->mem_start), BITMAP_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bitmap_calcsize(size_t total) {
|
||||||
|
size_t nblocks = DIV_ROUNDUP(total, BITMAP_BLOCK_SIZE);
|
||||||
|
size_t nbytes = DIV_ROUNDUP(nblocks, 8);
|
||||||
|
return nbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bitmap_get(BitMap *bm, size_t block) {
|
||||||
|
size_t elem = block / BITMAP_BLOCKS_PER_BYTE;
|
||||||
|
size_t off = block % BITMAP_BLOCKS_PER_BYTE;
|
||||||
|
return (bm->map[elem] & (1 << off)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitmap_set(BitMap *bm, size_t block, bool value) {
|
||||||
|
size_t elem = block / BITMAP_BLOCKS_PER_BYTE;
|
||||||
|
size_t off = block % BITMAP_BLOCKS_PER_BYTE;
|
||||||
|
if (value) {
|
||||||
|
bm->map[elem] |= (1 << off);
|
||||||
|
} else {
|
||||||
|
bm->map[elem] &= ~(1 << off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitmap_markblocks(BitMap *bm, size_t start, size_t size, bool value) {
|
||||||
|
if (!value && start < bm->last_deep_frag) {
|
||||||
|
bm->last_deep_frag = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = start; i < start + size; i++) {
|
||||||
|
bitmap_set(bm, i, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bm->alloc_blocks += value ? size : -size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used) {
|
||||||
|
size_t base, size1;
|
||||||
|
|
||||||
|
if (is_used) {
|
||||||
|
base = bitmap_toblock(bm, baseptr);
|
||||||
|
size1 = DIV_ROUNDUP(size, BITMAP_BLOCK_SIZE);
|
||||||
|
} else {
|
||||||
|
base = bitmap_toblock(bm, baseptr);
|
||||||
|
size1 = size / BITMAP_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
bitmap_markblocks(bm, base, size1, is_used);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bitmap_freeregion(BitMap *bm, size_t blocks) {
|
||||||
|
size_t curregstart = bm->last_deep_frag;
|
||||||
|
size_t curregsize = 0;
|
||||||
|
for (size_t i = curregstart; i < bm->nblocks; i++) {
|
||||||
|
if (bitmap_get(bm, i)) {
|
||||||
|
curregsize = 0;
|
||||||
|
curregstart = i + 1;
|
||||||
|
} else {
|
||||||
|
if (blocks == 1) {
|
||||||
|
bm->last_deep_frag = curregstart + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
curregsize++;
|
||||||
|
if (curregsize >= blocks) {
|
||||||
|
return curregstart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BITMAP_INVALID_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *bitmap_alloc(BitMap *bm, size_t blocks) {
|
||||||
|
if (!blocks) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pickedreg = bitmap_freeregion(bm, blocks);
|
||||||
|
if (pickedreg == BITMAP_INVALID_BLOCK) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_markblocks(bm, pickedreg, blocks, 1);
|
||||||
|
return bitmap_toptr(bm, pickedreg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitmap_free(BitMap *bm, void *base, size_t blocks) {
|
||||||
|
bitmap_markregion(bm, base, BITMAP_BLOCK_SIZE * blocks, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bitmap_allocpageframe(BitMap *bm) {
|
||||||
|
size_t pickedreg = bitmap_freeregion(bm, 1);
|
||||||
|
bitmap_markblocks(bm, pickedreg, 1, 1);
|
||||||
|
return (bm->mem_start + (pickedreg * BITMAP_BLOCK_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitmap_freepageframe(BitMap *bm, void *addr) {
|
||||||
|
bitmap_markregion(bm, addr, BITMAP_BLOCK_SIZE * 1, 0);
|
||||||
|
}
|
36
kernel/bitmap/bitmap.h
Normal file
36
kernel/bitmap/bitmap.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef BITMAP_BITMAP_H_
|
||||||
|
#define BITMAP_BITMAP_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t *map;
|
||||||
|
size_t nblocks;
|
||||||
|
size_t nbytes;
|
||||||
|
size_t alloc_blocks;
|
||||||
|
size_t last_deep_frag;
|
||||||
|
uintptr_t mem_start;
|
||||||
|
bool init;
|
||||||
|
} BitMap;
|
||||||
|
|
||||||
|
#define BITMAP_BLOCKS_PER_BYTE 8
|
||||||
|
#define BITMAP_BLOCK_SIZE 0x1000
|
||||||
|
#define BITMAP_INVALID_BLOCK ((size_t)-1)
|
||||||
|
|
||||||
|
void *bitmap_toptr(BitMap *bm, size_t block);
|
||||||
|
size_t bitmap_toblock(BitMap *bm, void *ptr);
|
||||||
|
size_t bitmap_toblock_roundup(BitMap *bm, void *ptr);
|
||||||
|
size_t bitmap_calcsize(size_t total);
|
||||||
|
bool bitmap_get(BitMap *bm, size_t block);
|
||||||
|
void bitmap_set(BitMap *bm, size_t block, bool value);
|
||||||
|
void bitmap_markblocks(BitMap *bm, size_t start, size_t size, bool value);
|
||||||
|
void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used);
|
||||||
|
size_t bitmap_freeregion(BitMap *bm, size_t blocks);
|
||||||
|
void *bitmap_alloc(BitMap *bm, size_t blocks);
|
||||||
|
void bitmap_free(BitMap *bm, void *base, size_t blocks);
|
||||||
|
size_t bitmap_allocpageframe(BitMap *bm);
|
||||||
|
void bitmap_freepageframe(BitMap *bm, void *addr);
|
||||||
|
|
||||||
|
#endif // BITMAP_BITMAP_H_
|
82
kernel/bootinfo/bootinfo.c
Normal file
82
kernel/bootinfo/bootinfo.c
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <limine.h>
|
||||||
|
#include "bootinfo.h"
|
||||||
|
#include "hal/hal.h"
|
||||||
|
|
||||||
|
BootInfo BOOT_INFO;
|
||||||
|
|
||||||
|
static volatile struct limine_paging_mode_request PAGING_REQ = {
|
||||||
|
.id = LIMINE_PAGING_MODE_REQUEST,
|
||||||
|
.revision = 0,
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
.mode = LIMINE_PAGING_MODE_X86_64_4LVL,
|
||||||
|
#else
|
||||||
|
# error "Paging mode is unknown for this architecture"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static volatile struct limine_kernel_address_request KERN_ADDR_REQ = {
|
||||||
|
.id = LIMINE_KERNEL_ADDRESS_REQUEST, .revision = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static volatile struct limine_hhdm_request HHDM_REQ = {
|
||||||
|
.id = LIMINE_HHDM_REQUEST, .revision = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static volatile struct limine_memmap_request MEMMAP_REQ = {
|
||||||
|
.id = LIMINE_MEMMAP_REQUEST, .revision = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static volatile struct limine_smp_request SMP_REQ = {
|
||||||
|
.id = LIMINE_SMP_REQUEST, .revision = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static volatile struct limine_rsdp_request RSDP_REQ = {
|
||||||
|
.id = LIMINE_RSDP_REQUEST, .revision = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
void bootinfo_init(void) {
|
||||||
|
struct limine_paging_mode_response *pagingres = PAGING_REQ.response;
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
if (pagingres->mode != LIMINE_PAGING_MODE_X86_64_4LVL) {
|
||||||
|
#endif
|
||||||
|
hal_hang();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct limine_hhdm_response *hhdmres = HHDM_REQ.response;
|
||||||
|
BOOT_INFO.hhdm_off = hhdmres->offset;
|
||||||
|
|
||||||
|
struct limine_kernel_address_response *kernaddrres = KERN_ADDR_REQ.response;
|
||||||
|
BOOT_INFO.kern_virtbase = kernaddrres->virtual_base;
|
||||||
|
BOOT_INFO.kern_physbase = kernaddrres->physical_base;
|
||||||
|
|
||||||
|
struct limine_memmap_response *memmapres = MEMMAP_REQ.response;
|
||||||
|
BOOT_INFO.memmap_entries = memmapres->entries;
|
||||||
|
BOOT_INFO.memmap_entrycount = memmapres->entry_count;
|
||||||
|
|
||||||
|
BOOT_INFO.memmap_total = 0;
|
||||||
|
for (size_t i = 0; i < memmapres->entry_count; i++) {
|
||||||
|
struct limine_memmap_entry *entry = memmapres->entries[i];
|
||||||
|
if (entry->type != LIMINE_MEMMAP_RESERVED) {
|
||||||
|
BOOT_INFO.memmap_total += entry->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct limine_smp_response *smpres = SMP_REQ.response;
|
||||||
|
BOOT_INFO.smp = smpres;
|
||||||
|
|
||||||
|
BOOT_INFO.smp_bspindex = (uint64_t)(-1);
|
||||||
|
for (size_t i = 0; i < smpres->cpu_count; i++) {
|
||||||
|
struct limine_smp_info *entry = smpres->cpus[i];
|
||||||
|
if (entry->lapic_id == smpres->bsp_lapic_id) {
|
||||||
|
BOOT_INFO.smp_bspindex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (BOOT_INFO.smp_bspindex == (uint64_t)-1) {
|
||||||
|
hal_hang();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct limine_rsdp_response *rsdpres = RSDP_REQ.response;
|
||||||
|
BOOT_INFO.rsdp = (size_t)rsdpres->address - BOOT_INFO.hhdm_off;
|
||||||
|
}
|
33
kernel/bootinfo/bootinfo.h
Normal file
33
kernel/bootinfo/bootinfo.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef BOOTINFO_BOOTINFO_H_
|
||||||
|
#define BOOTINFO_BOOTINFO_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <limine.h>
|
||||||
|
|
||||||
|
extern uint64_t kernel_text_start, kernel_text_end,
|
||||||
|
kernel_rodata_start, kernel_rodata_end,
|
||||||
|
kernel_data_start, kernel_data_end,
|
||||||
|
kernel_start, kernel_end;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Higher Half Direct Map: https://github.com/dreamportdev/Osdev-Notes/blob/master/01_Build_Process/02_Boot_Protocols.md#limine-protocol
|
||||||
|
size_t hhdm_off;
|
||||||
|
size_t kern_virtbase;
|
||||||
|
size_t kern_physbase;
|
||||||
|
size_t rsdp;
|
||||||
|
size_t memmap_total;
|
||||||
|
uint64_t memmap_entrycount;
|
||||||
|
LIMINE_PTR(struct limine_memmap_entry **) memmap_entries;
|
||||||
|
LIMINE_PTR(struct limine_smp_response *) smp;
|
||||||
|
uint64_t smp_bspindex;
|
||||||
|
} BootInfo;
|
||||||
|
|
||||||
|
extern BootInfo BOOT_INFO;
|
||||||
|
|
||||||
|
#define IS_IN_HHDM(a) ((size_t)a >= BOOT_INFO.hhdm_off \
|
||||||
|
&& (size_t)a <= BOOT_INFO.hhdm_off + BOOT_INFO.memmap_total)
|
||||||
|
|
||||||
|
void bootinfo_init(void);
|
||||||
|
|
||||||
|
#endif // BOOTINFO_BOOTINFO_H_
|
@ -1,32 +0,0 @@
|
|||||||
#include <serial.h>
|
|
||||||
#include <com1.h>
|
|
||||||
|
|
||||||
#define COM1 0x3f8
|
|
||||||
|
|
||||||
void com1_init(void) {
|
|
||||||
serial_outb(COM1 + 1, 0x00); // no intr
|
|
||||||
serial_outb(COM1 + 3, 0x80); // enable DLAB
|
|
||||||
serial_outb(COM1 + 0, 0x01); // 115200 baudrate
|
|
||||||
serial_outb(COM1 + 1, 0x00);
|
|
||||||
serial_outb(COM1 + 3, 0x03); // 8N1
|
|
||||||
serial_outb(COM1 + 2, 0xc7); // fifo
|
|
||||||
serial_outb(COM1 + 4, 0x0b); // irqs enabled, rts/dsr set
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 com1_is_ready(void) {
|
|
||||||
return serial_inb(COM1 + 5) & 0x20;
|
|
||||||
}
|
|
||||||
|
|
||||||
void com1_putch(char c) {
|
|
||||||
while (!com1_is_ready());
|
|
||||||
serial_outb(COM1, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void com1_puts(char *s) {
|
|
||||||
while (*s) com1_putch(*s++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void putchar_(char c) {
|
|
||||||
com1_putch(c);
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
#ifndef COM1_H_
|
|
||||||
#define COM1_H_
|
|
||||||
|
|
||||||
void com1_init(void);
|
|
||||||
|
|
||||||
#endif // COM1_H_
|
|
6
kernel/compiler/attr.h
Normal file
6
kernel/compiler/attr.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef COMPILER_ATTR_H_
|
||||||
|
#define COMPILER_ATTR_H_
|
||||||
|
|
||||||
|
#define PACKED __attribute__((packed))
|
||||||
|
|
||||||
|
#endif // COMPILER_ATTR_H_
|
@ -1,12 +0,0 @@
|
|||||||
#ifndef ERRORS_H_
|
|
||||||
#define ERRORS_H_
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
#define E_OK 0
|
|
||||||
|
|
||||||
typedef int32 Error;
|
|
||||||
|
|
||||||
#define E_ISOK(e) ((e) == (E_OK))
|
|
||||||
|
|
||||||
#endif // ERRORS_H_
|
|
1
kernel/extconf/extra.mk
Normal file
1
kernel/extconf/extra.mk
Normal file
@ -0,0 +1 @@
|
|||||||
|
CFLAGS += -DKPRINTF_COLORS
|
19
kernel/hal/hal.h
Normal file
19
kernel/hal/hal.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef KERNEL_HAL_HAL_H_
|
||||||
|
#define KERNEL_HAL_HAL_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void hal_hang(void);
|
||||||
|
|
||||||
|
void hal_init(void);
|
||||||
|
void hal_intr_disable(void);
|
||||||
|
void hal_intr_enable(void);
|
||||||
|
void hal_memset(void *mem, uint8_t v, uint32_t size);
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
# define HAL_PAGE_SIZE 0x1000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // KERNEL_HAL_HAL_H_
|
9
kernel/hal/util.c
Normal file
9
kernel/hal/util.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
void hal_memset(void *mem, uint8_t v, uint32_t size) {
|
||||||
|
uint8_t *mem1 = mem;
|
||||||
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
|
mem1[i] = v;
|
||||||
|
}
|
||||||
|
}
|
6
kernel/hal/util.h
Normal file
6
kernel/hal/util.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef HAL_UTIL_H_
|
||||||
|
#define HAL_UTIL_H_
|
||||||
|
|
||||||
|
#define HAL_MEMSET(m, v, n) hal_memset((void *)(m), (v), (n))
|
||||||
|
|
||||||
|
#endif // HAL_UTIL_H_
|
94
kernel/hal/x86_64/gdt.c
Normal file
94
kernel/hal/x86_64/gdt.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "compiler/attr.h"
|
||||||
|
#include "hal/hal.h"
|
||||||
|
|
||||||
|
#define GDT_SIZE 5
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t limitlow;
|
||||||
|
uint16_t baselow;
|
||||||
|
uint8_t basemid;
|
||||||
|
uint8_t access;
|
||||||
|
uint8_t gran;
|
||||||
|
uint8_t basehigh;
|
||||||
|
} PACKED GdtEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t limit;
|
||||||
|
uint64_t base;
|
||||||
|
} PACKED GdtPtr;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GdtEntry old[5];
|
||||||
|
GdtEntry tsslow;
|
||||||
|
GdtEntry tsshigh;
|
||||||
|
} PACKED ExtendedGdt;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t resv0;
|
||||||
|
uint64_t rsp0;
|
||||||
|
uint64_t rsp1;
|
||||||
|
uint64_t rsp2;
|
||||||
|
uint64_t resv1;
|
||||||
|
uint64_t ist[7];
|
||||||
|
uint64_t resv2;
|
||||||
|
uint16_t resv3;
|
||||||
|
uint16_t iopb_off;
|
||||||
|
} PACKED Tss;
|
||||||
|
|
||||||
|
static Tss tss = {0};
|
||||||
|
static ExtendedGdt *curgdt = NULL;
|
||||||
|
|
||||||
|
#define KCODE 0x08
|
||||||
|
#define KDATA 0x10
|
||||||
|
#define UCODE 0x18
|
||||||
|
#define UDATA 0x20
|
||||||
|
#define TSS 0x28
|
||||||
|
|
||||||
|
#define GDT_PRESENT 0x80
|
||||||
|
#define GDT_TSS 0x89
|
||||||
|
|
||||||
|
static uint64_t gdt_curretbase(void) {
|
||||||
|
GdtPtr gdtr;
|
||||||
|
asm volatile("sgdt %0" : "=m"(gdtr));
|
||||||
|
return gdtr.base;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdt_setenty(GdtEntry *entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
|
||||||
|
entry->baselow = base & 0xffff;
|
||||||
|
entry->basemid = (base >> 16) & 0xff;
|
||||||
|
entry->basehigh = (base >> 24) & 0xff;
|
||||||
|
entry->limitlow = limit & 0xffff;
|
||||||
|
entry->gran = (limit >> 16) & 0x0f | (gran & 0xf0);
|
||||||
|
entry->access = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdt_init(void) {
|
||||||
|
uint64_t base = gdt_curretbase();
|
||||||
|
curgdt = (ExtendedGdt *)base;
|
||||||
|
|
||||||
|
HAL_MEMSET(&tss, 0, sizeof(tss));
|
||||||
|
tss.iopb_off = sizeof(tss);
|
||||||
|
|
||||||
|
uint64_t tss_base = (uint64_t)&tss;
|
||||||
|
uint32_t tss_limit = sizeof(tss) - 1;
|
||||||
|
|
||||||
|
gdt_setenty(&curgdt->tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0);
|
||||||
|
|
||||||
|
GdtEntry *tsshigh = &curgdt->tsshigh;
|
||||||
|
tsshigh->baselow = (tss_base >> 32) & 0xffff;
|
||||||
|
tsshigh->basemid = (tss_base >> 48) & 0xff;
|
||||||
|
tsshigh->basehigh = (tss_base >> 56) & 0xff;
|
||||||
|
tsshigh->access = 0;
|
||||||
|
tsshigh->gran = 0;
|
||||||
|
tsshigh->limitlow = 0;
|
||||||
|
|
||||||
|
GdtPtr gdtr;
|
||||||
|
asm volatile("sgdt %0" : "=m"(gdtr));
|
||||||
|
gdtr.limit = sizeof(ExtendedGdt) - 1;
|
||||||
|
asm volatile("lgdt %0" :: "m"(gdtr));
|
||||||
|
|
||||||
|
asm volatile("ltr %0" :: "r"((uint16_t)0x28));
|
||||||
|
}
|
||||||
|
|
6
kernel/hal/x86_64/gdt.h
Normal file
6
kernel/hal/x86_64/gdt.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef HAL_GDT_H_
|
||||||
|
#define HAL_GDT_H_
|
||||||
|
|
||||||
|
void gdt_init(void);
|
||||||
|
|
||||||
|
#endif // HAL_GDT_H_
|
21
kernel/hal/x86_64/hal.c
Normal file
21
kernel/hal/x86_64/hal.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "hal/hal.h"
|
||||||
|
#include "kprintf.h"
|
||||||
|
#include "serial.h"
|
||||||
|
#include "gdt.h"
|
||||||
|
|
||||||
|
void hal_init(void) {
|
||||||
|
if (!serial_init()) {
|
||||||
|
hal_hang(); // going further makes no sense
|
||||||
|
}
|
||||||
|
LOG("hal", "serial init\n");
|
||||||
|
gdt_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void hal_hang(void) {
|
||||||
|
for(;;) {
|
||||||
|
asm("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
kernel/hal/x86_64/intr.S
Normal file
9
kernel/hal/x86_64/intr.S
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.global hal_intr_enable
|
||||||
|
hal_intr_enable:
|
||||||
|
sti
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global hal_intr_disable
|
||||||
|
hal_intr_disable:
|
||||||
|
cli
|
||||||
|
ret
|
50
kernel/hal/x86_64/serial.c
Normal file
50
kernel/hal/x86_64/serial.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define SERIAL_PORT 0x3f8
|
||||||
|
|
||||||
|
extern uint8_t serial_inb(uint16_t port);
|
||||||
|
extern void serial_outb(uint16_t port, uint8_t value);
|
||||||
|
|
||||||
|
static int serial_received(void) {
|
||||||
|
return serial_inb(SERIAL_PORT + 5) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t serial_read(void) {
|
||||||
|
while (serial_received() == 0);
|
||||||
|
return serial_inb(SERIAL_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int serial_trans_empty(void) {
|
||||||
|
return serial_inb(SERIAL_PORT + 5) & 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void serial_write(uint8_t value) {
|
||||||
|
while (!serial_trans_empty());
|
||||||
|
serial_outb(SERIAL_PORT, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// REFERENCE: https://wiki.osdev.org/Serial_Ports
|
||||||
|
bool serial_init(void) {
|
||||||
|
serial_outb(SERIAL_PORT + 1, 0x00);
|
||||||
|
serial_outb(SERIAL_PORT + 3, 0x80);
|
||||||
|
serial_outb(SERIAL_PORT + 0, 0x03);
|
||||||
|
serial_outb(SERIAL_PORT + 1, 0x00);
|
||||||
|
serial_outb(SERIAL_PORT + 3, 0x03);
|
||||||
|
serial_outb(SERIAL_PORT + 2, 0xc7);
|
||||||
|
serial_outb(SERIAL_PORT + 4, 0x0b);
|
||||||
|
serial_outb(SERIAL_PORT + 4, 0x1e);
|
||||||
|
serial_outb(SERIAL_PORT + 0, 0xae);
|
||||||
|
|
||||||
|
if (serial_inb(SERIAL_PORT + 0) != 0xae) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_outb(SERIAL_PORT + 4, 0x0f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For printf library
|
||||||
|
void putchar_(char c) {
|
||||||
|
serial_write(c);
|
||||||
|
}
|
8
kernel/hal/x86_64/serial.h
Normal file
8
kernel/hal/x86_64/serial.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef HAL_SERIAL_H_
|
||||||
|
#define HAL_SERIAL_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
bool serial_init(void);
|
||||||
|
|
||||||
|
#endif // HAL_SERIAL_H_
|
13
kernel/hal/x86_64/serial1.S
Normal file
13
kernel/hal/x86_64/serial1.S
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.global serial_outb
|
||||||
|
serial_outb:
|
||||||
|
mov %di, %dx
|
||||||
|
mov %sil, %al
|
||||||
|
out %al, %dx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global serial_inb
|
||||||
|
serial_inb:
|
||||||
|
mov %di, %dx
|
||||||
|
in %dx, %al
|
||||||
|
movzx %al, %rax
|
||||||
|
ret
|
@ -1,42 +1,22 @@
|
|||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include <com1.h>
|
#include "kprintf.h"
|
||||||
#include <kprintf.h>
|
#include "banner.h"
|
||||||
|
#include "hal/hal.h"
|
||||||
// Halt and catch fire function.
|
#include "bootinfo/bootinfo.h"
|
||||||
static void hcf(void) {
|
#include "pmm/pmm.h"
|
||||||
for (;;) {
|
|
||||||
asm ("hlt");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile LIMINE_BASE_REVISION(3);
|
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests_start")))
|
|
||||||
static volatile LIMINE_REQUESTS_START_MARKER;
|
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests_end")))
|
|
||||||
static volatile LIMINE_REQUESTS_END_MARKER;
|
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_memmap_request memmap_request = {
|
|
||||||
.id = LIMINE_MEMMAP_REQUEST,
|
|
||||||
.revision = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
void limine_init(void) {
|
|
||||||
|
|
||||||
if (LIMINE_BASE_REVISION_SUPPORTED == false) {
|
|
||||||
hcf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
static volatile LIMINE_BASE_REVISION(2);
|
||||||
|
|
||||||
void kmain(void) {
|
void kmain(void) {
|
||||||
limine_init();
|
if (LIMINE_BASE_REVISION_SUPPORTED == false) {
|
||||||
com1_init();
|
hal_hang();
|
||||||
|
}
|
||||||
|
|
||||||
kprintf("Hello dupa!\n");
|
bootinfo_init();
|
||||||
|
pmm_init();
|
||||||
|
hal_init();
|
||||||
|
|
||||||
hcf();
|
kprintf(BANNER_TEXT "\n");
|
||||||
|
|
||||||
|
hal_hang();
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,18 @@
|
|||||||
#define kvsnprintf vsnprintf_
|
#define kvsnprintf vsnprintf_
|
||||||
#define kvprintf vprintf_
|
#define kvprintf vprintf_
|
||||||
|
|
||||||
|
#ifdef KPRINTF_COLORS
|
||||||
|
# include "ansi_colors.h"
|
||||||
|
# define LOG(component, fmt, ...) kprintf(CRESET "[" CYN component CRESET "]: " fmt, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
# define LOG(component, fmt, ...) kprintf("["component"]: "fmt, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef KPRINTF_COLORS
|
||||||
|
# include "ansi_colors.h"
|
||||||
|
# define ERR(component, fmt, ...) kprintf(CRESET "[" RED component CRESET "]: " fmt, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
# define ERR(component, fmt, ...) kprintf("["component"]: "fmt, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // KPRINTF_H_
|
#endif // KPRINTF_H_
|
||||||
|
71
kernel/pmm/pmm.c
Normal file
71
kernel/pmm/pmm.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <limine.h>
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
#include "kprintf.h"
|
||||||
|
#include "bitmap/bitmap.h"
|
||||||
|
#include "bootinfo/bootinfo.h"
|
||||||
|
|
||||||
|
#define _DIV_ROUNDUP(num, div) ((num + div - 1) / div)
|
||||||
|
|
||||||
|
PhysMem PHYS_MEM;
|
||||||
|
|
||||||
|
void pmm_init(void) {
|
||||||
|
PHYS_MEM.spinlock = SPINLOCK_INIT();
|
||||||
|
|
||||||
|
BitMap *bm = &PHYS_MEM.self;
|
||||||
|
bm->init = false;
|
||||||
|
|
||||||
|
bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE);
|
||||||
|
bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8);
|
||||||
|
|
||||||
|
struct limine_memmap_entry *memmap_ent = NULL;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) {
|
||||||
|
struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i];
|
||||||
|
if (entry->type != LIMINE_MEMMAP_USABLE || entry->length < bm->nbytes) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memmap_ent = entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!memmap_ent) {
|
||||||
|
ERR("hal/pmm", "required memory: {%lx}\n", bm->nbytes);
|
||||||
|
hal_hang();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t physbegin = memmap_ent->base;
|
||||||
|
bm->map = (uint8_t *)(physbegin + BOOT_INFO.hhdm_off);
|
||||||
|
|
||||||
|
HAL_MEMSET(bm->map, 0xff, bm->nbytes);
|
||||||
|
for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) {
|
||||||
|
struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i];
|
||||||
|
// mark usable as 0 and unusable as 1
|
||||||
|
bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_markregion(bm, (void *)physbegin, bm->nbytes, 1);
|
||||||
|
bm->alloc_blocks = 0;
|
||||||
|
|
||||||
|
LOG("hal/pmm", "phys bitmap init 0x%lx, size = 0x%lx\n", physbegin, bm->nbytes);
|
||||||
|
bm->init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pmm_alloc(size_t pages) {
|
||||||
|
SPINLOCK_ACQUIRE(&PHYS_MEM.spinlock);
|
||||||
|
uintptr_t phys = (uintptr_t)bitmap_alloc(&PHYS_MEM.self, pages);
|
||||||
|
SPINLOCK_RELEASE(&PHYS_MEM.spinlock);
|
||||||
|
|
||||||
|
if (!phys) {
|
||||||
|
ERR("hal/pmm", "phys memory ran out\n");
|
||||||
|
hal_hang();
|
||||||
|
}
|
||||||
|
return (void *)phys;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_free(uintptr_t ptr, size_t pages) {
|
||||||
|
SPINLOCK_ACQUIRE(&PHYS_MEM.spinlock);
|
||||||
|
bitmap_markregion(&PHYS_MEM.self, (void *)ptr, pages * BITMAP_BLOCK_SIZE, 0);
|
||||||
|
SPINLOCK_RELEASE(&PHYS_MEM.spinlock);
|
||||||
|
}
|
20
kernel/pmm/pmm.h
Normal file
20
kernel/pmm/pmm.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef PMM_PMM_H_
|
||||||
|
#define PMM_PMM_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "spinlock.h"
|
||||||
|
#include "bitmap/bitmap.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SpinLock spinlock;
|
||||||
|
BitMap self;
|
||||||
|
} PhysMem;
|
||||||
|
|
||||||
|
extern PhysMem PHYS_MEM;
|
||||||
|
|
||||||
|
void pmm_init(void);
|
||||||
|
void *pmm_alloc(size_t pages);
|
||||||
|
void pmm_free(uintptr_t ptr, size_t pages);
|
||||||
|
|
||||||
|
#endif // PMM_PMM_H_
|
@ -1,14 +0,0 @@
|
|||||||
global serial_outb
|
|
||||||
serial_outb:
|
|
||||||
mov dx, di
|
|
||||||
mov al, sil
|
|
||||||
out dx, al
|
|
||||||
ret
|
|
||||||
|
|
||||||
global serial_inb
|
|
||||||
serial_inb:
|
|
||||||
mov dx, di
|
|
||||||
in al, dx
|
|
||||||
movzx rax, al
|
|
||||||
ret
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef SERIAL_H_
|
|
||||||
#define SERIAL_H_
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
void serial_outb(uint16 port, uint8 value);
|
|
||||||
uint8 serial_inb(uint16 port);
|
|
||||||
|
|
||||||
#endif // SERIAL_H_
|
|
31
kernel/spinlock.h
Normal file
31
kernel/spinlock.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef SPINLOCK_SPINLOCK_H_
|
||||||
|
#define SPINLOCK_SPINLOCK_H_
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include "hal/hal.h"
|
||||||
|
|
||||||
|
typedef atomic_bool SpinLock;
|
||||||
|
|
||||||
|
// Spin more efficiently - cpu dependant
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
# define SPINLOCK_HINT() asm volatile("pause")
|
||||||
|
#else
|
||||||
|
# define SPINLOCK_HINT()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SPINLOCK_ACQUIRE(sl) \
|
||||||
|
do { \
|
||||||
|
bool __unlocked = false; \
|
||||||
|
while (!atomic_compare_exchange_weak((sl), &__unlocked, true)) { \
|
||||||
|
SPINLOCK_HINT(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define SPINLOCK_RELEASE(sl) \
|
||||||
|
do { \
|
||||||
|
atomic_store((sl), false); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define SPINLOCK_INIT() false
|
||||||
|
|
||||||
|
#endif // SPINLOCK_SPINLOCK_H_
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef TYPES_H_
|
|
||||||
#define TYPES_H_
|
|
||||||
|
|
||||||
#define NULL ((void *)0)
|
|
||||||
|
|
||||||
typedef char int8;
|
|
||||||
typedef unsigned char uint8;
|
|
||||||
typedef short int16;
|
|
||||||
typedef unsigned short uint16;
|
|
||||||
typedef int int32;
|
|
||||||
typedef unsigned int uint32;
|
|
||||||
typedef long long int64;
|
|
||||||
typedef unsigned long long uint64;
|
|
||||||
|
|
||||||
#endif // TYPES_H_
|
|
3
run/qemu-x86_64.sh
Executable file
3
run/qemu-x86_64.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
qemu-system-x86_64 -m 4g -cdrom mop2.iso -boot d -serial stdio $@
|
Reference in New Issue
Block a user