switch bootloader protocol to stivale2, os now 64-bit (very buggy because i still havent updated the GDT and IDT) and on the higher half, framebuffer, drawing text on the framebuffer with a font loaded from a psf file
This commit is contained in:
parent
e46c2dbf0a
commit
ef1ee78320
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -3,4 +3,7 @@ workspace.code-workspace
|
|||
*.o
|
||||
*.bin
|
||||
*.iso
|
||||
disk.img
|
||||
*.elf
|
||||
*.img
|
||||
sysroot/
|
||||
*.log
|
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
[submodule "limine"]
|
||||
path = limine
|
||||
url = https://github.com/limine-bootloader/limine.git
|
||||
branch = v2.0-branch-binary
|
95
Makefile
95
Makefile
|
@ -1,47 +1,68 @@
|
|||
TARGET = i686-elf
|
||||
ARCH = i386
|
||||
CC = $(TARGET)-gcc
|
||||
STRIP = $(TARGET)-strip
|
||||
KERNEL := hhhos.elf
|
||||
ISO := hhhos.iso
|
||||
|
||||
CC = x86_64-elf-gcc
|
||||
NASM = nasm
|
||||
QEMU = qemu-system-i386
|
||||
MKDIR_P = mkdir -p
|
||||
|
||||
# User controllable CFLAGS.
|
||||
CFLAGS = -Wall -Wextra -O3 -pipe
|
||||
NASMFLAGS = -felf64
|
||||
|
||||
# Internal link flags that should not be changed by the user.
|
||||
INTERNALLDFLAGS := \
|
||||
-fno-pic -fpie \
|
||||
-Wl,-static,-pie,--no-dynamic-linker,-ztext \
|
||||
-static-pie \
|
||||
-nostdlib \
|
||||
-Tlinker.ld \
|
||||
-z max-page-size=0x1000
|
||||
|
||||
# Internal C flags that should not be changed by the user.
|
||||
INTERNALCFLAGS := \
|
||||
-Iinclude \
|
||||
-std=gnu11 \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
-fno-pic -fpie \
|
||||
-mno-80387 \
|
||||
-mno-mmx \
|
||||
-mno-3dnow \
|
||||
-mno-sse \
|
||||
-mno-sse2 \
|
||||
-mno-red-zone
|
||||
|
||||
# Use find to glob all *.c files in the directory and extract the object names.
|
||||
CFILES := $(shell find ./arch -type f -name '*.c')
|
||||
OBJ := $(CFILES:.c=.o)
|
||||
OBJ += font.o
|
||||
|
||||
CFLAGS += -std=gnu18 -ffreestanding -O2 -Wall -Wextra -mgeneral-regs-only
|
||||
LDFLAGS += -ffreestanding -O2 -nostdlib -lgcc
|
||||
NASMFLAGS += -felf32
|
||||
# Targets that do not actually build a file of the same name.
|
||||
.PHONY: all clean run
|
||||
|
||||
BIN = sysroot/boot/hhhos.bin
|
||||
ISO = build/HhhOS.iso
|
||||
run: $(ISO)
|
||||
qemu-system-x86_64 -cdrom $(ISO) -serial file:serial.log -drive id=disk,file=build/disk.img,if=none,format=raw -device ide-hd,drive=disk,bus=ide.0
|
||||
|
||||
DIRS = build build/boot build/std build/drivers build/drivers/terminal build/drivers/idt build/drivers/device build/drivers/keyboard build/drivers/pic build/drivers/ide
|
||||
$(ISO): $(KERNEL)
|
||||
mkdir -p sysroot
|
||||
cp -v $(KERNEL) limine.cfg limine/limine.sys limine/limine-cd.bin limine/limine-eltorito-efi.bin sysroot/
|
||||
xorriso -as mkisofs -b limine-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table \
|
||||
--efi-boot limine-eltorito-efi.bin -efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||
sysroot -o $(ISO)
|
||||
|
||||
OBJS = build/boot/boot.o build/boot/kernel.o build/std/string.o build/drivers/terminal/terminal.o build/drivers/idt/idt.o \
|
||||
build/drivers/idt/isr.o build/std/util.o build/drivers/device/device.o build/drivers/keyboard/keyboard.o build/drivers/pic/pic.o \
|
||||
build/drivers/ide/ide.o build/std/stdio.o
|
||||
# Default target.
|
||||
all: $(KERNEL)
|
||||
|
||||
ARCHDIR = arch/$(ARCH)/
|
||||
# Link rules for the final kernel executable.
|
||||
$(KERNEL): $(OBJ)
|
||||
$(CC) $(OBJ) -o $@ $(INTERNALLDFLAGS)
|
||||
|
||||
.PHONY: all run clean build
|
||||
# Compilation rules for *.c files.
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(INTERNALCFLAGS) -c $< -o $@
|
||||
|
||||
dirs:
|
||||
${MKDIR_P} ${DIRS}
|
||||
|
||||
all: dirs $(BIN)
|
||||
|
||||
run: $(ISO)
|
||||
$(QEMU) -cdrom $(ISO) -drive id=disk,file=build/disk.img,if=none,format=raw -device ide-hd,drive=disk,bus=ide.0
|
||||
|
||||
$(ISO): dirs $(BIN)
|
||||
grub-mkrescue -o $(ISO) sysroot
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) -T linker.ld -o $@ $^ $(LDFLAGS)
|
||||
|
||||
build/%.o: $(ARCHDIR)%.c
|
||||
$(CC) -c $(CFLAGS) -Iinclude -o $@ $<
|
||||
|
||||
build/%.o: $(ARCHDIR)%.asm
|
||||
$(NASM) $(NASMFLAGS) -o $@ $<
|
||||
font.o:
|
||||
objcopy -O elf64-x86-64 -B i386 -I binary font.psfu font.o
|
||||
|
||||
# Remove object files and the final executable.
|
||||
clean:
|
||||
rm -rf $(OBJS) $(BIN) $(ISO)
|
||||
rm -rf $(KERNEL) $(OBJ) $(ISO)
|
41
arch/i386/boot/asm.asm
Normal file
41
arch/i386/boot/asm.asm
Normal file
|
@ -0,0 +1,41 @@
|
|||
.intel_syntax noprefix
|
||||
|
||||
.rodata
|
||||
gdt:
|
||||
.null:
|
||||
dq 0x0
|
||||
.code:
|
||||
dw 0xffff
|
||||
dw 0x0000
|
||||
db 0x00
|
||||
db 10011010b
|
||||
db 11001111b
|
||||
db 0x00
|
||||
.data:
|
||||
dw 0xffff
|
||||
dw 0x0000
|
||||
db 0x00
|
||||
db 10010010b
|
||||
db 11001111b
|
||||
db 0x00
|
||||
.end:
|
||||
.descriptor:
|
||||
dw .end - gdt - 1
|
||||
dd gdt
|
||||
|
||||
.text
|
||||
.global gdt_load
|
||||
|
||||
gdt_load:
|
||||
push eax
|
||||
lgdt [gdt.descriptor]
|
||||
jmp 0x08:.loaded_cs
|
||||
.loaded_cs:
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
pop eax
|
||||
ret
|
|
@ -1,160 +0,0 @@
|
|||
; Declare constants for the multiboot header.
|
||||
MBALIGN equ 1 << 0 ; align loaded modules on page boundaries
|
||||
MEMINFO equ 1 << 1 ; provide memory map
|
||||
FLAGS equ MBALIGN | MEMINFO ; this is the Multiboot 'flag' field
|
||||
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
|
||||
CHECKSUM equ -(MAGIC + FLAGS) ; checksum of above, to prove we are multiboot
|
||||
|
||||
; Declare a multiboot header that marks the program as a kernel. These are magic
|
||||
; values that are documented in the multiboot standard. The bootloader will
|
||||
; search for this signature in the first 8 KiB of the kernel file, aligned at a
|
||||
; 32-bit boundary. The signature is in its own section so the header can be
|
||||
; forced to be within the first 8 KiB of the kernel file.
|
||||
section .multiboot
|
||||
align 4
|
||||
dd MAGIC
|
||||
dd FLAGS
|
||||
dd CHECKSUM
|
||||
|
||||
; The multiboot standard does not define the value of the stack pointer register
|
||||
; (esp) and it is up to the kernel to provide a stack. This allocates room for a
|
||||
; small stack by creating a symbol at the bottom of it, then allocating 16384
|
||||
; bytes for it, and finally creating a symbol at the top. The stack grows
|
||||
; downwards on x86. The stack is in its own section so it can be marked nobits,
|
||||
; which means the kernel file is smaller because it does not contain an
|
||||
; uninitialized stack. The stack on x86 must be 16-byte aligned according to the
|
||||
; System V ABI standard and de-facto extensions. The compiler will assume the
|
||||
; stack is properly aligned and failure to align the stack will result in
|
||||
; undefined behavior.
|
||||
section .bss
|
||||
align 16
|
||||
stack_bottom:
|
||||
resb 16384 ; 16 KiB
|
||||
stack_top:
|
||||
|
||||
section .rodata
|
||||
gdt:
|
||||
.null:
|
||||
dq 0x0
|
||||
.code:
|
||||
dw 0xffff
|
||||
dw 0x0000
|
||||
db 0x00
|
||||
db 10011010b
|
||||
db 11001111b
|
||||
db 0x00
|
||||
.data:
|
||||
dw 0xffff
|
||||
dw 0x0000
|
||||
db 0x00
|
||||
db 10010010b
|
||||
db 11001111b
|
||||
db 0x00
|
||||
.end:
|
||||
.descriptor:
|
||||
dw .end - gdt - 1
|
||||
dd gdt
|
||||
code_segment equ gdt.code - gdt
|
||||
data_segment equ gdt.data - gdt
|
||||
|
||||
; The linker script specifies _start as the entry point to the kernel and the
|
||||
; bootloader will jump to this position once the kernel has been loaded. It
|
||||
; doesn't make sense to return from this function as the bootloader is gone.
|
||||
; Declare _start as a function symbol with the given symbol size.
|
||||
section .text
|
||||
global _start:function (_start.end - _start)
|
||||
|
||||
gdt_load:
|
||||
push eax
|
||||
lgdt [gdt.descriptor]
|
||||
jmp 0x08:.loaded_cs
|
||||
.loaded_cs:
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
pop eax
|
||||
ret
|
||||
|
||||
global load_page_directory
|
||||
load_page_directory:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, [esp + 8]
|
||||
mov cr3, eax
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
global enable_paging
|
||||
enable_paging:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, cr0
|
||||
or eax, 80000001h
|
||||
mov cr0, eax
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
_start:
|
||||
; The bootloader has loaded us into 32-bit protected mode on a x86
|
||||
; machine. Interrupts are disabled. Paging is disabled. The processor
|
||||
; state is as defined in the multiboot standard. The kernel has full
|
||||
; control of the CPU. The kernel can only make use of hardware features
|
||||
; and any code it provides as part of itself. There's no printf
|
||||
; function, unless the kernel provides its own <stdio.h> header and a
|
||||
; printf implementation. There are no security restrictions, no
|
||||
; safeguards, no debugging mechanisms, only what the kernel provides
|
||||
; itself. It has absolute and complete power over the machine.
|
||||
|
||||
; To set up a stack, we set the esp register to point to the top of our
|
||||
; stack (as it grows downwards on x86 systems). This is necessarily done
|
||||
; in assembly as languages such as C cannot function without a stack.
|
||||
mov esp, stack_top
|
||||
|
||||
;now enable SSE and the like
|
||||
mov eax, cr0
|
||||
and ax, 0xFFFB ;clear coprocessor emulation CR0.EM
|
||||
or ax, 0x2 ;set coprocessor monitoring CR0.MP
|
||||
mov cr0, eax
|
||||
mov eax, cr4
|
||||
or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
|
||||
mov cr4, eax
|
||||
|
||||
; This is a good place to initialize crucial processor state before the
|
||||
; high-level kernel is entered. It's best to minimize the early
|
||||
; environment where crucial features are offline. Note that the
|
||||
; processor is not fully initialized yet: Features such as floating
|
||||
; point instructions and instruction set extensions are not initialized
|
||||
; yet. The GDT should be loaded here. Paging should be enabled here.
|
||||
; C++ features such as global constructors and exceptions will require
|
||||
; runtime support to work as well.
|
||||
call gdt_load
|
||||
|
||||
; Enter the high-level kernel. The ABI requires the stack is 16-byte
|
||||
; aligned at the time of the call instruction (which afterwards pushes
|
||||
; the return pointer of size 4 bytes). The stack was originally 16-byte
|
||||
; aligned above and we've since pushed a multiple of 16 bytes to the
|
||||
; stack since (pushed 0 bytes so far) and the alignment is thus
|
||||
; preserved and the call is well defined.
|
||||
; note, that if you are building on Windows, C functions may have "_" prefix in assembly: _kmain
|
||||
extern kmain
|
||||
call kmain
|
||||
|
||||
; If the system has nothing more to do, put the computer into an
|
||||
; infinite loop. To do that:
|
||||
; 1) Disable interrupts with cli (clear interrupt enable in eflags).
|
||||
; They are already disabled by the bootloader, so this is not needed.
|
||||
; Mind that you might later enable interrupts and return from
|
||||
; kmain (which is sort of nonsensical to do).
|
||||
; 2) Wait for the next interrupt to arrive with hlt (halt instruction).
|
||||
; Since they are disabled, this will lock up the computer.
|
||||
; 3) Jump to the hlt instruction if it ever wakes up due to a
|
||||
; non-maskable interrupt occurring or due to system management mode.
|
||||
cli
|
||||
.hang: hlt
|
||||
jmp .hang
|
||||
.end:
|
|
@ -1,16 +1,119 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stivale2.h>
|
||||
#include <std/inline.h>
|
||||
#include <std/util.h>
|
||||
#include <stdbool.h>
|
||||
#include <std/stdio.h>
|
||||
#include <drivers/idt/isr.h>
|
||||
#include <drivers/keyboard/keyboard.h>
|
||||
#include <drivers/pic/pic.h>
|
||||
#include <drivers/device/device.h>
|
||||
#include <drivers/ide/ide.h>
|
||||
#include <framebuffer.h>
|
||||
#include <psf.h>
|
||||
|
||||
uint8_t is_running = 1;
|
||||
// We need to tell the stivale bootloader where we want our stack to be.
|
||||
// We are going to allocate our stack as an uninitialised array in .bss.
|
||||
static uint8_t stack[4096];
|
||||
void kmain();
|
||||
|
||||
bool is_running = true;
|
||||
int keyboard_descriptor = 0;
|
||||
int terminal_descriptor = 0;
|
||||
|
||||
// stivale2 uses a linked list of tags for both communicating TO the
|
||||
// bootloader, or receiving info FROM it. More information about these tags
|
||||
// is found in the stivale2 specification.
|
||||
|
||||
// We are now going to define a framebuffer header tag, which is mandatory when
|
||||
// using the stivale2 terminal.
|
||||
// This tag tells the bootloader that we want a graphical framebuffer instead
|
||||
// of a CGA-compatible text mode. Omitting this tag will make the bootloader
|
||||
// default to text mode, if available.
|
||||
static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = {
|
||||
// Same as above.
|
||||
.tag = {
|
||||
.identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID,
|
||||
.next = 0
|
||||
},
|
||||
// set all the framebuffer specifics to 0 for it to pick the best it can.
|
||||
.framebuffer_width = 800,
|
||||
.framebuffer_height = 600,
|
||||
.framebuffer_bpp = 32
|
||||
};
|
||||
|
||||
// The stivale2 specification says we need to define a "header structure".
|
||||
// This structure needs to reside in the .stivale2hdr ELF section in order
|
||||
// for the bootloader to find it. We use this __attribute__ directive to
|
||||
// tell the compiler to put the following structure in said section.
|
||||
__attribute__((section(".stivale2hdr"), used))
|
||||
static struct stivale2_header stivale_hdr = {
|
||||
// The entry_point member is used to specify an alternative entry
|
||||
// point that the bootloader should jump to instead of the executable's
|
||||
// ELF entry point. We do not care about that so we leave it zeroed.
|
||||
.entry_point = 0,
|
||||
// Let's tell the bootloader where our stack is.
|
||||
// We need to add the sizeof(stack) since in x86(_64) the stack grows
|
||||
// downwards.
|
||||
.stack = (uintptr_t)stack + sizeof(stack),
|
||||
// Bit 1, if set, causes the bootloader to return to us pointers in the
|
||||
// higher half, which we likely want.
|
||||
.flags = (1 << 1),
|
||||
// This header structure is the root of the linked list of header tags and
|
||||
// points to the first one in the linked list.
|
||||
.tags = (uintptr_t)&framebuffer_hdr_tag
|
||||
};
|
||||
|
||||
// We will now write a helper function which will allow us to scan for tags
|
||||
// that we want FROM the bootloader (structure tags).
|
||||
void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, uint64_t id) {
|
||||
struct stivale2_tag *current_tag = (void *)stivale2_struct->tags;
|
||||
for (;;) {
|
||||
// If the tag pointer is NULL (end of linked list), we did not find
|
||||
// the tag. Return NULL to signal this.
|
||||
if (current_tag == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check whether the identifier matches. If it does, return a pointer
|
||||
// to the matching tag.
|
||||
if (current_tag->identifier == id) {
|
||||
return current_tag;
|
||||
}
|
||||
|
||||
// Get a pointer to the next tag in the linked list and repeat.
|
||||
current_tag = (void *)current_tag->next;
|
||||
}
|
||||
}
|
||||
|
||||
framebuffer_t *framebuffer;
|
||||
|
||||
// The following will be our kernel's entry point.
|
||||
void _start(struct stivale2_struct *stivale2_struct) {
|
||||
struct stivale2_struct_tag_framebuffer *tagfb = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID);
|
||||
|
||||
if (tagfb == NULL) {
|
||||
printf("Requested stivale2 tags were not found, hanging...");
|
||||
for (;;) {
|
||||
asm ("hlt");
|
||||
}
|
||||
}
|
||||
framebuffer->address = (uint8_t*)tagfb->framebuffer_addr;
|
||||
framebuffer->width = tagfb->framebuffer_width;
|
||||
framebuffer->height = tagfb->framebuffer_height;
|
||||
framebuffer->depth = tagfb->framebuffer_bpp;
|
||||
framebuffer->pitch = tagfb->framebuffer_pitch;
|
||||
framebuffer->pixelwidth = tagfb->framebuffer_bpp / 8;
|
||||
|
||||
terminal_descriptor = terminal_initialize(framebuffer);
|
||||
printf("Terminal initialized, descriptor: %d\n", terminal_descriptor);
|
||||
|
||||
printf("Framebuffer | addr: %#X, width: %d, height: %d, depth: %d, pitch: %d\n", framebuffer->address, framebuffer->width, framebuffer->height, framebuffer->depth, framebuffer->pitch, framebuffer->pixelwidth);
|
||||
|
||||
kmain();
|
||||
}
|
||||
|
||||
void shell() {
|
||||
printf("hello yes");
|
||||
|
||||
|
@ -18,7 +121,7 @@ void shell() {
|
|||
printf("\n> ");
|
||||
|
||||
while (true) {
|
||||
unsigned char scancode = read(keyboard_descriptor, NULL);
|
||||
uint32_t scancode = (uint32_t)read(keyboard_descriptor, NULL);
|
||||
if (!scancode) continue;
|
||||
|
||||
bool special = true;
|
||||
|
@ -56,46 +159,55 @@ extern void enable_paging();
|
|||
|
||||
uint32_t page_directory[1024] __attribute__((aligned(4096)));
|
||||
uint32_t first_page_table[1024] __attribute__((aligned(4096)));
|
||||
uint32_t second_page_table[1024] __attribute__((aligned(4096)));
|
||||
|
||||
void kmain() {
|
||||
//set each entry to not present
|
||||
#define PAGE_PRESENT 1 << 0
|
||||
#define PAGE_WRITABLE 1 << 1
|
||||
#define PAGE_USER 1 << 2
|
||||
#define PAGE_WRITE_THROUGH 1 << 3
|
||||
#define PAGE_CACHE_DISABLE 1 << 4
|
||||
#define PAGE_ACCESSED 1 << 5
|
||||
#define PAGE_DIRTY 1 << 6
|
||||
#define PAGE_LARGE 1 << 7
|
||||
#define PAGE_GLOBAL 1 << 8
|
||||
/*
|
||||
void setup_paging() {
|
||||
// set each entry to not present
|
||||
for (uint32_t i = 0; i < 1024; i++) {
|
||||
// This sets the following flags to the pages:
|
||||
// Supervisor: Only kernel-mode can access them
|
||||
// Write Enabled: It can be both read from and written to
|
||||
// Not Present: The page table is not present
|
||||
page_directory[i] = 0x00000002;
|
||||
page_directory[i] = 0;
|
||||
}
|
||||
|
||||
// i holds the physical address where we want to start mapping these pages to.
|
||||
// in this case, we want to map these pages to the very beginning of memory.
|
||||
// we will fill all 1024 entries in the table, mapping 4 megabytes
|
||||
for (uint32_t i = 0; i < 1024; i++) {
|
||||
// As the address is page aligned, it will always leave 12 bits zeroed.
|
||||
// Those bits are used by the attributes ;)
|
||||
first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present.
|
||||
first_page_table[i] = (i * 0x1000) | PAGE_PRESENT | PAGE_WRITABLE;
|
||||
}
|
||||
|
||||
// attributes: supervisor level, read/write, present
|
||||
page_directory[0] = ((uint32_t)first_page_table) | 3;
|
||||
page_directory[0] = ((uint32_t)first_page_table) | PAGE_PRESENT | PAGE_WRITABLE;
|
||||
|
||||
load_page_directory(page_directory);
|
||||
load_page_directory((uint32_t)page_directory);
|
||||
enable_paging();
|
||||
}
|
||||
*/
|
||||
void kmain() {
|
||||
//setup_paging();
|
||||
|
||||
terminal_descriptor = terminal_initialize();
|
||||
printf("Terminal initialized, descriptor: %d\n", terminal_descriptor);
|
||||
printf("Preparing interrupts... ");
|
||||
pic_init();
|
||||
isr_install();
|
||||
printf("done\n");
|
||||
|
||||
printf("Preparing IDE driver... \n");
|
||||
printf("Searching for IDE devices... \n");
|
||||
ide_init();
|
||||
|
||||
fillrect(framebuffer, 500, 200, 100, 100, 0x00FFD5FF);
|
||||
fillrect(framebuffer, 600, 300, 100, 100, 0xFF00D5FF);
|
||||
|
||||
keyboard_descriptor = keyboard_init();
|
||||
printf("Keyboard ready, descriptor: %d\n", keyboard_descriptor);
|
||||
|
||||
printf("Preparing IDE driver... \n");
|
||||
printf("Searching for IDE devices... \n");
|
||||
ide_init();
|
||||
|
||||
printf("Are interrupts enabled? ");
|
||||
if (are_interrupts_enabled() == 1) {
|
||||
printf("yes\n");
|
||||
|
@ -103,8 +215,8 @@ void kmain() {
|
|||
printf("no\n");
|
||||
}
|
||||
|
||||
printf("kmain memory address: %p\n", kmain);
|
||||
printf("kmain memory address: %#X\n", (unsigned int)kmain);
|
||||
|
||||
printf("----------\n");
|
||||
shell();
|
||||
}
|
||||
}
|
||||
|
|
24
arch/i386/drivers/framebuffer.c
Normal file
24
arch/i386/drivers/framebuffer.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include <framebuffer.h>
|
||||
#include <std/stdio.h>
|
||||
|
||||
void putpixel(framebuffer_t *framebuffer, uint16_t x, uint16_t y, uint32_t color) {
|
||||
if (color & 255 == 0) return;
|
||||
uint64_t where = x * framebuffer->pixelwidth + y * framebuffer->pitch;
|
||||
framebuffer->address[where] = (color >> 8) & 255; // BLUE
|
||||
framebuffer->address[where + 1] = (color >> 16) & 255; // GREEN
|
||||
framebuffer->address[where + 2] = (color >> 24) & 255; // RED
|
||||
}
|
||||
|
||||
void fillrect(framebuffer_t *framebuffer, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color) {
|
||||
if (color & 255 == 0) return;
|
||||
uint8_t* where;
|
||||
uint32_t pw = framebuffer->pixelwidth;
|
||||
for (uint16_t i = y; i < h + y; i++) {
|
||||
where = (uint8_t*)((uint64_t)framebuffer->address + framebuffer->pitch * i);
|
||||
for (uint16_t j = x; j < w + x; j++) {
|
||||
where[j * pw] = (color >> 8) & 255; // BLUE
|
||||
where[j * pw + 1] = (color >> 16) & 255; // GREEN
|
||||
where[j * pw + 2] = (color >> 24) & 255; // RED
|
||||
}
|
||||
}
|
||||
}
|
|
@ -88,7 +88,7 @@ void ide_read_buffer(unsigned char channel, unsigned char reg,
|
|||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||
|
||||
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
|
||||
//asm("pushw %es; movw %ds, %ax; movw %ax, %es");
|
||||
|
||||
if (reg < 0x08)
|
||||
insl(channels[channel].base + reg - 0x00, buffer, quads);
|
||||
|
@ -99,7 +99,7 @@ void ide_read_buffer(unsigned char channel, unsigned char reg,
|
|||
else if (reg < 0x16)
|
||||
insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
|
||||
|
||||
asm("popw %es;");
|
||||
//asm("popw %es;");
|
||||
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||
|
|
|
@ -58,7 +58,6 @@ unsigned char keyboard_buffer_pop_key() {
|
|||
return scancode;
|
||||
}
|
||||
|
||||
|
||||
unsigned char keyboard_get_key_from_scancode(unsigned char scancode) {
|
||||
return kbdus[scancode];
|
||||
}
|
||||
|
@ -80,12 +79,12 @@ uint8_t keyboard_enabled(void) {
|
|||
return __kbd_enabled;
|
||||
}
|
||||
|
||||
void* keyboard_read(void* data) {
|
||||
return keyboard_buffer_pop_key();
|
||||
void* keyboard_read() {
|
||||
return (void*) keyboard_buffer_pop_key();
|
||||
}
|
||||
|
||||
void* keyboard_write(void* data) {
|
||||
return -1;
|
||||
void* keyboard_write() {
|
||||
return (void*) -1;
|
||||
}
|
||||
|
||||
int keyboard_init(void) {
|
||||
|
|
32
arch/i386/drivers/psf.c
Normal file
32
arch/i386/drivers/psf.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <psf.h>
|
||||
|
||||
// c is a unicode character, cx and cy are cursor position in characters
|
||||
void draw_psf_char(framebuffer_t *framebuffer, uint32_t c, uint16_t cx, uint16_t cy, uint32_t fg, uint32_t bg) {
|
||||
PSF_font *font = (PSF_font*)&_binary_font_psfu_start;
|
||||
// we need to know how many bytes encode one row
|
||||
int bytesperline = (font->width + 7) / 8;
|
||||
// get the glyph for the character. If there's no
|
||||
// glyph for a given character, we'll display the first glyph.
|
||||
uint8_t *glyph = (uint8_t*)&_binary_font_psfu_start + font->headersize +
|
||||
(c > 0 && c < font->numglyph ? c : 0) * font->bytesperglyph;
|
||||
// calculate the upper left corner on screen where we want to display.
|
||||
// we only do this once, and adjust the whereet later. This is faster.
|
||||
int where = (cy * font->height * framebuffer->pitch) + (cx * (font->width + 1) * 4);
|
||||
// finally display pixels according to the bitmap
|
||||
int x, y, line, mask;
|
||||
for (y = 0; y < font->height; y++) {
|
||||
// save the starting position of the line
|
||||
line = where;
|
||||
mask = 1 << (font->width - 1);
|
||||
// display a row
|
||||
for (x = 0; x < font->width; x++) {
|
||||
*((uint32_t*)(framebuffer->address + line)) = *((uint32_t*)glyph) & mask ? fg : bg;
|
||||
// adjust to the next pixel
|
||||
mask >>= 1;
|
||||
line += 4;
|
||||
}
|
||||
// adjust to the next line
|
||||
glyph += bytesperline;
|
||||
where += framebuffer->pitch;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#include <drivers/tar/tar.h>
|
||||
#include <std/util.h>
|
||||
#include <drivers/device/device.h>
|
||||
|
||||
/*
|
||||
struct tar_header* tar_seek(int fd, char filename[100]) {
|
||||
unsigned int i;
|
||||
unsigned int addr;
|
||||
|
@ -15,4 +15,5 @@ struct tar_header* tar_seek(int fd, char filename[100]) {
|
|||
addr += ((size / 512) + 1);
|
||||
if (size % 512) addr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -4,9 +4,10 @@
|
|||
size_t terminal_row;
|
||||
size_t terminal_column;
|
||||
uint8_t terminal_color;
|
||||
uint16_t* terminal_buffer;
|
||||
uint16_t *terminal_buffer;
|
||||
framebuffer_t *terminal_framebuffer;
|
||||
|
||||
void terminal_clear(void) {
|
||||
void terminal_clear() {
|
||||
for (size_t y = 0; y < VGA_HEIGHT; y++) {
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++) {
|
||||
const size_t index = y * VGA_WIDTH + x;
|
||||
|
@ -35,10 +36,11 @@ void* terminal_devwrite(void* data) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int terminal_initialize(void) {
|
||||
int terminal_initialize(framebuffer_t *terminal_fb) {
|
||||
terminal_framebuffer = terminal_fb;
|
||||
terminal_row = 0;
|
||||
terminal_column = 0;
|
||||
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||
terminal_color = vga_entry_color(VGA_COLOR_BLACK, VGA_COLOR_WHITE);
|
||||
terminal_buffer = (uint16_t*) 0xB8000;
|
||||
terminal_clear();
|
||||
|
||||
|
@ -70,7 +72,7 @@ void terminal_clearlines(size_t from, size_t to) {
|
|||
}
|
||||
}
|
||||
|
||||
void terminal_updatecursor(void) {
|
||||
void terminal_updatecursor() {
|
||||
size_t temp = terminal_row * VGA_WIDTH + terminal_column;
|
||||
outportb(0x3D4, 14);
|
||||
outportb(0x3D5, temp >> 8);
|
||||
|
@ -78,7 +80,7 @@ void terminal_updatecursor(void) {
|
|||
outportb(0x3D5, temp);
|
||||
}
|
||||
|
||||
void terminal_scrollup(void) {
|
||||
void terminal_scrollup() {
|
||||
for (size_t index = 0; index < VGA_WIDTH * (VGA_HEIGHT - 1); index++) {
|
||||
terminal_buffer[index] = terminal_buffer[index + VGA_WIDTH];
|
||||
}
|
||||
|
@ -92,17 +94,19 @@ void terminal_scrollup(void) {
|
|||
terminal_updatecursor();
|
||||
}
|
||||
|
||||
void terminal_checknewline(void) {
|
||||
void terminal_checknewline() {
|
||||
if (terminal_row >= VGA_HEIGHT - 1) {
|
||||
terminal_scrollup();
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
|
||||
terminal_buffer[y * VGA_WIDTH + x] = vga_entry(c, color);
|
||||
//terminal_buffer[y * VGA_WIDTH + x] = vga_entry(c, color);
|
||||
draw_psf_char(terminal_framebuffer, c, x, y, 0xFFFFFFFF, 0);
|
||||
}
|
||||
|
||||
void terminal_putchar(char c) {
|
||||
outportb(0x3F8, c); // log terminal to serial.log when running on qemu
|
||||
switch (c) {
|
||||
case '\b':
|
||||
if (--terminal_column < 0) {
|
||||
|
|
|
@ -13,6 +13,7 @@ extern "C" {
|
|||
|
||||
int keyboard_init(void);
|
||||
uint8_t keyboard_enabled(void);
|
||||
unsigned char keyboard_get_key_from_scancode(unsigned char scancode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <stdint.h>
|
||||
#include <std/string.h>
|
||||
#include <std/inline.h>
|
||||
#include <drivers/ide/ide.h>
|
||||
#include <psf.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -29,11 +31,11 @@ enum vga_color {
|
|||
VGA_COLOR_WHITE = 15,
|
||||
};
|
||||
|
||||
static inline uint8_t vga_entry_color(enum vga_color const fg, enum vga_color const bg) {
|
||||
return fg | bg << 4;
|
||||
static inline uint8_t vga_entry_color(const enum vga_color fg, const enum vga_color bg) {
|
||||
return fg | (bg << 4);
|
||||
}
|
||||
|
||||
static inline uint16_t vga_entry(unsigned char const uc, uint8_t const color) {
|
||||
static inline uint16_t vga_entry(const uint8_t uc, const uint8_t color) {
|
||||
return (uint16_t) uc | (uint16_t) color << 8;
|
||||
}
|
||||
|
||||
|
@ -43,25 +45,25 @@ static const size_t VGA_HEIGHT = 25;
|
|||
extern size_t terminal_row;
|
||||
extern size_t terminal_column;
|
||||
extern uint8_t terminal_color;
|
||||
extern uint16_t* terminal_buffer;
|
||||
extern uint16_t *terminal_buffer;
|
||||
|
||||
void terminal_clear(void);
|
||||
int terminal_initialize(void);
|
||||
void terminal_clear();
|
||||
int terminal_initialize(framebuffer_t *terminal_fb);
|
||||
void terminal_setcolor(uint8_t color);
|
||||
void terminal_clearline(size_t line);
|
||||
void terminal_clearlines(size_t from, size_t to);
|
||||
void terminal_updatecursor(void);
|
||||
void terminal_scrollup(void);
|
||||
void terminal_checknewline(void);
|
||||
void terminal_updatecursor();
|
||||
void terminal_scrollup();
|
||||
void terminal_checknewline();
|
||||
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y);
|
||||
void terminal_putchar(char c);
|
||||
void terminal_write(const char* data, size_t size);
|
||||
|
||||
static inline void terminal_writestring(const char* data) {
|
||||
static inline void terminal_writestring(const char *data) {
|
||||
terminal_write(data, strlen(data));
|
||||
}
|
||||
|
||||
static inline void terminal_writeline(const char* data) {
|
||||
static inline void terminal_writeline(const char *data) {
|
||||
terminal_writestring(data);
|
||||
terminal_putchar('\n');
|
||||
}
|
||||
|
|
24
include/framebuffer.h
Normal file
24
include/framebuffer.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t *address;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t depth;
|
||||
uint32_t pitch;
|
||||
uint32_t pixelwidth;
|
||||
} framebuffer_t;
|
||||
|
||||
void putpixel(framebuffer_t *framebuffer, uint16_t x, uint16_t y, uint32_t color);
|
||||
void fillrect(framebuffer_t *framebuffer, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
33
include/psf.h
Normal file
33
include/psf.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <framebuffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PSF_FONT_MAGIC 0x864ab572
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic; /* magic bytes to identify PSF */
|
||||
uint32_t version; /* zero */
|
||||
uint32_t headersize; /* whereet of bitmaps in file, 32 */
|
||||
uint32_t flags; /* 0 if there's no unicode table */
|
||||
uint32_t numglyph; /* number of glyphs */
|
||||
uint32_t bytesperglyph; /* size of each glyph */
|
||||
uint32_t height; /* height in pixels */
|
||||
uint32_t width; /* width in pixels */
|
||||
} PSF_font;
|
||||
|
||||
// these are linked using objcopy
|
||||
extern char _binary_font_psfu_start;
|
||||
extern char _binary_font_psfu_end;
|
||||
|
||||
// c is a unicode character, cx and cy are cursor position in characters
|
||||
void draw_psf_char(framebuffer_t *framebuffer, uint32_t c, uint16_t cx, uint16_t cy, uint32_t fg, uint32_t bg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -7,15 +7,15 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void outportb(uint16_t const port, uint8_t const val) {
|
||||
static inline void outportb(const uint16_t port, const uint8_t val) {
|
||||
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
|
||||
}
|
||||
|
||||
static inline void outportw(uint16_t const port, uint16_t const val) {
|
||||
static inline void outportw(const uint16_t port, const uint16_t val) {
|
||||
asm volatile ( "outw %0, %1" : : "a"(val), "Nd"(port) );
|
||||
}
|
||||
|
||||
static inline void outportl(uint16_t const port, uint32_t const val) {
|
||||
static inline void outportl(const uint16_t port, const uint32_t val) {
|
||||
asm volatile ( "outl %0, %1" : : "a"(val), "Nd"(port) );
|
||||
}
|
||||
|
||||
|
@ -23,19 +23,19 @@ static inline void outportsm(unsigned short port, unsigned char* data, unsigned
|
|||
asm volatile ("rep outsw" : "+S" (data), "+c" (size) : "d" (port));
|
||||
}
|
||||
|
||||
static inline uint8_t inportb(uint16_t const port) {
|
||||
static inline uint8_t inportb(const uint16_t port) {
|
||||
uint8_t ret;
|
||||
asm volatile ( "inb %1, %0" : "=a"(ret) : "Nd"(port) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint16_t inportw(uint16_t const port) {
|
||||
static inline uint16_t inportw(const uint16_t port) {
|
||||
uint16_t ret;
|
||||
asm volatile ( "inw %1, %0" : "=a"(ret) : "Nd"(port) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t inportl(uint16_t const port) {
|
||||
static inline uint32_t inportl(const uint16_t port) {
|
||||
uint32_t ret;
|
||||
asm volatile ( "inl %1, %0" : "=a"(ret) : "Nd"(port) );
|
||||
return ret;
|
||||
|
|
251
include/stivale2.h
Normal file
251
include/stivale2.h
Normal file
|
@ -0,0 +1,251 @@
|
|||
#ifndef __STIVALE__STIVALE2_H__
|
||||
#define __STIVALE__STIVALE2_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct stivale2_tag {
|
||||
uint64_t identifier;
|
||||
uint64_t next;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* --- Header --------------------------------------------------------------- */
|
||||
/* Information passed from the kernel to the bootloader */
|
||||
|
||||
struct stivale2_header {
|
||||
uint64_t entry_point;
|
||||
uint64_t stack;
|
||||
uint64_t flags;
|
||||
uint64_t tags;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_HEADER_TAG_FRAMEBUFFER_ID 0x3ecc1bc43d0f7971
|
||||
|
||||
struct stivale2_header_tag_framebuffer {
|
||||
struct stivale2_tag tag;
|
||||
uint16_t framebuffer_width;
|
||||
uint16_t framebuffer_height;
|
||||
uint16_t framebuffer_bpp;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_HEADER_TAG_FB_MTRR_ID 0x4c7bb07731282e00
|
||||
|
||||
#define STIVALE2_HEADER_TAG_TERMINAL_ID 0xa85d499b1823be72
|
||||
|
||||
struct stivale2_header_tag_terminal {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t flags;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_HEADER_TAG_SMP_ID 0x1ab015085f3273df
|
||||
|
||||
struct stivale2_header_tag_smp {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t flags;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_HEADER_TAG_5LV_PAGING_ID 0x932f477032007e8f
|
||||
|
||||
#define STIVALE2_HEADER_TAG_UNMAP_NULL_ID 0x92919432b16fe7e7
|
||||
|
||||
/* --- Struct --------------------------------------------------------------- */
|
||||
/* Information passed from the bootloader to the kernel */
|
||||
|
||||
struct stivale2_struct {
|
||||
#define STIVALE2_BOOTLOADER_BRAND_SIZE 64
|
||||
char bootloader_brand[STIVALE2_BOOTLOADER_BRAND_SIZE];
|
||||
|
||||
#define STIVALE2_BOOTLOADER_VERSION_SIZE 64
|
||||
char bootloader_version[STIVALE2_BOOTLOADER_VERSION_SIZE];
|
||||
|
||||
uint64_t tags;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_CMDLINE_ID 0xe5e76a1b4597a781
|
||||
|
||||
struct stivale2_struct_tag_cmdline {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t cmdline;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_MEMMAP_ID 0x2187f79e8612de07
|
||||
|
||||
#define STIVALE2_MMAP_USABLE 1
|
||||
#define STIVALE2_MMAP_RESERVED 2
|
||||
#define STIVALE2_MMAP_ACPI_RECLAIMABLE 3
|
||||
#define STIVALE2_MMAP_ACPI_NVS 4
|
||||
#define STIVALE2_MMAP_BAD_MEMORY 5
|
||||
#define STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE 0x1000
|
||||
#define STIVALE2_MMAP_KERNEL_AND_MODULES 0x1001
|
||||
#define STIVALE2_MMAP_FRAMEBUFFER 0x1002
|
||||
|
||||
struct stivale2_mmap_entry {
|
||||
uint64_t base;
|
||||
uint64_t length;
|
||||
uint32_t type;
|
||||
uint32_t unused;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct stivale2_struct_tag_memmap {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t entries;
|
||||
struct stivale2_mmap_entry memmap[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID 0x506461d2950408fa
|
||||
|
||||
#define STIVALE2_FBUF_MMODEL_RGB 1
|
||||
|
||||
struct stivale2_struct_tag_framebuffer {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t framebuffer_addr;
|
||||
uint16_t framebuffer_width;
|
||||
uint16_t framebuffer_height;
|
||||
uint16_t framebuffer_pitch;
|
||||
uint16_t framebuffer_bpp;
|
||||
uint8_t memory_model;
|
||||
uint8_t red_mask_size;
|
||||
uint8_t red_mask_shift;
|
||||
uint8_t green_mask_size;
|
||||
uint8_t green_mask_shift;
|
||||
uint8_t blue_mask_size;
|
||||
uint8_t blue_mask_shift;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_EDID_ID 0x968609d7af96b845
|
||||
|
||||
struct stivale2_struct_tag_edid {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t edid_size;
|
||||
uint8_t edid_information[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_FB_MTRR_ID 0x6bc1a78ebe871172
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_TERMINAL_ID 0xc2b3f4c3233b0974
|
||||
|
||||
struct stivale2_struct_tag_terminal {
|
||||
struct stivale2_tag tag;
|
||||
uint32_t flags;
|
||||
uint16_t cols;
|
||||
uint16_t rows;
|
||||
uint64_t term_write;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_MODULES_ID 0x4b6fe466aade04ce
|
||||
|
||||
struct stivale2_module {
|
||||
uint64_t begin;
|
||||
uint64_t end;
|
||||
|
||||
#define STIVALE2_MODULE_STRING_SIZE 128
|
||||
char string[STIVALE2_MODULE_STRING_SIZE];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct stivale2_struct_tag_modules {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t module_count;
|
||||
struct stivale2_module modules[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_RSDP_ID 0x9e1786930a375e78
|
||||
|
||||
struct stivale2_struct_tag_rsdp {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t rsdp;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_EPOCH_ID 0x566a7bed888e1407
|
||||
|
||||
struct stivale2_struct_tag_epoch {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t epoch;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_FIRMWARE_ID 0x359d837855e3858c
|
||||
|
||||
#define STIVALE2_FIRMWARE_BIOS (1 << 0)
|
||||
|
||||
struct stivale2_struct_tag_firmware {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t flags;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_EFI_SYSTEM_TABLE_ID 0x4bc5ec15845b558e
|
||||
|
||||
struct stivale2_struct_tag_efi_system_table {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t system_table;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_KERNEL_FILE_ID 0xe599d90c2975584a
|
||||
|
||||
struct stivale2_struct_tag_kernel_file {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t kernel_file;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_KERNEL_SLIDE_ID 0xee80847d01506c57
|
||||
|
||||
struct stivale2_struct_tag_kernel_slide {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t kernel_slide;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_SMBIOS_ID 0x274bd246c62bf7d1
|
||||
|
||||
struct stivale2_struct_tag_smbios {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t flags;
|
||||
uint64_t smbios_entry_32;
|
||||
uint64_t smbios_entry_64;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_SMP_ID 0x34d1d96339647025
|
||||
|
||||
struct stivale2_smp_info {
|
||||
uint32_t processor_id;
|
||||
uint32_t lapic_id;
|
||||
uint64_t target_stack;
|
||||
uint64_t goto_address;
|
||||
uint64_t extra_argument;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct stivale2_struct_tag_smp {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t flags;
|
||||
uint32_t bsp_lapic_id;
|
||||
uint32_t unused;
|
||||
uint64_t cpu_count;
|
||||
struct stivale2_smp_info smp_info[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_PXE_SERVER_INFO 0x29d1e96239247032
|
||||
|
||||
struct stivale2_struct_tag_pxe_server_info {
|
||||
struct stivale2_tag tag;
|
||||
uint32_t server_ip;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_MMIO32_UART 0xb813f9b8dbc78797
|
||||
|
||||
struct stivale2_struct_tag_mmio32_uart {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t addr;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_DTB 0xabb29bd49a2833fa
|
||||
|
||||
struct stivale2_struct_tag_dtb {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define STIVALE2_STRUCT_TAG_VMAP 0xb0ed257db18cb58f
|
||||
|
||||
struct stivale2_struct_vmap {
|
||||
struct stivale2_tag tag;
|
||||
uint64_t addr;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#endif
|
1
limine
Submodule
1
limine
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 2862a261450af7cb2b1504b5a3ed15c32759deaa
|
14
limine.cfg
Normal file
14
limine.cfg
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Timeout in seconds that Limine will use before automatically booting.
|
||||
TIMEOUT=5
|
||||
|
||||
# The entry name that will be displayed in the boot menu
|
||||
:HhhOS
|
||||
|
||||
# Change the protocol line depending on the used protocol.
|
||||
PROTOCOL=stivale2
|
||||
|
||||
# Path to the kernel to boot. boot:/// represents the partition on which limine.cfg is located.
|
||||
KERNEL_PATH=boot:///hhhos.elf
|
||||
|
||||
# Remove the following line to enable kernel address layout randomisation.
|
||||
KASLR=no
|
57
linker.ld
57
linker.ld
|
@ -1,43 +1,34 @@
|
|||
/* The bootloader will look at this image and start execution at the symbol
|
||||
designated as the entry point. */
|
||||
/* Tell the linker that we want the symbol _start to be our entry point */
|
||||
ENTRY(_start)
|
||||
|
||||
/* Tell where the various sections of the object files will be put in the final
|
||||
kernel image. */
|
||||
SECTIONS
|
||||
{
|
||||
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
|
||||
loaded at by the bootloader. */
|
||||
. = 1M;
|
||||
/* We wanna be placed in the higher half, 2MiB above 0 in physical memory. */
|
||||
/* Since we are going to use PIE, this is just the base load address, but the */
|
||||
/* bootloader will be able to relocate us as it sees fit. */
|
||||
. = 0xffffffff80200000;
|
||||
|
||||
/* First put the multiboot header, as it is required to be put very early
|
||||
early in the image or the bootloader won't recognize the file format.
|
||||
Next we'll put the .text section. */
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.text)
|
||||
}
|
||||
/* We place the .stivale2hdr section containing the header in its own section, */
|
||||
/* and we use the KEEP directive on it to make sure it doesn't get discarded. */
|
||||
.stivale2hdr : {
|
||||
KEEP(*(.stivale2hdr))
|
||||
}
|
||||
|
||||
/* Read-only data. */
|
||||
.rodata BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
/* Then let's place all the other traditional executable sections afterwards. */
|
||||
.text : {
|
||||
*(.text*)
|
||||
}
|
||||
|
||||
/* Read-write data (initialized) */
|
||||
.data BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
}
|
||||
|
||||
/* Read-write data (uninitialized) and stack */
|
||||
.bss BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
}
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
|
||||
/* The compiler may produce other sections, by default it will put them in
|
||||
a segment with the same name. Simply add stuff here as needed. */
|
||||
.bss : {
|
||||
*(COMMON)
|
||||
*(.bss*)
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
menuentry "HhhOS" {
|
||||
multiboot /boot/hhhos.bin
|
||||
}
|
Loading…
Reference in a new issue