initial commit
This commit is contained in:
commit
0fa2351940
19 changed files with 693 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
compile_flags.txt
|
||||||
|
bin
|
49
Makefile
Normal file
49
Makefile
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
CC=i386-elf-gcc
|
||||||
|
LD=i386-elf-ld
|
||||||
|
CFLAGS=-ffreestanding -g -m32 -std=c2x -O2 -Wall -Wextra -pedantic -lgcc -isystem ./libk/include
|
||||||
|
|
||||||
|
C_SOURCE=$(shell find kernel -type f -name "*.c")
|
||||||
|
C_OBJ=$(patsubst %.c,bin/%.o,$(C_SOURCE))
|
||||||
|
|
||||||
|
A_SOURCE=$(shell find kernel -type f -name "*.asm")
|
||||||
|
A_OBJ=$(patsubst %.asm,bin/%_asm.o,$(A_SOURCE))
|
||||||
|
|
||||||
|
LIBK_SOURCE=$(shell find libk -type f -name "*.c")
|
||||||
|
LIBK_OBJ=$(patsubst %.c,bin/%.o,$(LIBK_SOURCE))
|
||||||
|
|
||||||
|
.PHONY: test all run clean
|
||||||
|
|
||||||
|
all: bin/os.iso
|
||||||
|
|
||||||
|
$(A_OBJ): bin/%_asm.o : %.asm
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
nasm $< -f elf -o $@
|
||||||
|
|
||||||
|
$(C_OBJ): bin/%.o : %.c
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$(LIBK_OBJ): bin/%.o : %.c
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
bin/libk.a: $(LIBK_OBJ)
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(AR) rcs bin/libk.a $(LIBK_OBJ)
|
||||||
|
|
||||||
|
bin/kernel.bin: bin/libk.a $(A_OBJ) $(C_OBJ)
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(LD) -nmagic -o bin/kernel.bin -T linker.ld $(A_OBJ) $(C_OBJ) bin/libk.a
|
||||||
|
|
||||||
|
bin/os.iso: bin/kernel.bin
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
@mkdir -p bin/iso/boot/grub
|
||||||
|
cp grub.cfg bin/iso/boot/grub
|
||||||
|
cp bin/kernel.bin bin/iso/boot
|
||||||
|
grub-mkrescue -o bin/os.iso bin/iso
|
||||||
|
|
||||||
|
run: all
|
||||||
|
qemu-system-i386 -cdrom bin/os.iso
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf bin
|
7
grub.cfg
Normal file
7
grub.cfg
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
set timeout=0
|
||||||
|
set default=0
|
||||||
|
|
||||||
|
menuentry "trios" {
|
||||||
|
multiboot2 /boot/kernel.bin
|
||||||
|
boot
|
||||||
|
}
|
87
kernel/interrupt/idt.asm
Normal file
87
kernel/interrupt/idt.asm
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
extern idt_exception_handler
|
||||||
|
extern idt_pic_timer
|
||||||
|
extern idt_pic_keyboard
|
||||||
|
extern idt_pic_handler
|
||||||
|
global isr_stub_table
|
||||||
|
|
||||||
|
%macro ISRErrorStub 1
|
||||||
|
isr_stub_%+%1:
|
||||||
|
push dword %1
|
||||||
|
call idt_exception_handler
|
||||||
|
pop eax
|
||||||
|
iret
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro PICGeneric 1
|
||||||
|
isr_stub_%+%1:
|
||||||
|
push dword %1
|
||||||
|
call idt_pic_handler
|
||||||
|
pop eax
|
||||||
|
iret
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro PICTimer 1
|
||||||
|
isr_stub_%+%1:
|
||||||
|
push dword %1
|
||||||
|
call idt_pic_handler
|
||||||
|
call idt_pic_timer
|
||||||
|
pop eax
|
||||||
|
iret
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro PICKeyboard 1
|
||||||
|
isr_stub_%+%1:
|
||||||
|
push dword %1
|
||||||
|
call idt_pic_handler
|
||||||
|
call idt_pic_keyboard
|
||||||
|
pop eax
|
||||||
|
iret
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro ISRSyscall 1
|
||||||
|
isr_stub_%+%1:
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
call idt_syscall
|
||||||
|
add esp, 16
|
||||||
|
pop eax
|
||||||
|
iret
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
section .text
|
||||||
|
%assign i 0
|
||||||
|
%rep 32
|
||||||
|
ISRErrorStub i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
PICTimer 32
|
||||||
|
PICKeyboard 33
|
||||||
|
PICGeneric 34
|
||||||
|
PICGeneric 35
|
||||||
|
PICGeneric 36
|
||||||
|
PICGeneric 37
|
||||||
|
PICGeneric 38
|
||||||
|
PICGeneric 39
|
||||||
|
PICGeneric 40
|
||||||
|
PICGeneric 41
|
||||||
|
PICGeneric 42
|
||||||
|
PICGeneric 43
|
||||||
|
PICGeneric 44
|
||||||
|
PICGeneric 45
|
||||||
|
PICGeneric 46
|
||||||
|
PICGeneric 47
|
||||||
|
%assign i 48
|
||||||
|
%rep 256 - 48
|
||||||
|
ISRErrorStub i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
|
||||||
|
section .rodata
|
||||||
|
isr_stub_table:
|
||||||
|
%assign i 0x00
|
||||||
|
%rep 256
|
||||||
|
dd isr_stub_%+i
|
||||||
|
%assign i i+0x01
|
||||||
|
%endrep
|
81
kernel/interrupt/idt.c
Normal file
81
kernel/interrupt/idt.c
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys.h>
|
||||||
|
#include "idt.h"
|
||||||
|
#include "../term.h"
|
||||||
|
#include "pic.h"
|
||||||
|
|
||||||
|
static int timer = 0;
|
||||||
|
|
||||||
|
void idt_pic_handler(uint8_t exception) {
|
||||||
|
pic_eoi(exception - PIC_REMAP_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_pic_timer(void) {
|
||||||
|
uint32_t state = term_save();
|
||||||
|
term_setcol(0x0a);
|
||||||
|
char buf[20];
|
||||||
|
itoa(timer, buf);
|
||||||
|
term_setpos(0, 20);
|
||||||
|
puts(" ");
|
||||||
|
term_setpos(0, 20);
|
||||||
|
puts(buf);
|
||||||
|
timer += 1;
|
||||||
|
term_load(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_pic_keyboard(void) {
|
||||||
|
uint8_t c = inb(0x60);
|
||||||
|
uint32_t state = term_save();
|
||||||
|
term_setcol(0x0c);
|
||||||
|
term_setpos(0, 21);
|
||||||
|
puts(" ");
|
||||||
|
term_setpos(0, 21);
|
||||||
|
char buf[20];
|
||||||
|
itoa(c, buf);
|
||||||
|
puts(buf);
|
||||||
|
term_load(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_exception_handler(uint8_t exception) {
|
||||||
|
switch(exception) {
|
||||||
|
case 0x00:
|
||||||
|
puts("Div by zero");
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
puts("Double fault");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
puts("Error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
halt();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((aligned(0x10)))
|
||||||
|
static struct IdtEntry idt[256];
|
||||||
|
static struct Idtr idtr;
|
||||||
|
extern void* isr_stub_table[];
|
||||||
|
|
||||||
|
static void set_descriptor(uint8_t vector, void* isr, uint8_t flags) {
|
||||||
|
struct IdtEntry* entry = &idt[vector];
|
||||||
|
entry->isr_low = (size_t)isr & 0xffff;
|
||||||
|
entry->kernel_cs = 0x08;
|
||||||
|
entry->attributes = flags;
|
||||||
|
entry->isr_high = (size_t)isr >> 16;
|
||||||
|
entry->_reserved = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_init(void) {
|
||||||
|
idtr.base = (uintptr_t)&idt[0];
|
||||||
|
idtr.limit = (uint16_t)sizeof(struct IdtEntry) * IDT_SIZE - 1;
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < IDT_INTERRUPTS; i++) {
|
||||||
|
set_descriptor(i, isr_stub_table[i], 0x8e);
|
||||||
|
}
|
||||||
|
|
||||||
|
__asm__ volatile ("lidt %0" : : "m"(idtr));
|
||||||
|
}
|
||||||
|
|
36
kernel/interrupt/idt.h
Normal file
36
kernel/interrupt/idt.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define IDT_SIZE 256
|
||||||
|
#define IDT_INTERRUPTS 48
|
||||||
|
|
||||||
|
struct IdtEntry {
|
||||||
|
uint16_t isr_low;
|
||||||
|
uint16_t kernel_cs;
|
||||||
|
uint8_t _reserved;
|
||||||
|
uint8_t attributes;
|
||||||
|
uint16_t isr_high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct Idtr {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
IDT_FLAG_GATE_TASK = 0x5,
|
||||||
|
IDT_FLAG_GATE_16BIT_INT = 0x6,
|
||||||
|
IDT_FLAG_GATE_16BIT_TRAP = 0x7,
|
||||||
|
IDT_FLAG_GATE_32BIT_INT = 0xE,
|
||||||
|
IDT_FLAG_GATE_32BIT_TRAP = 0xF,
|
||||||
|
|
||||||
|
IDT_FLAG_RING0 = (0 << 5),
|
||||||
|
IDT_FLAG_RING1 = (1 << 5),
|
||||||
|
IDT_FLAG_RING2 = (2 << 5),
|
||||||
|
IDT_FLAG_RING3 = (3 << 5),
|
||||||
|
|
||||||
|
IDT_FLAG_PRESENT = 0x80,
|
||||||
|
|
||||||
|
} IDTFlags;
|
||||||
|
|
||||||
|
void idt_init(void);
|
82
kernel/interrupt/pic.c
Normal file
82
kernel/interrupt/pic.c
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#include "pic.h"
|
||||||
|
#include "../term.h"
|
||||||
|
#include <sys.h>
|
||||||
|
|
||||||
|
#define PIC1_COMMAND_PORT 0x20
|
||||||
|
#define PIC1_DATA_PORT 0x21
|
||||||
|
#define PIC2_COMMAND_PORT 0xA0
|
||||||
|
#define PIC2_DATA_PORT 0xA1
|
||||||
|
|
||||||
|
|
||||||
|
void pic_remap(uint8_t offset) {
|
||||||
|
char a1 = inb(PIC1_DATA_PORT);
|
||||||
|
char a2 = inb(PIC2_DATA_PORT);
|
||||||
|
// control word 1
|
||||||
|
// 0x11: initialize, enable ICW4
|
||||||
|
outb(PIC1_COMMAND_PORT, 0x11);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_COMMAND_PORT, 0x11);
|
||||||
|
io_wait();
|
||||||
|
// control word 2
|
||||||
|
// interrupt offset
|
||||||
|
outb(PIC1_DATA_PORT, offset);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_DATA_PORT, offset + 8);
|
||||||
|
io_wait();
|
||||||
|
// control word 3
|
||||||
|
// primary pic: set which pin secondary is connected to
|
||||||
|
// (pin 2)
|
||||||
|
outb(PIC1_DATA_PORT, 0b00000100);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_DATA_PORT, 2);
|
||||||
|
io_wait();
|
||||||
|
// control word 3
|
||||||
|
// 0x01: enable 8086 mode
|
||||||
|
outb(PIC1_DATA_PORT, 0x01);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_DATA_PORT, 0x01);
|
||||||
|
io_wait();
|
||||||
|
// clear data registers
|
||||||
|
outb(PIC1_DATA_PORT, a1);
|
||||||
|
outb(PIC2_DATA_PORT, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pic_mask(int irq) {
|
||||||
|
uint8_t port;
|
||||||
|
if(irq < 8) {
|
||||||
|
port = PIC1_DATA_PORT;
|
||||||
|
} else {
|
||||||
|
irq -= 8;
|
||||||
|
port = PIC2_DATA_PORT;
|
||||||
|
}
|
||||||
|
uint8_t mask = inb(port);
|
||||||
|
outb(port, mask | (1 << irq));
|
||||||
|
}
|
||||||
|
|
||||||
|
void pic_unmask(int irq) {
|
||||||
|
uint8_t port;
|
||||||
|
if(irq < 8) {
|
||||||
|
port = PIC1_DATA_PORT;
|
||||||
|
} else {
|
||||||
|
irq -= 8;
|
||||||
|
port = PIC2_DATA_PORT;
|
||||||
|
}
|
||||||
|
uint8_t mask = inb(port);
|
||||||
|
outb(port, mask & ~(1 << irq));
|
||||||
|
}
|
||||||
|
|
||||||
|
// completely disable the PIC
|
||||||
|
void pic_disable() {
|
||||||
|
outb(PIC1_DATA_PORT, 0xff);
|
||||||
|
io_wait();
|
||||||
|
outb(PIC2_DATA_PORT, 0xff);
|
||||||
|
io_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
// end of interrupt
|
||||||
|
void pic_eoi(int irq) {
|
||||||
|
if(irq >= 8) {
|
||||||
|
outb(PIC2_COMMAND_PORT, 0x20);
|
||||||
|
}
|
||||||
|
outb(PIC1_COMMAND_PORT, 0x20);
|
||||||
|
}
|
10
kernel/interrupt/pic.h
Normal file
10
kernel/interrupt/pic.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PIC_REMAP_OFFSET 0x20
|
||||||
|
|
||||||
|
void pic_remap(uint8_t offset);
|
||||||
|
void pic_mask(int irq);
|
||||||
|
void pic_unmask(int irq);
|
||||||
|
void pic_disable();
|
||||||
|
void pic_eoi(int irq);
|
22
kernel/main.c
Normal file
22
kernel/main.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <sys.h>
|
||||||
|
#include "term.h"
|
||||||
|
#include "interrupt/pic.h"
|
||||||
|
#include "interrupt/idt.h"
|
||||||
|
|
||||||
|
extern void kmain(void) {
|
||||||
|
term_clear();
|
||||||
|
term_setcol(0x0f);
|
||||||
|
puts("loading kernel\n");
|
||||||
|
idt_init();
|
||||||
|
puts("initialized idt\n");
|
||||||
|
pic_remap(PIC_REMAP_OFFSET);
|
||||||
|
puts("remapped pic\n");
|
||||||
|
int_enable();
|
||||||
|
puts("enabled interrupts\n");
|
||||||
|
outb(0x60, 0xF4);
|
||||||
|
puts("enabled keyboard\n");
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
int_wait();
|
||||||
|
}
|
||||||
|
}
|
66
kernel/start.asm
Normal file
66
kernel/start.asm
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
global start
|
||||||
|
extern kmain
|
||||||
|
bits 32
|
||||||
|
|
||||||
|
; base, limit, access, flags
|
||||||
|
%macro gdt_entry 4
|
||||||
|
db %2 & 0xff
|
||||||
|
db (%2 >> 8) & 0xff
|
||||||
|
db %1 & 0xff
|
||||||
|
db (%1 >> 8) & 0xff
|
||||||
|
db (%1 >> 16) & 0xff
|
||||||
|
db %3
|
||||||
|
db ((%2 >> 16) & 0x0f) | (%4 << 4)
|
||||||
|
db (%1 >> 24) & 0xff
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
section .multiboot_header
|
||||||
|
align 8
|
||||||
|
mb_start:
|
||||||
|
dd 0xe85250d6
|
||||||
|
dd 0
|
||||||
|
dd mb_end - mb_start
|
||||||
|
dd 0x100000000 - (0xe85250d6 + (mb_end - mb_start))
|
||||||
|
dw 0
|
||||||
|
dw 0
|
||||||
|
dd 8
|
||||||
|
mb_end:
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 16
|
||||||
|
stack_start:
|
||||||
|
resb 16384
|
||||||
|
stack_end:
|
||||||
|
|
||||||
|
section .rodata
|
||||||
|
align 16
|
||||||
|
gdt_start:
|
||||||
|
gdt_entry 0, 0, 0, 0
|
||||||
|
gdt_entry 0, 0xFFFFF, 0x9A, 0xC
|
||||||
|
gdt_entry 0, 0xFFFFF, 0x92, 0xC
|
||||||
|
gdt_end:
|
||||||
|
gdt_descriptor:
|
||||||
|
dw gdt_end - gdt_start - 1
|
||||||
|
dd gdt_start
|
||||||
|
|
||||||
|
|
||||||
|
section .text
|
||||||
|
align 8
|
||||||
|
start:
|
||||||
|
cli
|
||||||
|
lgdt [gdt_descriptor]
|
||||||
|
jmp 0x08:after_lgdt
|
||||||
|
after_lgdt:
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ds, ax
|
||||||
|
mov ss, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
mov esp, stack_end
|
||||||
|
mov ebp, stack_end
|
||||||
|
call kmain
|
||||||
|
cli
|
||||||
|
halt:
|
||||||
|
hlt
|
||||||
|
jmp halt
|
63
kernel/term.c
Normal file
63
kernel/term.c
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "term.h"
|
||||||
|
|
||||||
|
static uint16_t* screen = (uint16_t*)0xb8000;
|
||||||
|
static size_t x = 0;
|
||||||
|
static size_t y = 0;
|
||||||
|
static uint8_t color = 0x0f;
|
||||||
|
|
||||||
|
static inline uint16_t screen_entry(char c, uint8_t col) {
|
||||||
|
return (uint16_t)c | ((uint16_t)col << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void putc(char c) {
|
||||||
|
switch(c) {
|
||||||
|
case '\n':
|
||||||
|
x = TERM_W;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
if(x % 8 == 0) x += 8;
|
||||||
|
x += 7 - (x % 8);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
screen[x + y * TERM_W] = screen_entry(c, color);
|
||||||
|
x += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(x >= TERM_W) {
|
||||||
|
x = 0;
|
||||||
|
y += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void puts(char* s) {
|
||||||
|
for(char* c = s; *c != '\0'; c++) {
|
||||||
|
putc(*c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void term_clear(void) {
|
||||||
|
memset(screen, 0, TERM_W * TERM_H * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void term_setpos(size_t new_x, size_t new_y) {
|
||||||
|
x = new_x;
|
||||||
|
y = new_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void term_setcol(uint8_t new_col) {
|
||||||
|
color = new_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t term_save(void) {
|
||||||
|
return color | ((x + y * TERM_W) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void term_load(uint32_t state) {
|
||||||
|
color = state & 0xff;
|
||||||
|
state >>= 8;
|
||||||
|
x = state % TERM_W;
|
||||||
|
y = state / TERM_W;
|
||||||
|
}
|
15
kernel/term.h
Normal file
15
kernel/term.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define TERM_W 80
|
||||||
|
#define TERM_H 25
|
||||||
|
|
||||||
|
void putc(char c);
|
||||||
|
void puts(char* s);
|
||||||
|
void term_clear(void);
|
||||||
|
void term_setcol(uint8_t new_col);
|
||||||
|
void term_setpos(size_t new_x, size_t new_y);
|
||||||
|
uint32_t term_save(void);
|
||||||
|
void term_load(uint32_t pos);
|
4
libk/include/stdlib.h
Normal file
4
libk/include/stdlib.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int atoi(const char* s);
|
||||||
|
void itoa(int n, char* buf);
|
8
libk/include/string.h
Normal file
8
libk/include/string.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int memcmp(const void *lhs, const void *rhs, size_t n);
|
||||||
|
void *memcpy(void *restrict dst, const void *restrict src, size_t n);
|
||||||
|
void *memmove(void *dst, const void *src, size_t n);
|
||||||
|
void *memset(void *dest, int c, size_t n);
|
12
libk/include/sys.h
Normal file
12
libk/include/sys.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint8_t inb(uint16_t port);
|
||||||
|
void outb(uint16_t port, uint8_t val);
|
||||||
|
void io_wait(void);
|
||||||
|
|
||||||
|
void int_enable(void);
|
||||||
|
void int_disable(void);
|
||||||
|
void int_wait(void);
|
||||||
|
|
||||||
|
void halt(void);
|
46
libk/stdlib.c
Normal file
46
libk/stdlib.c
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "include/stdlib.h"
|
||||||
|
|
||||||
|
int atoi(const char* s) {
|
||||||
|
bool neg = false;
|
||||||
|
if(*s == '+') {
|
||||||
|
s++;
|
||||||
|
} else if(*s == '-') {
|
||||||
|
neg = true;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
int n = 0;
|
||||||
|
while(*s >= '0' && *s <= '9') {
|
||||||
|
n *= 10;
|
||||||
|
n += (*s - '0');
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return neg ? -n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void itoa(int n, char* buf) {
|
||||||
|
if(n < 0) {
|
||||||
|
n = -n;
|
||||||
|
*buf = '-';
|
||||||
|
buf++;
|
||||||
|
} else if(n == 0) {
|
||||||
|
buf[0] = '0';
|
||||||
|
buf[1] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char* start = buf;
|
||||||
|
while(n > 0) {
|
||||||
|
*buf= n % 10 + '0';
|
||||||
|
n /= 10;
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
*buf = '\0';
|
||||||
|
buf--;
|
||||||
|
while(start < buf) {
|
||||||
|
char tmp = *start;
|
||||||
|
*start = *buf;
|
||||||
|
*buf = tmp;
|
||||||
|
start++;
|
||||||
|
buf--;
|
||||||
|
}
|
||||||
|
}
|
47
libk/string.c
Normal file
47
libk/string.c
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "include/string.h"
|
||||||
|
|
||||||
|
int memcmp(const void *lhs, const void *rhs, size_t n) {
|
||||||
|
const unsigned char *l = lhs;
|
||||||
|
const unsigned char *r = rhs;
|
||||||
|
while(n != 0 && *l == *r) {
|
||||||
|
n--;
|
||||||
|
l++;
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
return (n == 0) ? 0 : *l - *r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memcpy(void *restrict dst, const void *restrict src, size_t n) {
|
||||||
|
char *d = dst;
|
||||||
|
const char *s = src;
|
||||||
|
while(n--) {
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memmove(void *dst, const void *src, size_t n) {
|
||||||
|
char *d = dst;
|
||||||
|
const char *s = src;
|
||||||
|
if(s < d) {
|
||||||
|
d += n;
|
||||||
|
s += n;
|
||||||
|
while(n--) {
|
||||||
|
*--d = *--s;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while(n--) {
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memset(void *dest, int c, size_t n) {
|
||||||
|
unsigned char *d = dest;
|
||||||
|
while(n--) {
|
||||||
|
*d = c;
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
}
|
31
libk/sys.c
Normal file
31
libk/sys.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint8_t inb(uint16_t port) {
|
||||||
|
uint8_t ret;
|
||||||
|
__asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void outb(uint16_t port, uint8_t val) {
|
||||||
|
__asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
void io_wait(void) {
|
||||||
|
outb(0x80, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void int_enable(void) {
|
||||||
|
__asm__ volatile ("sti");
|
||||||
|
}
|
||||||
|
|
||||||
|
void int_disable(void) {
|
||||||
|
__asm__ volatile ("cli");
|
||||||
|
}
|
||||||
|
|
||||||
|
void int_wait(void) {
|
||||||
|
__asm__ volatile ("hlt");
|
||||||
|
}
|
||||||
|
|
||||||
|
void halt(void) {
|
||||||
|
__asm__ volatile ("cli; hlt");
|
||||||
|
}
|
25
linker.ld
Normal file
25
linker.ld
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
ENTRY(start)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 1M;
|
||||||
|
|
||||||
|
.boot :
|
||||||
|
{
|
||||||
|
*(.multiboot_header)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue