Pridana verze v0.1
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* AsterOS Kernel
|
||||
* Autor: Pavel Kalas
|
||||
* Rok: 2026
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tento soubor implementuje bridge mezi API pro aplikace a jadrem.
|
||||
* Dnes funguje jako tenka vrstva nad kernel sluzbami a syscall API,
|
||||
* aby bylo mozne na stejnem rozhrani pozdeji stavet user-space runtime.
|
||||
*/
|
||||
|
||||
#include "aster_api.h"
|
||||
#include "display.h"
|
||||
#include "storage.h"
|
||||
#include "syscall.h"
|
||||
#include "timer.h"
|
||||
|
||||
int aster_api_print(const char *text) {
|
||||
return (int)aster_write(text);
|
||||
}
|
||||
|
||||
int aster_api_clear(void) {
|
||||
display_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aster_api_ticks(u64 *out_ticks) {
|
||||
if (!out_ticks) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out_ticks = (u64)timer_ticks();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *aster_api_alloc(usize size) {
|
||||
return aster_alloc(size);
|
||||
}
|
||||
|
||||
int aster_api_file_create(const char *path) {
|
||||
return asterfs_create_file(path);
|
||||
}
|
||||
|
||||
int aster_api_file_read(const char *path, u8 *out, u16 max_len) {
|
||||
return asterfs_read_file(path, out, max_len);
|
||||
}
|
||||
|
||||
int aster_api_file_write(const char *path, const u8 *data, u16 len) {
|
||||
return asterfs_write_file(path, data, len);
|
||||
}
|
||||
|
||||
int aster_api_process_spawn(void (*entry)(void), const char *name, u8 priority) {
|
||||
return (int)aster_process_create(entry, name, priority);
|
||||
}
|
||||
+2959
File diff suppressed because it is too large
Load Diff
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* AsterOS Kernel
|
||||
* Autor: Pavel Kalaš
|
||||
* Rok: 2026
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tento modul realizuje dve vrstvy spravy pameti jadra.
|
||||
* Prvni cast je bitmap allocator fyzickych stranek pro page_alloc/page_free,
|
||||
* druha cast je jednoducha linearni heap alokace pro kernelove objekty.
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
#include "string.h"
|
||||
|
||||
#define PMM_MAX_MEMORY (64ULL * 1024ULL * 1024ULL)
|
||||
#define PMM_MAX_PAGES (PMM_MAX_MEMORY / PAGE_SIZE)
|
||||
#define PMM_BITMAP_SIZE (PMM_MAX_PAGES / 8)
|
||||
|
||||
static u8 page_bitmap[PMM_BITMAP_SIZE];
|
||||
static usize free_pages = PMM_MAX_PAGES;
|
||||
|
||||
#define KHEAP_SIZE (1024 * 1024)
|
||||
static u8 kernel_heap[KHEAP_SIZE];
|
||||
static usize heap_offset = 0;
|
||||
|
||||
static void bitmap_set(usize idx) {
|
||||
page_bitmap[idx / 8] |= (u8)(1u << (idx % 8));
|
||||
}
|
||||
|
||||
static void bitmap_clear(usize idx) {
|
||||
page_bitmap[idx / 8] &= (u8)~(1u << (idx % 8));
|
||||
}
|
||||
|
||||
static int bitmap_test(usize idx) {
|
||||
return (page_bitmap[idx / 8] & (u8)(1u << (idx % 8))) != 0;
|
||||
}
|
||||
|
||||
void memory_init(void) {
|
||||
aster_memset(page_bitmap, 0, PMM_BITMAP_SIZE);
|
||||
free_pages = PMM_MAX_PAGES;
|
||||
heap_offset = 0;
|
||||
|
||||
for (usize i = 0; i < 256; ++i) {
|
||||
bitmap_set(i);
|
||||
--free_pages;
|
||||
}
|
||||
}
|
||||
|
||||
void *page_alloc(void) {
|
||||
usize i;
|
||||
|
||||
for (i = 0; i < PMM_MAX_PAGES; ++i) {
|
||||
if (!bitmap_test(i)) {
|
||||
bitmap_set(i);
|
||||
--free_pages;
|
||||
return (void *)(i * PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void page_free(void *page) {
|
||||
usize idx;
|
||||
|
||||
if (!page) {
|
||||
return;
|
||||
}
|
||||
|
||||
idx = ((usize)page) / PAGE_SIZE;
|
||||
if (idx < PMM_MAX_PAGES && bitmap_test(idx)) {
|
||||
bitmap_clear(idx);
|
||||
++free_pages;
|
||||
}
|
||||
}
|
||||
|
||||
void *kmalloc(usize size) {
|
||||
usize aligned;
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aligned = (size + 15) & ~((usize)15);
|
||||
if (heap_offset + aligned > KHEAP_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *ptr = &kernel_heap[heap_offset];
|
||||
heap_offset += aligned;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void kfree(void *ptr) {
|
||||
(void)ptr;
|
||||
}
|
||||
|
||||
usize memory_total_pages(void) {
|
||||
return PMM_MAX_PAGES;
|
||||
}
|
||||
|
||||
usize memory_free_pages(void) {
|
||||
return free_pages;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* AsterOS Kernel
|
||||
* Autor: Pavel Kalaš
|
||||
* Rok: 2026
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tento soubor drzi nouzovou cestu pro neobnovitelne chyby jadra.
|
||||
* Pri volani panic prepne vizualni styl vystupu, vypise duvod selhani
|
||||
* a bezpecne zastavi CPU, aby se predeslo dalsimu poskozeni stavu.
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "display.h"
|
||||
#include "panic.h"
|
||||
#include "printk.h"
|
||||
|
||||
void panic(const char *reason) {
|
||||
display_set_color(0x0F, 0x04);
|
||||
printk("\n[KERNEL PANIC] %s\n", reason ? reason : "unknown");
|
||||
cpu_halt();
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* AsterOS Kernel
|
||||
* Autor: Pavel Kalaš
|
||||
* Rok: 2026
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tento modul implementuje tiskovou vrstvu kernelu nad VGA vystupem.
|
||||
* Obsahuje podporu zakladnich formatovacich specifikatoru pro ladeni
|
||||
* a jednotne API, ktere pouzivaji ostatni casti jadra pri logovani.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "printk.h"
|
||||
|
||||
static void print_u64(unsigned long long value, unsigned int base) {
|
||||
char buf[32];
|
||||
const char *digits = "0123456789abcdef";
|
||||
int i = 0;
|
||||
|
||||
if (value == 0) {
|
||||
display_putc('0');
|
||||
return;
|
||||
}
|
||||
|
||||
while (value > 0 && i < (int)sizeof(buf)) {
|
||||
buf[i++] = digits[value % base];
|
||||
value /= base;
|
||||
}
|
||||
|
||||
while (i > 0) {
|
||||
display_putc(buf[--i]);
|
||||
}
|
||||
}
|
||||
|
||||
void aster_print(const char *text) {
|
||||
display_write(text);
|
||||
}
|
||||
|
||||
void printk(const char *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
while (*fmt) {
|
||||
if (*fmt != '%') {
|
||||
display_putc(*fmt++);
|
||||
continue;
|
||||
}
|
||||
|
||||
++fmt;
|
||||
switch (*fmt) {
|
||||
case '%':
|
||||
display_putc('%');
|
||||
break;
|
||||
case 'c': {
|
||||
int c = va_arg(args, int);
|
||||
display_putc((char)c);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
const char *s = va_arg(args, const char *);
|
||||
if (!s) {
|
||||
s = "(null)";
|
||||
}
|
||||
display_write(s);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
long v = va_arg(args, int);
|
||||
if (v < 0) {
|
||||
display_putc('-');
|
||||
print_u64((unsigned long long)(-v), 10);
|
||||
} else {
|
||||
print_u64((unsigned long long)v, 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
unsigned int v = va_arg(args, unsigned int);
|
||||
print_u64(v, 10);
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
unsigned int v = va_arg(args, unsigned int);
|
||||
print_u64(v, 16);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
unsigned long long v = (unsigned long long)va_arg(args, void *);
|
||||
display_write("0x");
|
||||
print_u64(v, 16);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
display_putc('?');
|
||||
break;
|
||||
}
|
||||
++fmt;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* AsterOS Kernel
|
||||
* Autor: Pavel Kalaš
|
||||
* Rok: 2026
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tento soubor spravuje zivotni cyklus kernel procesu.
|
||||
* Implementuje statickou procesovou tabulku, prirazovani PID,
|
||||
* pripravu stacku a zakladni operace pro vytvoreni a ukonceni procesu.
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
#include "process.h"
|
||||
#include "string.h"
|
||||
|
||||
#define PROCESS_STACK_SIZE (16 * 1024)
|
||||
|
||||
static process_t g_processes[ASTER_MAX_PROCESSES];
|
||||
static usize g_process_count = 0;
|
||||
static u32 g_next_pid = 1;
|
||||
static process_t *g_current = 0;
|
||||
|
||||
void process_init(void) {
|
||||
usize i;
|
||||
|
||||
for (i = 0; i < ASTER_MAX_PROCESSES; ++i) {
|
||||
g_processes[i].pid = 0;
|
||||
g_processes[i].state = PROCESS_UNUSED;
|
||||
g_processes[i].priority = 0;
|
||||
g_processes[i].stack_base = 0;
|
||||
g_processes[i].stack_top = 0;
|
||||
g_processes[i].name = 0;
|
||||
g_processes[i].context.rip = 0;
|
||||
}
|
||||
|
||||
g_process_count = 0;
|
||||
g_current = 0;
|
||||
}
|
||||
|
||||
process_t *process_create(const char *name, void (*entry)(void), u8 priority) {
|
||||
process_t *p;
|
||||
void *stack;
|
||||
|
||||
if (g_process_count >= ASTER_MAX_PROCESSES || !entry) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = &g_processes[g_process_count];
|
||||
stack = kmalloc(PROCESS_STACK_SIZE);
|
||||
if (!stack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->pid = g_next_pid++;
|
||||
p->state = PROCESS_READY;
|
||||
p->priority = priority;
|
||||
p->stack_base = (u8 *)stack;
|
||||
p->stack_top = (u64)(p->stack_base + PROCESS_STACK_SIZE - 16);
|
||||
p->name = name;
|
||||
|
||||
aster_memset(&p->context, 0, sizeof(context_t));
|
||||
p->context.rip = (u64)entry;
|
||||
p->context.rbp = p->stack_top;
|
||||
|
||||
++g_process_count;
|
||||
return p;
|
||||
}
|
||||
|
||||
void process_exit(void) {
|
||||
if (g_current) {
|
||||
g_current->state = PROCESS_EXITED;
|
||||
}
|
||||
}
|
||||
|
||||
process_t *process_current(void) {
|
||||
return g_current;
|
||||
}
|
||||
|
||||
void process_set_current(process_t *p) {
|
||||
g_current = p;
|
||||
}
|
||||
|
||||
process_t *process_table(void) {
|
||||
return &g_processes[0];
|
||||
}
|
||||
|
||||
usize process_count(void) {
|
||||
return g_process_count;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* AsterOS Kernel
|
||||
* Autor: Pavel Kalaš
|
||||
* Rok: 2026
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tento modul implementuje jednoduchy planovac typu round-robin.
|
||||
* Reaguje na tiky casovace, vybira dalsi bezici proces
|
||||
* a ridi prepinani mezi stavy READY, RUNNING a EXITED.
|
||||
*/
|
||||
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
#include "timer.h"
|
||||
|
||||
static usize g_current_index = 0;
|
||||
static unsigned long g_quantum_ticks = 0;
|
||||
|
||||
void scheduler_init(void) {
|
||||
g_current_index = 0;
|
||||
g_quantum_ticks = 0;
|
||||
}
|
||||
|
||||
process_t *scheduler_pick_next(void) {
|
||||
process_t *table = process_table();
|
||||
usize count = process_count();
|
||||
usize i;
|
||||
|
||||
if (count == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
usize idx = (g_current_index + i + 1) % count;
|
||||
if (table[idx].state == PROCESS_READY || table[idx].state == PROCESS_RUNNING) {
|
||||
g_current_index = idx;
|
||||
return &table[idx];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scheduler_run_once(void) {
|
||||
process_t *next = scheduler_pick_next();
|
||||
|
||||
if (!next) {
|
||||
return;
|
||||
}
|
||||
|
||||
process_set_current(next);
|
||||
if (next->state == PROCESS_READY) {
|
||||
void (*entry)(void) = (void (*)(void))next->context.rip;
|
||||
next->state = PROCESS_RUNNING;
|
||||
entry();
|
||||
if (next->state == PROCESS_RUNNING) {
|
||||
next->state = PROCESS_EXITED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scheduler_yield(void) {
|
||||
process_t *current = process_current();
|
||||
|
||||
if (current && current->state == PROCESS_RUNNING) {
|
||||
current->state = PROCESS_READY;
|
||||
}
|
||||
|
||||
scheduler_run_once();
|
||||
}
|
||||
|
||||
void scheduler_tick(void) {
|
||||
timer_tick_advance();
|
||||
++g_quantum_ticks;
|
||||
|
||||
if ((g_quantum_ticks % 5) == 0) {
|
||||
scheduler_run_once();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* AsterOS Kernel
|
||||
* Autor: Pavel Kalaš
|
||||
* Rok: 2026
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tento soubor obsahuje vlastni implementace zakladnich utility funkci.
|
||||
* Kernel je pouziva misto standardni knihovny pro strlen, strcmp,
|
||||
* memcpy a memset, aby zustal freestanding a plne pod kontrolou jadra.
|
||||
*/
|
||||
|
||||
#include "string.h"
|
||||
|
||||
usize aster_strlen(const char *s) {
|
||||
usize n = 0;
|
||||
while (s && s[n]) {
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int aster_strcmp(const char *a, const char *b) {
|
||||
while (*a && (*a == *b)) {
|
||||
++a;
|
||||
++b;
|
||||
}
|
||||
return (unsigned char)*a - (unsigned char)*b;
|
||||
}
|
||||
|
||||
int aster_strncmp(const char *a, const char *b, usize n) {
|
||||
usize i;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (a[i] != b[i] || a[i] == '\0' || b[i] == '\0') {
|
||||
return (unsigned char)a[i] - (unsigned char)b[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *aster_memcpy(void *dst, const void *src, usize n) {
|
||||
usize i;
|
||||
u8 *d = (u8 *)dst;
|
||||
const u8 *s = (const u8 *)src;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void *aster_memset(void *dst, int v, usize n) {
|
||||
usize i;
|
||||
u8 *d = (u8 *)dst;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
d[i] = (u8)v;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* AsterOS Kernel
|
||||
* Autor: Pavel Kalaš
|
||||
* Rok: 2026
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tento modul je vstupni brana pro systemova volani.
|
||||
* Obsahuje dispatcher, ktery podle ID vola konkretni kernelovou sluzbu,
|
||||
* a implementuje zakladni syscall operace pro zapis, alokaci a procesy.
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
#include "printk.h"
|
||||
#include "process.h"
|
||||
#include "syscall.h"
|
||||
|
||||
void syscall_init(void) {
|
||||
}
|
||||
|
||||
u64 syscall_dispatch(u64 id, u64 a1, u64 a2, u64 a3, u64 a4) {
|
||||
(void)a3;
|
||||
(void)a4;
|
||||
|
||||
switch (id) {
|
||||
case SYSCALL_WRITE:
|
||||
return aster_write((const char *)a1);
|
||||
case SYSCALL_ALLOC:
|
||||
return (u64)aster_alloc((usize)a1);
|
||||
case SYSCALL_PROCESS_CREATE:
|
||||
return (u64)aster_process_create((void (*)(void))a1, (const char *)a2, (u8)a3);
|
||||
default:
|
||||
return (u64)-1;
|
||||
}
|
||||
}
|
||||
|
||||
u64 aster_write(const char *text) {
|
||||
if (!text) {
|
||||
return (u64)-1;
|
||||
}
|
||||
|
||||
printk("%s", text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *aster_alloc(usize size) {
|
||||
return kmalloc(size);
|
||||
}
|
||||
|
||||
i64 aster_process_create(void (*entry)(void), const char *name, u8 priority) {
|
||||
process_t *p = process_create(name, entry, priority);
|
||||
if (!p) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return p->pid;
|
||||
}
|
||||
Reference in New Issue
Block a user