Compare commits

..

No commits in common. "dev" and "core" have entirely different histories.
dev ... core

92 changed files with 1937 additions and 3626 deletions

View File

@ -1,5 +0,0 @@
{
"files.associations": {
"random": "cpp"
}
}

View File

@ -1,60 +1,67 @@
CFLAGS = -g -w -std=gnu11 -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast -Isrc/
CXXFLAGS = -g -w -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -Isrc/
CFLAGS = -g -std=gnu11 -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast
CXXFLAGS = -g -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -I.
LDFLAGS =
DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt
DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt \
build/hello/hello.bin
KERNEL_CPP_SRCS = $(shell find src/kernel/ -name '*.cpp')
KERNEL_ASM_SRCS = $(shell find src/kernel/ -name '*.asm')
KERNEL_CPP_SRCS = $(wildcard src/kernel/*.cpp) $(wildcard src/kernel/*/*.cpp)
KERNEL_ASM_SRCS = $(wildcard src/kernel/*.asm)
KERNEL_CPP_OBJS = $(patsubst src/%.cpp,build/%.o,$(KERNEL_CPP_SRCS))
KERNEL_ASM_OBJS = $(patsubst src/%.asm,build/%.o,$(KERNEL_ASM_SRCS))
KERNEL_OBJS = build/kernel/isr.o $(KERNEL_CPP_OBJS) $(KERNEL_ASM_OBJS)
STAGE2_C_SRCS = $(wildcard src/bootstage2/*.c)
STAGE2_C_SRCS = $(wildcard src/boot_stage2/*.c)
STAGE2_C_OBJS = $(patsubst src/%.c,build/%.o,$(STAGE2_C_SRCS))
STAGE2_OBJS = build/c_code_entry.o $(STAGE2_C_OBJS)
PROGRAM_COMMON = build/programs/entry.o build/common/common.o
PROGRAM_COMMON = build/program_code_entry.o build/common/common.o
SRC_DIRS = $(shell find src/ -type d)
BUILD_DIRS = $(subst src/,build/,$(SRC_DIRS))
PROGRAM_C_SRCS = $(wildcard src/program/*.c)
PROGRAM_C_OBJS = $(patsubst src/%.c,build/%.o,$(PROGRAM_C_SRCS))
PROGRAM_OBJS = $(PROGRAM_COMMON) $(PROGRAM_C_OBJS)
PROGRAMS = $(shell find src/programs/* -type d)
$(foreach program,$(PROGRAMS),\
$(eval $(program)_C_SRCS := $(shell find $(program) -name '*.c')) \
$(eval $(program)_CPP_SRCS := $(shell find $(program) -name '*.cpp')) \
$(eval $(program)_OBJS := $(patsubst src/%.c,build/%.o,$($(program)_C_SRCS)) \
$(patsubst src/%.cpp,build/%.o,$($(program)_CPP_SRCS))) \
$(eval DISK_IMG_FILES += $(subst src/,build/,$(program))/$(shell basename $(program).bin)) \
)
HELLO_C_SRCS = $(wildcard src/hello/*.c)
HELLO_C_OBJS = $(patsubst src/%.c,build/%.o,$(HELLO_C_SRCS))
HELLO_OBJS = $(PROGRAM_COMMON) $(HELLO_C_OBJS)
.PHONY: run debug prepare clean cleanbuild
WORLD_C_SRCS = $(wildcard src/world/*.c)
WORLD_C_OBJS = $(patsubst src/%.c,build/%.o,$(WORLD_C_SRCS))
WORLD_OBJS = $(PROGRAM_COMMON) $(WORLD_C_OBJS)
.PHONY: run debug prepare clean
run: disk.img
qemu-system-i386 disk.img
cleanbuild: clean disk.img
qemu-system-i386 disk.img
debug: clean disk.img
debug: disk.img
qemu-system-i386 -s -S -no-reboot -no-shutdown disk.img & gdb --command=gdbscript
disk.img: prepare build/boot/boot.bin build/bootstage2/boot.bin $(DISK_IMG_FILES)
disk.img: prepare build/boot/boot.bin build/boot_stage2/boot.bin $(DISK_IMG_FILES) build/world/world.bin
dd if=/dev/zero of=disk.img count=43 bs=100k
dd if=build/boot/boot.bin of=disk.img conv=notrunc
dd obs=512 seek=1 if=build/bootstage2/boot.bin of=disk.img conv=notrunc
dd obs=512 seek=1 if=build/boot_stage2/boot.bin of=disk.img conv=notrunc
mount disk.img img.d
mkdir img.d/etc/
cp $(DISK_IMG_FILES) img.d/
cp build/world/world.bin img.d/etc/world.bin
sleep 0.1
umount img.d
chmod 777 disk.img
prepare:
mkdir -p img.d
mkdir -p $(BUILD_DIRS)
mkdir -p build/boot
mkdir -p build/boot_stage2
mkdir -p build/kernel
mkdir -p build/kernel/datatypes
mkdir -p build/kernel/stdio
mkdir -p build/program
mkdir -p build/hello
mkdir -p build/world
mkdir -p build/common
mountpoint img.d | grep not || umount img.d
clean:
@ -64,10 +71,10 @@ build/boot/boot.bin: src/boot/boot.asm
nasm $< -o $@
# Boot Stage 2
build/bootstage2/boot.bin: src/bootstage2/bootstage2.ld $(STAGE2_OBJS)
build/boot_stage2/boot.bin: src/boot_stage2/boot_stage2.ld $(STAGE2_OBJS)
ld $(LDFLAGS) -T $< $(STAGE2_OBJS)
build/bootstage2/%.o: src/bootstage2/%.c
build/boot_stage2/%.o: src/boot_stage2/%.c
gcc $(CFLAGS) -o $@ -c $<
# Kernel
@ -94,6 +101,12 @@ src/kernel/isr.S: src/kernel/isr.S.base src/kernel/gen_isr_asm.sh
# Program
.SECONDEXPANSION:
build/programs/%.bin: src/programs/userspace.ld build/programs/entry.o $$(src/programs/$$(basename $$(notdir $$*))_OBJS) $(PROGRAM_COMMON)
ld -o $@ -T $^
build/program/program.bin: src/program/program.ld $(PROGRAM_OBJS)
echo $(PROGRAM_OBJS)
ld $(LDFLAGS) -T $< $(PROGRAM_OBJS)
build/hello/hello.bin: src/hello/hello.ld $(HELLO_OBJS)
ld $(LDFLAGS) -T $< $(HELLO_OBJS)
build/world/world.bin: src/world/world.ld $(WORLD_OBJS)
ld $(LDFLAGS) -T $< $(WORLD_OBJS)

View File

@ -50,7 +50,7 @@ bootcode:
mov ax, 2 ; Begin with the 2nd sector
call prep_i13
mov al, 31 ; Load the next 31 sectors (15.5kb)
mov al, 31 ; Load the next 9 sectors (4.5k)
int 13h
; We need to get the memory configuration from the BIOS now

View File

@ -11,8 +11,8 @@
uint16_t identify_result[256];
uint32_t total_28_lbas = 0;
uint8_t* rootDirEntries = (uint8_t*)0x1000000;
uint16_t* FAT1 = (uint16_t*)0x1002000;
uint8_t* rootDirEntries = 0x1000000;
uint16_t* FAT1 = 0x1002000;
uint16_t countReserved;
uint8_t countFATs;
@ -60,7 +60,7 @@ void init_atapio() {
// We've initialised now, let's load the FAT and RootDirEntries.
read_sectors(sectorsPerFAT * countFATs + countReserved, countRDEs / 16, rootDirEntries);
read_sectors(countReserved, sectorsPerFAT, (uint8_t*)FAT1);
read_sectors(countReserved, sectorsPerFAT, FAT1);
}
void read_sector(uint32_t address, uint8_t* buffer) {
@ -95,7 +95,7 @@ uint16_t file_exists(char* filename) {
for (int i=0; i<countRDEs; i++) {
bool found = strcmp(rootDirEntries+(i*32), filename, 11);
if (found) {
uint16_t* correctEntry = (uint16_t*)(rootDirEntries+(i*32));
uint16_t* correctEntry = (rootDirEntries+(i*32));
return correctEntry[13];
}
}

View File

@ -1,14 +1,14 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:i386)
OUTPUT(build/bootstage2/boot.bin)
OUTPUT(build/boot_stage2/boot.bin)
SECTIONS {
. = 0x7E00;
.text : {
build/c_code_entry.o(.text)
build/bootstage2/main.o(.text)
build/bootstage2/*(.text)
build/boot_stage2/main.o(.text)
build/boot_stage2/*(.text)
}
}

View File

@ -1,4 +1,5 @@
#include "atapio.h"
#include "screenstuff.h"
#include "paging.h"
typedef struct {
@ -10,7 +11,7 @@ typedef struct {
uint32_t acpi3_extended;
}__attribute__((packed)) e820entry;
uint8_t* bitmap = (uint8_t*)0x100000;
uint8_t* bitmap = 0x100000;
void set_bit(uint32_t offset, uint8_t* buffer) {
uint32_t index = offset / 8;
@ -46,30 +47,39 @@ void mark_unavailble(uint32_t address, uint32_t size, uint8_t* buffer) {
}
}
typedef struct {
PDE* pde;
uint32_t page_directory_phys_addr;
uint32_t page_directory_phys_offset;
uint32_t page_bitmap_phys;
uint32_t page_bitmap_virt;
uint32_t stack_ptr;
uint32_t vga_addr;
uint32_t remainingPages;
} KernelInformationStruct;
char* stringify_type(uint32_t type) {
switch (type) {
case 1:
return "Usable";
case 3:
return "ACPI Reclaimable";
case 4:
return "ACPI NVS";
case 5:
return "Bad memory";
default:
return "Reserved";
}
}
void main() {
init_term();
init_atapio();
// e820 memory map exists at 0x20000
e820entry* e820_entries = (e820entry*)0x20000;
e820entry* e820_entries = 0x20000;
// Zero out the bitmap.
memset(bitmap, 0x20000, 0);
// Ensure the bitmap data is clear
uint32_t pages;
for (int i=0; i<0x20000; i++)
if (bitmap[i])
printf("Found data in bitmap at %x!\n", (bitmap+i));
for (int i=0; e820_entries[i].length_low != 0 || e820_entries[i].length_high != 0; i++) {
e820entry entry = e820_entries[i];
printf("BIOS-e820: Starting %x%x, length %x%x is %s\n", entry.base_high, entry.base_low, entry.length_high, entry.length_low, stringify_type(entry.type));
if (entry.type != 1)
continue;
@ -86,18 +96,18 @@ void main() {
}
}
uint32_t page_index = base / 4096;
pages += length / 4096;
printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096);
for (int j=0; length > 4096; length -= 4096, j++) {
set_bit(page_index + j, bitmap);
}
}
mark_unavailble((uint32_t)bitmap, 0x20000, bitmap);
mark_unavailble(0, 0xFFFFF, bitmap);
mark_unavailble(bitmap, 0x20000, bitmap);
// Page Directory
PDE* kernel_page_directory = (PDE*)(bitmap + 0x20000);
PDE* kernel_page_directory = bitmap + 0x20000;
// Clear the PD
memset((uint8_t*)kernel_page_directory, 4096, 0);
@ -110,7 +120,7 @@ void main() {
((uint32_t*)0x521000)[i] = 0x121000 + 0x1000*i;
}
PTE** kernel_page_tables = (PTE**)0x521000;
PTE** kernel_page_tables = 0x521000;
for (int i = 0; i < 1023; i++) {
kernel_page_directory[i] = (PDE){
@ -130,15 +140,15 @@ void main() {
}
// Mark unavailable bitmap to 0x522000
mark_unavailble((uint32_t)bitmap, 0x4000000, bitmap);
mark_unavailble(bitmap, 0x4000000, bitmap);
// Now we want to map some stuff.
// But first, we should load the kernel somewhere
uint8_t* kernel_location = (uint8_t*)0x542000; // Just load it at 0x524000 for now
mark_unavailble((uint32_t)kernel_location, 0x20000, bitmap); // Just treat the kernel as not growing beyond 128k for now.
uint8_t* kernel_location = 0x542000; // Just load it at 0x524000 for now
mark_unavailble(kernel_location, 0x10000, bitmap); // Just treat the kernel as not growing beyond 32k for now.
map_many_4k_phys_to_virt((uint32_t)kernel_location, 0xc0000000, kernel_page_directory, kernel_page_tables, 0x20); // Map 32 pages from 0x522000 to 0xc0000000;
map_many_4k_phys_to_virt(kernel_location, 0xc0000000, kernel_page_directory, kernel_page_tables, 0x10); // Map 16 pages from 0x522000 to 0xc0000000;
map_4k_phys_to_virt((uint32_t)kernel_page_directory, 0xc0100000, kernel_page_directory, kernel_page_tables); // Map the page directory to 0xc0100000
map_many_4k_phys_to_virt(0x121000, 0xc0101000, kernel_page_directory, kernel_page_tables, 1024); // Map 1024 pages from 0x121000 to 0xc0101000
map_4k_phys_to_virt(0xb8000, 0xc0501000, kernel_page_directory, kernel_page_tables); // Map 0xb8000 (video) to 0xc0501000
@ -148,12 +158,12 @@ void main() {
mark_unavailble(0xa0000, 0x20000, bitmap);
uint8_t* vm_bitmap = (uint8_t*)0x522000;
mark_unavailble((uint32_t)vm_bitmap, 0x20000, bitmap);
uint8_t* vm_bitmap = 0x522000;
mark_unavailble(vm_bitmap, 0x20000, bitmap);
memset(vm_bitmap, 0x20000, 0xff);
mark_unavailble(0xc07a0000, 0x20000, vm_bitmap);
mark_unavailble(0xc0000000, 0x20000, vm_bitmap);
mark_unavailble(0xc0000000, 0x10000, vm_bitmap);
mark_unavailble(0xc0100000, 0x1000, vm_bitmap);
mark_unavailble(0xc0101000, 0x400000, vm_bitmap);
mark_unavailble(0xc0501000, 0x1000, vm_bitmap);
@ -173,31 +183,17 @@ void main() {
map_many_4k_phys_to_virt(0x8a000, 0xc1000000, kernel_page_directory, kernel_page_tables, 16);
mark_unavailble(0x8a000, 0x10000, bitmap);
// Identity map the first 1MiB of RAM
mark_unavailble(0, 0x100000, bitmap);
mark_unavailble(0, 0x100000, vm_bitmap);
map_many_4k_phys_to_virt_pl3(0, 0, kernel_page_directory, kernel_page_tables, 256);
load_file("KERNEL BIN", kernel_location);
printf("Stage2 success!\n");
//while (1);
asm volatile("mov %0, %%eax;"
"mov %%eax, %%cr3;"
"mov %%cr0, %%eax;"
"or $0x80000000, %%eax;"
"mov %%eax, %%cr0" : : "m" (kernel_page_directory));
asm volatile ("mov %0, %%esp":: "r"(0xc1000000 + 16*0x1000));
KernelInformationStruct kstruct= (KernelInformationStruct){
.pde = (PDE*)0xc0100000,
.page_directory_phys_addr = (uint32_t)kernel_page_directory,
.page_directory_phys_offset = 0xc0100000 - (uint32_t)kernel_page_directory,
.page_bitmap_phys = 0xc0600000,
.page_bitmap_virt = 0xc0620000,
.stack_ptr = 0xc1000000 + 16*0x1000 - sizeof(KernelInformationStruct) - 4,
.vga_addr = 0xc07a0000,
.remainingPages = pages
};
((void(*)(KernelInformationStruct))0xc0000000)(kstruct);
((void(*)(void))0xc0000000)();
}

View File

@ -6,40 +6,6 @@ typedef struct {
uint32_t pd_index : 10;
}__attribute__((packed)) split_addr;
void map_4k_phys_to_virt_pl3(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables) {
split_addr* split = (split_addr*)&virtual;
page_directory[split->pd_index] = (PDE){
.address = (uint32_t)(page_tables[split->pd_index]) >> 12,
.available = 0,
.page_4mb = 0,
.accessed = 0,
.disable_cache = 0,
.write_through_cache = 0,
.privilege = 3,
.present = 1,
.read_write = 1,
.ignored = 0,
.ignored2 = 0
};
page_tables[split->pd_index][split->pt_index] = (PTE){
.address = physical >> 12,
.available = 0,
.global = 0,
.accessed = 0,
.disable_cache = 0,
.dirty = 0,
.write_through_cache = 0,
.privilege = 3,
.present = 1,
.read_write = 1,
.ignored = 0
};
}
void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables) {
split_addr* split = (split_addr*)&virtual;
@ -74,11 +40,6 @@ void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_director
};
}
void map_many_4k_phys_to_virt_pl3(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count) {
for (int i=0; i<count; i++)
map_4k_phys_to_virt_pl3(physical + 4096*i, virtual + 4096*i, page_directory, page_tables);
}
void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count) {
for (int i=0; i<count; i++)
map_4k_phys_to_virt(physical + 4096*i, virtual + 4096*i, page_directory, page_tables);

View File

@ -34,5 +34,4 @@ typedef struct {
void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables);
void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count);
void map_many_4k_phys_to_virt_pl3(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count);
#endif

View File

@ -0,0 +1,165 @@
#include "screenstuff.h"
uint16_t* VMEM_ADDR = (uint16_t*)0xb8000;
const int TERM_WIDTH = 80;
const int TERM_HEIGHT = 25;
int cursor_x = 0;
int cursor_y = 0;
uint16_t get_curpos() {
uint16_t cursor_position = 0;
uint8_t* cursor_position_split = (uint8_t*)&cursor_position;
outb(0x3D4, 0x0F);
cursor_position_split[0] = inb(0x3D5);
outb(0x3D4, 0x0E);
cursor_position_split[1] = inb(0x3D5);
return cursor_position;
}
void init_term() {
uint16_t cursor_position = get_curpos();
cursor_y = cursor_position / TERM_WIDTH;
cursor_x = cursor_position % TERM_WIDTH;
}
void clear_screen() {
for (int i=0; i<TERM_WIDTH*TERM_HEIGHT; i++) {
VMEM_ADDR[i] = 0x0720;
}
}
void clear_line(int line) {
for (int x=0; x<TERM_WIDTH; x++) {
VMEM_ADDR[TERM_WIDTH*line + x] = 0x0720;
}
}
void set_curpos_raw(int curpos) {
uint8_t* cursor_position_split = (uint8_t*)&curpos;
outb(0x3D4, 0x0F);
outb(0x3D5, cursor_position_split[0]);
outb(0x3D4, 0x0E);
outb(0x3D5, cursor_position_split[1]);
cursor_x = (*(uint16_t*)cursor_position_split) % TERM_WIDTH;
cursor_y = (*(uint16_t*)cursor_position_split) / TERM_WIDTH;
}
void set_curpos(int x, int y) {
set_curpos_raw(y * TERM_WIDTH + x);
cursor_x = x;
cursor_y = y;
}
int int_to_decimal(unsigned int number, char* string_buffer) {
for (int i=0; i<11; i++)
string_buffer[i] = 0;
int index = 9;
unsigned int acc = number;
if (acc == 0)
string_buffer[index--] = '0';
while (acc != 0) {
string_buffer[index--] = 0x30+(acc%10);
acc /= 10;
}
return (index+1);
}
char dec_to_hex[16] = "0123456789abcdef";
int int_to_hex(unsigned int number, char* string_buffer) {
for (int i=0; i<8; i++)
string_buffer[i] = '0';
string_buffer[8] = 0;
int index = 7;
unsigned int acc = number;
if (acc == 0)
string_buffer[index--] = '0';
while (acc != 0) {
string_buffer[index--] = dec_to_hex[acc%0x10];
acc /= 0x10;
}
return (index+1);
}
void printf(const char* string, ...) {
va_list ptr;
va_start(ptr, string);
int index = 0;
int count = 0;
char current;
while (current=string[index++]) {
count++;
if (current == '\n') {
cursor_x = 0;
cursor_y++;
}
if (cursor_x == TERM_WIDTH) {
cursor_x = 0;
cursor_y++;
}
if (cursor_y == TERM_HEIGHT) {
for (int i=1; i<TERM_HEIGHT; i++) {
for (int x=0; x<TERM_WIDTH; x++) {
int from = i * TERM_WIDTH + x;
int to = (i-1) * TERM_WIDTH + x;
VMEM_ADDR[to] = VMEM_ADDR[from];
}
}
clear_line(24);
cursor_y--;
}
if (current == '%') {
int type = string[index++];
int offset;
switch (type) {
case 'd': {
char decimal_buffer[11];
offset = int_to_decimal(va_arg(ptr, int), decimal_buffer);
printf(decimal_buffer + offset);
break;
}
case 'x': {
char hex_buffer[8];
offset = int_to_hex(va_arg(ptr, int), hex_buffer);
printf(hex_buffer);
break;
}
case 's': {
printf(va_arg(ptr, const char*));
break;
}
case 'c': {
int mem_pos = cursor_y * TERM_WIDTH + cursor_x++;
int promoted = va_arg(ptr, int);
char charred = promoted;
VMEM_ADDR[mem_pos] = charred + (0x07<<8);
break;
}
}
continue;
}
if (current != '\n') {
int mem_pos = cursor_y * TERM_WIDTH + cursor_x++;
VMEM_ADDR[mem_pos] = current + (0x07<<8);
}
}
set_curpos(cursor_x, cursor_y);
va_end(ptr);
}
void non_moving_put(char chr) {
int mem_pos = cursor_y * TERM_WIDTH + cursor_x;
VMEM_ADDR[mem_pos] = chr + (0x07<<8);
}

View File

@ -0,0 +1,19 @@
#ifndef SCREENSTUFF_H
#define SCREENSTUFF_H
#include <stdarg.h>
#include "types.h"
#include "io.h"
uint16_t get_curpos();
void init_term();
void clear_screen();
void clear_line(int line);
void set_curpos_raw(int curpos);
void set_curpos(int x, int y);
int int_to_decimal(unsigned int number, char* string_buffer);
int int_to_hex(unsigned int number, char* string_buffer);
void printf(const char* string, ...);
void non_moving_put(char chr);
#endif

69
src/boot_stage2/strings.c Normal file
View File

@ -0,0 +1,69 @@
#include "strings.h"
bool strcmp(char* a, char* b, int max) {
int index = 0;
while (index < max) {
if (a[index] != b[index])
return false;
index++;
}
return true;
}
char* split_on_first(char delimeter, char* string) {
int index = 0;
char current;
while (current = string[index++]) {
if (current == delimeter) {
string[index-1] = 0;
return string+index;
}
}
return 0;
}
int string_split(char delimeter, char* string, char** pointer_array) {
int index = 0;
int last_split_index = 0;
int split_count = 0;
char current;
while (current = string[index]) {
if (current == delimeter) {
string[index] = 0;
pointer_array[split_count++] = (string+last_split_index);
last_split_index = (index+1);
}
index++;
}
// Add remaining part of the string to the pointer_array
pointer_array[split_count] = (string+last_split_index);
return split_count;
}
void decode_filename(char* nice_name, char* filenamebuffer) {
// Clear filenamebuffer
for (int i=0; i<11; i++)
filenamebuffer[i] = ' ';
filenamebuffer[11] = 0;
int fbIndex = 0;
for (int i=0; i<12; i++) {
if (nice_name[i] == 0)
return;
if (nice_name[i] == '.') {
fbIndex = 8;
continue;
}
if (nice_name[i] >= 0x61 && nice_name[i] <= 0x7f)
filenamebuffer[fbIndex++] = nice_name[i] - 32;
else
filenamebuffer[fbIndex++] = nice_name[i];
}
}

11
src/boot_stage2/strings.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef STRINGS_H
#define STRINGS_H
#include <stdbool.h>
bool strcmp(char* a, char* b, int max);
char* split_on_first(char delimeter, char* string);
int string_split(char delimeter, char* string, char** pointer_array);
void decode_filename(char* nice_name, char* filenamebuffer);
#endif

View File

@ -1,11 +0,0 @@
#include "strings.h"
bool strcmp(char* a, char* b, int max) {
int index = 0;
while (index < max) {
if (a[index] != b[index])
return false;
index++;
}
return true;
}

View File

@ -1,8 +0,0 @@
#ifndef STRINGS_H
#define STRINGS_H
#include <stdbool.h>
bool strcmp(char* a, char* b, int max);
#endif

View File

@ -3,7 +3,6 @@
_start:
mov ax, 10h
mov ds, ax
mov es, ax
mov ss, ax
mov esp, 90000h

View File

@ -1,81 +1,5 @@
#include "common.h"
#define syscall_hdlr_0(a, b, c) \
a b() { \
asm volatile("mov $" c ", %%eax; int $0x80" : : :); \
}
#define syscall_hdlr_1(a, b, c, d, e) \
a b(d e) { \
asm volatile("mov $" c ", %%eax; mov %0, %%ebx; int $0x80" : : "m" (e) : "ebx"); \
}
#define syscall_hdlr_2(a, b, c, d, e, f, g) \
a b(d e, f g) { \
asm volatile("mov $" c ", %%eax; mov %0, %%ebx; mov %1, %%ecx; int $0x80" : : "m" (e), "m" (g) : "ebx", "ecx"); \
}
#define syscall_hdlr_3(a, b, c, d, e, f, g, h, i) \
a b(d e, f g, h i) { \
asm volatile("mov $" c ", %%eax; mov %0, %%ebx; mov %1, %%ecx; mov %2, %%edx; int $0x80" : : "m" (e), "m" (g), "m" (i) : "ebx", "ecx", "edx"); \
}
#include "syscalls.h"
char** environ = 0;
uint32_t strcmpc(char* a, char* b, char c) {
for (int i=0; a[i] && b[i]; i++) {
if (a[i] == c)
return i;
}
return 0;
}
void __setup(uint32_t argc, char** argv, char** envp) {
environ = envp;
}
char* getenv(char* key) {
for (int i=0; environ[i]; i++) {
uint32_t pos;
if (pos = strcmpc(environ[i], key, '=')) {
return key+pos+1;
}
}
return 0;
}
void setenv(char* key, char* value) {
uint32_t environ_count = 0;
for (int i=0; environ[i]; i++)
environ_count += 1;
char** new_environ = (char**)malloc((environ_count+2)*sizeof(char*));
for (int i=0; i<environ_count; i++)
new_environ[i] = environ[i];
uint32_t key_size = strlen(key);
uint32_t value_size = strlen(value);
char* new_entry = (char*)malloc(key_size + value_size + 2);
memcpy(new_entry, key, key_size);
new_entry[key_size] = '=';
memcpy(new_entry+key_size+1, value, value_size);
new_entry[key_size+1+value_size] = 0;
new_environ[environ_count] = new_entry;
new_environ[environ_count+1] = 0;
environ = new_environ;
}
uint32_t strlen(char* s) {
uint32_t i=0;
while (s[i]) i++;
return i;
}
bool strcmp(char* a, char* b) {
for (int i=0; a[i] && b[i]; i++)
if (a[i] != b[i])
return false;
return true;
}
void print(char* string) {
char* c = string;
int i=0;
@ -84,6 +8,54 @@ void print(char* string) {
write(i, 0, (uint8_t*)string);
}
void* localalloc(uint32_t size) {
asm volatile ("mov $4, %%eax; mov %0, %%esi; int $0x7f" : : "m" (size) : "esi");
}
void localdelete(void* ptr) {
asm volatile ("mov $5, %%eax; mov %0, %%esi; int $0x7f" : : "m" (ptr) : "esi");
}
uint32_t getPID() {
asm volatile ("mov $8, %%eax; int $0x7f" : : :);
}
int read(uint32_t count, void* filehanlder, uint8_t* buffer) {
asm volatile ("mov $10, %%eax; mov %0, %%ebx; mov %1, %%esi; mov %2, %%edi; int $0x7f" : : "m" (count), "m" (filehanlder), "m" (buffer): "ebx", "esi", "edi");
}
int write(uint32_t count, void* filehanlder, uint8_t* buffer) {
asm volatile ("mov $11, %%eax; mov %0, %%ebx; mov %1, %%esi; mov %2, %%edi; int $0x7f" : : "m" (count), "m" (filehanlder), "m" (buffer): "ebx", "esi", "edi");
}
uint32_t fork(uint32_t fh) {
asm volatile("mov $7, %%eax; mov %0, %%esi; int $0x7f" : : "m" (fh) : "esi");
}
uint32_t bindStdout(uint32_t PID) {
asm volatile("mov $13, %%eax; mov %0, %%esi; int $0x7f" : : "m" (PID) : "esi");
}
uint32_t bindStdin(uint32_t PID) {
asm volatile("mov $14, %%eax; mov %0, %%esi; int $0x7f" : : "m" (PID) : "esi");
}
int fopen(char* filename) {
asm volatile("mov $15, %%eax; mov %0, %%esi; int $0x7f" : : "m" (filename) : "esi");
}
void fclose(uint32_t fh) {
asm volatile("mov $16, %%eax; mov %0, %%esi; int $0x7f" : : "m" (fh) : "esi");
}
void kill(uint32_t pid) {
asm volatile("mov $17, %%eax; mov %0, %%esi; int $0x7f" : : "m" (pid) : "esi");
}
void bindToKeyboard() {
asm volatile ("mov $12, %%eax; int $0x7f" : : :);
}
int int_to_decimal(unsigned int number, char* string_buffer) {
for (int i=0; i<11; i++)
string_buffer[i] = 0;
@ -115,96 +87,3 @@ int int_to_hex(unsigned int number, char* string_buffer) {
}
return (index+1);
}
bool isnum(char c) {
return c >= 0x30 && c <= 0x39;
}
void printf(const char* string, ...) {
va_list ptr;
va_start(ptr, string);
int index = 0;
char current;
while (current=string[index++]) {
if (current == '%') {
uint32_t width = 0;
bool lp = false;
if (string[index] == '.') {
lp = true;
index++;
} else {
while (isnum(string[index])) {
width *= 10;
width += string[index] - 0x30;
index++;
}
}
int type = string[index++];
int offset;
switch (type) {
case 'd': {
char decimal_buffer[11];
offset = int_to_decimal(va_arg(ptr, int), decimal_buffer);
print(decimal_buffer + offset);
break;
}
case 'x': {
char hex_buffer[8];
offset = int_to_hex(va_arg(ptr, int), hex_buffer);
print(hex_buffer);
break;
}
case 's': {
if (width) {
char s[width+1];
s[width] = 0;
memcpy(s, va_arg(ptr, const char*), width);
print(s);
} else if (lp) {
int width = va_arg(ptr, int);
char s[width+1];
s[width] = 0;
memcpy(s, va_arg(ptr, const char*), width);
print(s);
} else {
print(va_arg(ptr, const char*));
}
break;
}
case 'c': {
int promoted = va_arg(ptr, int);
char charred = promoted;
write(1, 0, &charred);
break;
}
}
continue;
}
write(1, 0, &current);
}
va_end(ptr);
}
void memset(void* ptr, char c, uint32_t count) {
for (int i=0; i<count; i++) {
((char*)ptr)[i] = c;
}
}
void memcpy(void* dst, void* src, uint32_t count) {
for (int i=0; i<count; i++)
((char*)dst)[i] = ((char*)src)[i];
}
uint32_t exec(uint32_t fh) {
uint8_t* zero = 0;
return execve(fh, &zero, (uint8_t**)environ);
}
uint32_t execv(uint32_t fh, char** argv) {
return execve(fh, (uint8_t**)argv, (uint8_t**)environ);
}

View File

@ -2,57 +2,28 @@
#define COMMON_H
#include "../kernel/types.h"
#include <stdarg.h>
typedef enum {
File,
Directory,
CharacterDev,
BlockDev,
NoExist
} FSType;
typedef struct {
uint16_t length;
uint8_t* path;
} PathEntry;
typedef struct {
PathEntry path;
FSType type;
uint32_t sizeBytes;
} FSDirectoryEntry;
typedef struct {
uint32_t count;
uint32_t stringsLength;
FSDirectoryEntry entries[];
} FSDirectoryListing;
#define syscall_hdlr_0(a, b, c) \
a b();
#define syscall_hdlr_1(a, b, c, d, e) \
a b(d e);
#define syscall_hdlr_2(a, b, c, d, e, f, g) \
a b(d e, f g);
#define syscall_hdlr_3(a, b, c, d, e, f, g, h, i) \
a b(d e, f g, h i);
#include "syscalls.h"
char* getenv(char* key);
void setenv(char* key, char* value);
uint32_t strlen(char* s);
bool strcmp(char* a, char* b);
void memset(void* ptr, char c, uint32_t count);
void memcpy(void* dst, void* src, uint32_t count);
void print(char* string);
void readfile(char* filename, uint8_t* buffer);
void* localalloc(uint32_t size);
void localdelete(void* ptr);
uint32_t filesize(char* filename);
uint32_t fork(uint32_t fh);
uint32_t bindStdout(uint32_t PID);
uint32_t bindStdin(uint32_t PID);
uint32_t getPID();
int read(uint32_t count, void* filehandler, uint8_t* buffer);
int write(uint32_t count, void* filehandler, uint8_t* buffer);
void bindToKeyboard();
int fopen(char* filename);
void fclose(uint32_t fh);
void kill(uint32_t pid);
int int_to_decimal(unsigned int number, char* string_buffer);
int int_to_hex(unsigned int number, char* string_buffer);
void printf(const char* string, ...);
uint32_t exec(uint32_t fh);
uint32_t execv(uint32_t fh, char** argv);
#endif

View File

@ -1,31 +0,0 @@
#include <stdbool.h>
syscall_hdlr_1(uint32_t, getDentsSize, "0", char*, path);
syscall_hdlr_2(void, getDents, "1", char*, path, uint8_t*, buffer);
syscall_hdlr_1(bool, exists, "2", char*, path);
syscall_hdlr_1(FSType, type, "3", char*, path);
syscall_hdlr_1(void*, malloc, "4", uint32_t, size);
syscall_hdlr_1(void, free, "5", void*, ptr);
syscall_hdlr_0(uint32_t, getMillisecondsElapsed, "6");
syscall_hdlr_3(uint32_t, execve, "7", uint32_t, fh, uint8_t**, argv, uint8_t**, envp);
syscall_hdlr_0(uint32_t, getPID, "8");
syscall_hdlr_1(void, die, "9", uint32_t, exit);
syscall_hdlr_3(int, read, "10", uint32_t, count, uint32_t, filehandler, uint8_t*, buffer);
syscall_hdlr_3(int, write, "11", uint32_t, count, uint32_t, filehandler, const uint8_t*, buffer);
syscall_hdlr_0(void, bindToKeyboard, "12");
syscall_hdlr_1(uint32_t, bindStdout, "13", uint32_t, PID);
syscall_hdlr_1(uint32_t, bindStdin, "14", uint32_t, PID);
syscall_hdlr_1(uint32_t, fopen, "15", char*, filename);
syscall_hdlr_1(void, fclose, "16", uint32_t, filehandler);
syscall_hdlr_1(void, kill, "17", uint32_t, PID);
syscall_hdlr_1(void, sleep, "18", uint32_t, time);
syscall_hdlr_0(uint32_t, getRemainingPages, "19");
syscall_hdlr_0(uint32_t, getInitPages, "20");
syscall_hdlr_0(uint32_t, getCurrentTerminalWidth, "21");
syscall_hdlr_0(uint32_t, getCurrentTerminalHeight, "22");
syscall_hdlr_1(uint32_t, getProcessState, "23", uint32_t, PID);
syscall_hdlr_1(void, spawnThread, "24", uint32_t, functionPointer);
syscall_hdlr_0(uint32_t, fork, "25");
syscall_hdlr_1(bool, programRunning, "26", uint32_t, pid);

40
src/hello/hello.c Normal file
View File

@ -0,0 +1,40 @@
#include "../common/common.h"
void readline(int count, char* buffer) {
int index = 0;
char c;
while (index < count) {
if (read(1, 1, &c)) {
if (c == '\n')
break;
if (c == '\b') {
if (index == 0)
continue;
else {
index--;
buffer[index] = 0;
write(1, 0, &c);
continue;
}
}
buffer[index++] = c;
write(1, 0, &c);
}
}
print("\n");
}
int main() {
print("Hello, World!\n");
char buffer[32];
while (1) {
for (int i=0; i<32; i++)
buffer[i] = 0;
print(">>> ");
readline(32, buffer);
print("You said: ");
print(buffer);
print("\n\n");
}
}

14
src/hello/hello.ld Normal file
View File

@ -0,0 +1,14 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:i386)
OUTPUT(build/hello/hello.bin)
SECTIONS {
. = 0x20;
.text : {
build/program_code_entry.o(.text)
build/hello/hello.o(.text)
build/common/common.o(.text)
}
}

View File

@ -8,6 +8,12 @@ uint32_t kernel_allocate_area = 0xf0000000;
uint32_t last_free_page = 0;
/*void init_allocator() {
for (int i=0; i<1024; i++) {
kernel_page_tables[i] = 0xc0101000 + 0x1000*i;
}
}*/ // Don't do this.
void set_bit(uint32_t offset, uint8_t* buffer) {
uint32_t index = offset / 8;
uint32_t bit = offset % 8;

View File

@ -3,6 +3,7 @@
#include "paging.h"
#include "datatypes/tuple.h"
//void init_allocator();
extern uint8_t* bitmap;
extern PDE* kernel_page_directory;

View File

@ -1,169 +0,0 @@
#include "ata.h"
uint16_t controlBase[4] = {0x1f0, 0x170, 0x1e8, 0x168};
uint16_t dcrBase[4] = {0x3f6, 0x376, 0x3e6, 0x366};
uint8_t ATA::readStatus() {
uint8_t status;
for (int i=0; i<15; i++)
status=StatusRegister.readb();
return status;
}
uint8_t ATA::pollTillNotBSY() {
uint8_t lastStatus;
while (((lastStatus=StatusRegister.readb()) & 0x80))
if (lastStatus&0x1)
return lastStatus;
return 0;
}
uint8_t ATA::pollTillDRQ() {
uint8_t lastStatus;
while (!((lastStatus=StatusRegister.readb()) & 0x8))
if (lastStatus&0x1)
return lastStatus;
return 0;
}
ATA::ATA(uint32_t bus) :
DataRegister(controlBase[bus]+0),
ErrorRegister(controlBase[bus]+1),
FeaturesRegister(controlBase[bus]+1),
SectorCountRegister(controlBase[bus]+2),
LBALo(controlBase[bus]+3),
LBAMid(controlBase[bus]+4),
LBAHi(controlBase[bus]+5),
DriveSelectRegister(controlBase[bus]+6),
StatusRegister(controlBase[bus]+7),
CommandRegister(controlBase[bus]+7) {
this->isValid = 0;
DriveSelectRegister.writeb(0xA0);
LBALo.writeb(0);
LBAMid.writeb(0);
LBAHi.writeb(0);
CommandRegister.writeb(0xEC);
if (!readStatus()) {
this->isValid = false;
} else {
pollTillNotBSY();
uint8_t LBAmid;
uint8_t LBAhi;
if ((LBAmid = LBAMid.readb()) || (LBAhi = LBAHi.readb())) {
this->isValid = false;
} else {
uint8_t status = pollTillDRQ();
if (!(status&0x1)) {
for (int i=0; i<256; i++)
((uint16_t*)identifyResult)[i] = DataRegister.readw();
this->isValid = true;
}
}
}
if (this->isValid) {
this->totalLBA28Sectors = *((uint32_t*)(identifyResult+60));
this->diskSize = this->totalLBA28Sectors * 512;
}
}
bool ATA::validDevice() {
return this->isValid;
}
void ATA::ATARead(uint32_t sector, uint8_t* buffer) {
driveLock.lock();
DriveSelectRegister.writeb(0xE0 | ((sector >> 24) & 0xf));
SectorCountRegister.writeb(1);
LBALo.writeb((uint8_t)sector);
LBAMid.writeb((uint8_t)(sector>>8));
LBAHi.writeb((uint8_t)(sector>>16));
CommandRegister.writeb(0x20);
pollTillNotBSY();
for (int i=0; i<256; i++)
((uint16_t*)buffer)[i] = DataRegister.readw();
driveLock.unlock();
}
void ATA::ATAWrite(uint32_t sector, uint8_t* buffer) {
driveLock.lock();
DriveSelectRegister.writeb(0xE0 | ((sector >> 24) & 0xf));
SectorCountRegister.writeb(1);
LBALo.writeb((uint8_t)sector);
LBAMid.writeb((uint8_t)(sector>>8));
LBAHi.writeb((uint8_t)(sector>>16));
CommandRegister.writeb(0x30);
pollTillNotBSY();
for (int i=0; i<256; i++)
DataRegister.writew(((uint16_t*)buffer)[i]);
CommandRegister.writeb(0xe7);
driveLock.unlock();
}
ATAReadWriter::ATAReadWriter(uint32_t bus):
ATA(bus) {
this->currentPosition = 0;
}
uint32_t ATAReadWriter::read(uint32_t count, uint8_t* buffer) {
driveLock.lock();
uint32_t remainingBytes = count;
uint32_t inThisSector = currentPosition % 512;
uint32_t index=0;
uint32_t c=0;
ATARead(currentPosition / 512, sectorBuffer);
while (remainingBytes) {
if (currentPosition >= diskSize)
break;
buffer[index++] = sectorBuffer[inThisSector++];
remainingBytes--;
currentPosition++;
if (inThisSector == 512) {
ATARead(currentPosition / 512, sectorBuffer);
inThisSector = 0;
}
c++;
}
driveLock.unlock();
return c;
}
uint32_t ATAReadWriter::write(uint32_t count, uint8_t* buffer) {
driveLock.lock();
uint32_t remainingBytes = count;
uint32_t inThisSector = currentPosition % 512;
uint32_t index=0;
uint32_t c=0;
ATARead(currentPosition / 512, sectorBuffer);
while (remainingBytes) {
if (currentPosition >= diskSize)
break;
sectorBuffer[inThisSector++] = buffer[index++];
remainingBytes--;
currentPosition++;
if (inThisSector == 512) {
ATAWrite((currentPosition / 512) - 1, sectorBuffer);
ATARead(currentPosition / 512, sectorBuffer);
inThisSector = 0;
}
c++;
}
// Perform a final write to ensure that we've written everything to disk.
ATAWrite((currentPosition / 512), sectorBuffer);
driveLock.unlock();
return c;
}
uint32_t ATAReadWriter::size() {
return this->diskSize;
}
uint32_t ATAReadWriter::seek(uint32_t position) {
this->currentPosition = position;
return position;
}

View File

@ -1,110 +0,0 @@
#ifndef ATA_PIO
#define ATA_PIO
#include "io.h"
#include "types.h"
#include "strings.h"
#include "global.h"
#include "stdio/readwriter.h"
#include "spinlock.h"
// Bus 0
// Control Ports: 1F0-1F7
// DCR / Alt Status: 3F6
// IRQ: 14
// Bus 1
// Control Ports: 170-177
// DCR / Alt Status: 376
// IRQ: 15
// Bus 2
// Control Ports: 1E8-1EF
// DCR / Alt Status: 3E6
// IRQ: Determine via PCI
// Bus 3
// Control Ports: 168-16F
// DCR / Alt Status: 366
// IRQ: Determine via PCI
// Control Port Map
// Name | RW | Offset | Size28 | Size48
// Data Register RW 0 2 2
// Error Register R 1 1 2
// Features Reg. W 1 1 2
// Sector Count Reg. RW 2 1 2
// LBAlo RW 3 1 2
// LBAmid RW 4 1 2
// LBAhi RW 5 1 2
// Drive Select RW 6 1 1
// Status Reg R 7 1 1
// Command Reg W 7 1 1
// DCR Port Map
// Name | RW | Offset | Size28 | Size48
// Alt. Status R 0 1 1
// Device Control W 1 1 1
// Device Address R 1 1 1
enum ATADriveType {
ATA,
ATAPI,
SATA
};
class ATA {
private:
ATADriveType type;
Spinlock driveLock;
protected:
uint32_t bus;
uint32_t totalLBA28Sectors;
uint32_t diskSize;
uint8_t identifyResult[512];
Port DataRegister;
Port ErrorRegister;
Port FeaturesRegister;
Port SectorCountRegister;
Port LBALo;
Port LBAMid;
Port LBAHi;
Port DriveSelectRegister;
Port StatusRegister;
Port CommandRegister;
bool isValid;
uint8_t readStatus();
uint8_t pollTillNotBSY();
uint8_t pollTillDRQ();
public:
ATA(uint32_t bus);
bool validDevice();
void ATARead(uint32_t sector, uint8_t* buffer);
void ATAWrite(uint32_t sector, uint8_t* buffer);
};
class ATAReadWriter: public ReadWriter, public ATA {
private:
uint8_t sectorBuffer[512];
uint32_t currentPosition;
Spinlock driveLock;
public:
ATAReadWriter(uint32_t bus);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;
uint32_t size() override;
uint32_t seek(uint32_t position) override;
};
#endif

255
src/kernel/atapio.cpp Normal file
View File

@ -0,0 +1,255 @@
#include "atapio.h"
// Disk code
// Primary ATA Bus: 0x1f0 to 0x1f7
// Device Control Register: 0x3f6
// Secondary ATA Bus: 0x170 to 0x177
// Device Control Register: 0x376
uint16_t identify_result[256];
uint32_t total_28_lbas = 0;
DirectoryEntry* rootDirEntries;
uint16_t* FAT1;
uint16_t countReserved;
uint8_t countFATs;
uint16_t countRDEs;
uint16_t sectorsPerFAT;
void init_atapio() {
rootDirEntries = (DirectoryEntry*)new uint8_t[8192];
FAT1 = (uint16_t*)(new uint8_t[512 * 34]);
uint32_t boot_sector = new uint32_t[1024];
read_sectors(0, 1, (uint8_t*)boot_sector);
countReserved = *((uint16_t*)(boot_sector + 0x0e));
countFATs = *((uint8_t*)(boot_sector + 0x10));
countRDEs = *((uint16_t*)(boot_sector + 0x11));
sectorsPerFAT = *((uint16_t*)(boot_sector + 0x16));
// Select Drive 0 on the Primary Bus
outb(0x1f6, 0xa0);
// Set sector count to 0 for IDENTIFY
outb(0x1f2, 0);
// Set LBAlo to 0
outb(0x1f3, 0);
// Set LBAmid to 0
outb(0x1f4, 0);
// Set LBAhi to 0
outb(0x1f5, 0);
// Send IDENTIFY command
outb(0x1f7, 0xec);
uint8_t status = inb(0x1f7);
if (status) {
while ((status = inb(0x1f7)) & 0x80);
if ( !(inb(0x1f4) || inb(0x1f5)) ) {
while ( !(status & 8 || status & 1) )
status = inb(0x1f7);
if (!(status & 1)) {
for (int index=0; index<256; index++)
identify_result[index] = inw(0x1f0);
}
}
}
total_28_lbas = *(uint32_t*)(identify_result+60);
// We've initialised now, let's load the FAT and RootDirEntries.
read_sectors(sectorsPerFAT * countFATs + countReserved, countRDEs / 16, (uint8_t*)rootDirEntries);
read_sectors(countReserved, sectorsPerFAT, (uint8_t*)FAT1);
}
void read_sector(uint32_t address, uint8_t* buffer) {
outb(0x1f6, 0xe0 | ((address>>24)&0x0f));
// Read a single sector
outb(0x1f2, 1);
// Set LBAlo, LBAmid and LBAhi
outb(0x1f3, address);
outb(0x1f4, address>>8);
outb(0x1f5, address>>16);
// Send read command
outb(0x1f7, 0x20);
// Poll
uint8_t status = inb(0x1f7);
while ( (status & 0x80) && !(status & 8) )
status = inb(0x1f7);
for (int index=0; index<256; index++)
((uint16_t*)buffer)[index] = inw(0x1f0);
}
void read_sectors(uint32_t address, int count, uint8_t* buffer) {
for (int i=0; i<count; i++) {
read_sector(address+i, buffer+512*i);
for (int i=0; i<15; i++)
inb(0x1f7);
}
}
uint32_t clusterToSector(uint32_t cluster) {
return cluster + (sectorsPerFAT * countFATs) + (countRDEs / 16) + (countReserved - 1) - 1;
}
int split_on_char(char c, char* str, char** split) {
char* cstr = str;
char* last = str;
uint32_t count = 0;
while (*cstr) {
if (*cstr == c) {
*cstr = 0;
split[count++] = last;
last = cstr+1;
}
cstr++;
}
split[count++] = last;
return count;
}
void to83(char* filename, char* buf83) {
char* c = filename;
for (int i=0;i<11;i++)
buf83[i] = ' ';
uint32_t bufpos = 0;
while (*c && bufpos != 11) {
if (*c == '.')
bufpos = 8;
else
buf83[bufpos++] = *c & 223;
c++;
}
}
void load_file(uint32_t location, uint8_t* destination) {
int offset = 0;
bool loaded = false;
while (!loaded) {
uint16_t fromSector = clusterToSector(location);
read_sector(fromSector, destination+offset);
offset += 512;
location = FAT1[location++];
if (location == 0xffff)
loaded = true;
}
}
int calc_size(uint32_t location) {
int offset = 0;
bool loaded = false;
while (!loaded) {
uint16_t fromSector = clusterToSector(location);
offset += 512;
location = FAT1[location++];
if (location == 0xffff)
loaded = true;
}
return offset;
}
DirectoryEntry* get_DE(char* filename) {
DirectoryEntry* dirbuf;
Directory dir = {
.entry = rootDirEntries,
.entries = countRDEs
};
char* levels[8];
int count = split_on_char('/', filename, levels);
for (int i=0; i<(count-1); i++) {
char normalname[11] = {' '};
to83(levels[i], normalname);
for (int e=0; e<dir.entries; e++) {
bool found=strcmp(dir.entry[e].name, normalname, 11);
if (found) {
DirectoryEntry* de = &dir.entry[e];
uint32_t size = calc_size(de->firstClusterLow);
dirbuf = (DirectoryEntry*)(new uint8_t[size]);
uint32_t cluster = de->firstClusterLow;
load_file(cluster, (uint8_t*)dirbuf);
dir.entry = dirbuf;
dir.entries = size / 32;
break;
}
}
}
char normalname[11];
to83(levels[count-1], normalname);
for (int i=0; i<dir.entries; i++) {
bool found = strcmp(dir.entry[i].name, normalname, 11);
if (found) {
return &dir.entry[i];
}
}
return 0;
}
uint16_t file_exists(char* filename) {
DirectoryEntry* de = get_DE(filename);
if (de)
return de->firstClusterLow;
return 0;
}
uint32_t file_size(char* filename) {
for (int i=0; i<countRDEs; i++) {
bool found = strcmp(rootDirEntries[i].name, filename, 11);
if (found) {
if (rootDirEntries[i].size % 512)
return ((rootDirEntries[i].size / 512) + 1) * 512;
else
return rootDirEntries[i].size;
}
}
return 0;
}
void load_file(char* filename, uint8_t* location) {
DirectoryEntry* de = get_DE(filename);
load_file(de->firstClusterLow, location);
}
FATFileReadWriter::FATFileReadWriter(uint32_t owner, char* filename)
: ReadWriter(owner) {
this->bytesRead = 0;
DirectoryEntry* de = get_DE(filename);
this->sizeBytes = de->size;
this->currentCluster = de->firstClusterLow;
this->read_buffer = new uint8_t[512];
read_sector(clusterToSector(this->currentCluster), this->read_buffer);
}
uint32_t FATFileReadWriter::read(uint32_t count, uint8_t* buffer) {
int index = 0;
while (count) {
buffer[index] = this->read_buffer[this->bytesRead++];
if (this->bytesRead == 512) {
this->currentCluster = FAT1[this->currentCluster++];
read_sector(clusterToSector(this->currentCluster), this->read_buffer);
this->bytesRead = 0;
}
count--;
index++;
}
}
uint32_t FATFileReadWriter::write(uint32_t count, uint8_t* buffer) {}
uint32_t FATFileReadWriter::size() {
return this->sizeBytes;
}

77
src/kernel/atapio.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef ATA_PIO
#define ATA_PIO
#include <stdbool.h>
#include "io.h"
#include "types.h"
#include "strings.h"
#include "allocate.h"
#include "global.h"
#include "stdio/readwriter.h"
struct __attribute__((packed)) DirectoryEntry {
char name[11];
uint8_t _ignored0 : 3;
uint8_t archive : 1;
uint8_t directory : 1;
uint8_t volumeid : 1;
uint8_t system : 1;
uint8_t hidden : 1;
uint8_t readonly : 1;
uint8_t _ignored1;
uint16_t createdHour : 5;
uint16_t createdMinute : 6;
uint16_t createdSecond : 5;
uint16_t createdYear : 7;
uint16_t createdMonth : 4;
uint16_t createdDay : 5;
uint16_t lastAccessYear : 7;
uint16_t lastAccessMonth : 4;
uint16_t lastAccessDay : 5;
uint16_t firstClusterHigh;
uint16_t modifiedHour : 5;
uint16_t modifiedMinute : 6;
uint16_t modifiedSecond : 5;
uint16_t modifiedYear : 7;
uint16_t modifiedMonth : 4;
uint16_t modifiedDay : 5;
uint16_t firstClusterLow;
uint32_t size;
};
struct Directory {
DirectoryEntry* entry;
uint32_t entries;
};
void init_atapio();
void read_sector(uint32_t address, uint8_t* buffer);
void read_sectors(uint32_t address, int count, uint8_t* buffer);
uint16_t file_exists(char* filename);
void load_file(char* filename, uint8_t* location);
uint32_t file_size(char* filename);
class FATFileReadWriter : public ReadWriter {
private:
uint32_t sizeBytes;
uint32_t bytesRead;
uint32_t currentCluster;
uint8_t* read_buffer;
public:
FATFileReadWriter(uint32_t owner, char* filename);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;
uint32_t size() override;
};
#endif

View File

@ -1,71 +0,0 @@
#ifndef DYNARRAY_H
#define DYNARRAY_H
#include "../global.h"
#include "maybe.h"
#include "../spinlock.h"
namespace xnoe {
template<typename T>
class dynarray {
private:
uint32_t size = 128;
T* buffer;
uint32_t index = 0;
uint32_t start_index = 0;
Spinlock lock;
public:
dynarray(uint32_t start_index=0) {
this->buffer = new T[size];
this->index = this->start_index = start_index;
}
dynarray(dynarray* d) {
this->size = d->size;
this->buffer = new T[size];
this->index = d->index;
this->start_index = d->start_index;
memcpy((uint8_t*)this->buffer, (uint8_t*)d->buffer, sizeof(T)*d->size);
}
void push(T t) {
if (index == size) {
lock.lock();
uint32_t old_size = size;
size *= 2;
T* buffer_tmp = new T[size];
memcpy((uint8_t*)buffer_tmp, (uint8_t*)buffer, sizeof(T)*old_size);
delete buffer;
buffer = buffer_tmp;
lock.unlock();
}
buffer[index++] = t;
}
uint32_t length() {
return index;
}
xnoe::maybe<T> pop() {
if (index == start_index)
return xnoe::maybe<T>();
return xnoe::maybe<T>(buffer[--index]);
}
xnoe::maybe<T> get(uint32_t i) {
if (i>size)
return xnoe::maybe<T>();
return xnoe::maybe<T>(buffer[i]);
}
void set(uint32_t i, T t) {
if (i>size)
return;
buffer[i] = t;
}
};
}
#endif

View File

@ -5,6 +5,7 @@
#include "linkedlist.h"
#include "../memory.h"
#include "maybe.h"
#include "../screenstuff.h"
namespace xnoe {
template <class key, class value>
@ -39,19 +40,19 @@ namespace xnoe {
list->append(xnoe::tuple<key, value>(k, v));
}
xnoe::maybe<value> get(key k) {
xnoe::Maybe<value> get(key k) {
xnoe::linkedlist<xnoe::tuple<key, value>>* list = &table[xnoe::hash<key>(k) % 4096];
xnoe::linkedlistelem<xnoe::tuple<key, value>>* current = list->start;
if (current) {
while (current) {
if (xnoe::get<0>(current->elem) == k)
return xnoe::maybe<value>(xnoe::get<1>(current->elem));
return xnoe::Maybe<value>(xnoe::get<1>(current->elem));
current = current->next;
}
}
return xnoe::maybe<value>();
return xnoe::Maybe<value>();
}
void remove(key k) {
@ -59,12 +60,11 @@ namespace xnoe {
xnoe::linkedlistelem<xnoe::tuple<key, value>>* current = list->start;
if (current) {
while (current) {
xnoe::linkedlistelem<xnoe::tuple<key, value>>* next = current->next;
if (xnoe::get<0>(current->elem) == k) {
list->remove(current);
delete current;
}
current = next;
current = current->next;
}
}
}

View File

@ -1,9 +1,7 @@
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "../types.h"
#include "../memory.h"
#include "../spinlock.h"
namespace xnoe {
template<typename T>
@ -21,38 +19,25 @@ namespace xnoe {
template<typename T>
struct linkedlist {
xnoe::linkedlistelem<T>* start=0;
xnoe::linkedlistelem<T>* end=0;
Spinlock lock = Spinlock();
uint32_t length = 0;
xnoe::linkedlistelem<T>* start;
xnoe::linkedlistelem<T>* end;
bool has(T t) {
xnoe::linkedlistelem<T>* current = this->start;
while (start) {
if (start->elem == t)
return true;
//current = current->next;
}
return false;
}
void destroy() {
xnoe::linkedlistelem<T>* current = this->start;
while (current) {
xnoe::linkedlistelem<T>* c = current;
current = current->next;
delete c;
}
}
void append(T t) {
xnoe::linkedlistelem<T>* llelem = new xnoe::linkedlistelem<T>(t);
append(llelem);
}
void append(xnoe::linkedlistelem<T>* llelem) {
lock.lock();
if (this->start && this->end) {
this->end->next = llelem;
llelem->prev = this->end;
@ -62,8 +47,6 @@ namespace xnoe {
this->start = llelem;
this->end = llelem;
}
length++;
lock.unlock();
}
void prepend(T t) {
@ -72,7 +55,6 @@ namespace xnoe {
}
void prepend(xnoe::linkedlistelem<T>* llelem) {
lock.lock();
if (this->start && this->end) {
this->start->prev = llelem;
llelem->next = this->start;
@ -82,19 +64,14 @@ namespace xnoe {
this->start = llelem;
this->end = llelem;
}
length++;
lock.unlock();
}
void insert(linkedlist<T>* ll, uint32_t index) {
lock.lock();
linkedlistelem<T>* current = this->start;
for (int i=0; i<index; i++, current = current->next);
current->next->prev = ll->end;
current->next = ll->start;
length += ll.length;
lock.unlock();
}
/*void remove(uint32_t index) {
@ -108,7 +85,6 @@ namespace xnoe {
}*/
void remove(linkedlistelem<T>* elem) {
lock.lock();
linkedlistelem<T>* current = start;
while (current) {
if (current == elem) {
@ -119,22 +95,18 @@ namespace xnoe {
current->next->prev = current->prev;
if (current == start)
start = current->next;
start = 0;
if (current = end)
end = current->prev;
end = 0;
length--;
lock.unlock();
return;
}
current = current->next;
}
lock.unlock();
}
void remove(T elem) {
lock.lock();
linkedlistelem<T>* current = start;
while (current) {
if (current->elem == elem) {
@ -152,13 +124,10 @@ namespace xnoe {
delete current;
length--;
lock.unlock();
return;
}
current = current->next;
}
lock.unlock();
}
};
}

View File

@ -3,17 +3,17 @@
namespace xnoe {
template<typename T>
class maybe {
class Maybe {
private:
T t;
bool ok;
public:
maybe() {
Maybe() {
this->ok = false;
}
maybe(T t) {
Maybe(T t) {
this->ok = true;
this->t = t;
}

View File

@ -1,6 +1,7 @@
[BITS 32]
_start:
mov esp, 0xc100a000
jmp main
extern main

View File

@ -1,5 +0,0 @@
#include "devfs.h"
DevFS::DevFS() {
addEntry(createPathFromString("ata"), [](){return new ATAReadWriter(0);});
}

View File

@ -1,14 +0,0 @@
#ifndef DEVFS_H
#define DEVFS_H
#include "fstree.h"
#include "../ata.h"
#include "../kernel.h"
#include "vfs.h"
class DevFS : public VFS {
public:
DevFS();
};
#endif

View File

@ -1,401 +0,0 @@
#include "fat16.h"
uint32_t FAT16FileReadWriter::offsetBytesToCluster(uint32_t offset) {
uint32_t cluster = this->firstCluster;
uint32_t remaining = offset;
while (remaining > this->clusterSize) {
cluster = this->backingFS->FAT1[this->firstCluster];
remaining -= this->clusterSize;
}
return cluster;
}
FAT16FileReadWriter::FAT16FileReadWriter(uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS) {
this->firstCluster = firstCluster;
this->sizeBytes = sizeBytes;
this->currentPosition = 0;
this->backingFS = backingFS;
this->clusterSize = 512 * (uint32_t)(*this->backingFS->sectorsPerCluster);
}
uint32_t FAT16FileReadWriter::read(uint32_t count, uint8_t* buffer) {
//uint8_t* clusterBuffer = new uint8_t[this->clusterSize];
uint8_t clusterBuffer[this->clusterSize];
uint32_t clusterToRead = offsetBytesToCluster(this->currentPosition);
uint32_t sectorToRead = this->backingFS->clusterToSector(clusterToRead);
this->backingFS->backingDevice->seek(sectorToRead * this->clusterSize);
this->backingFS->backingDevice->read(this->clusterSize, clusterBuffer);
uint32_t currentClusterIndex = this->currentPosition % this->clusterSize;
if (this->currentPosition >= this->sizeBytes)
return 0;
uint32_t remaining = count;
uint32_t index = 0;
while (remaining) {
if (currentClusterIndex == this->clusterSize) {
clusterToRead = this->backingFS->FAT1[clusterToRead];
if (clusterToRead == 0xffff)
break;
sectorToRead = this->backingFS->clusterToSector(clusterToRead);
this->backingFS->backingDevice->seek(sectorToRead * this->clusterSize);
this->backingFS->backingDevice->read(this->clusterSize, clusterBuffer);
currentClusterIndex = 0;
}
buffer[index++] = clusterBuffer[currentClusterIndex++];
remaining--;
this->currentPosition++;
}
//delete[] clusterBuffer;
return index;
}
uint32_t FAT16FileReadWriter::write(uint32_t count, uint8_t* buffer) {return;}
uint32_t FAT16FileReadWriter::size() {
return this->sizeBytes;
}
uint32_t FAT16FileReadWriter::seek(uint32_t position) {
if (position < this->sizeBytes) {
this->currentPosition = position;
return position;
}
return 0;
}
char safeUppercase(char c) {
switch (c) {
case 'a'...'z':
return c & ~32;
default:
return c;
}
}
void FAT16FS::pathEntryTo83(PathEntry pe, char* buffer) {
uint32_t maxSize = pe.length;
uint8_t* data = pe.path;
uint32_t readIndex=0;
uint32_t writeIndex=0;
while (writeIndex<11 && readIndex < maxSize) {
char c;
if ((c=data[readIndex++]) == '.') {
writeIndex = 8;
continue;
}
buffer[writeIndex++] = safeUppercase(c);
}
}
uint32_t FAT16FS::clusterToSector(uint32_t cluster) {
return (cluster * (uint32_t)(*this->sectorsPerCluster)) + (*sectorsPerFAT * *countFATs) + (*countRDEs / 16) + (*countReserved - 1) - 1;
}
void FAT16FS::load_file(uint32_t location, uint8_t* destination) {
int offset = 0;
bool loaded = false;
while (!loaded) {
uint16_t fromSector = clusterToSector(location);
this->backingDevice->seek(fromSector * 512 * *this->sectorsPerCluster);
this->backingDevice->read(512 * *this->sectorsPerCluster, destination+offset);
offset += 512 * *this->sectorsPerCluster;
location = FAT1[location++];
if (location == 0xffff)
loaded = true;
}
}
uint32_t FAT16FS::calc_size(uint32_t location) {
int offset = 0;
bool loaded = false;
while (!loaded) {
uint16_t fromSector = clusterToSector(location);
offset += 512 * *this->sectorsPerCluster;
location = FAT1[location++];
if (location == 0xffff)
loaded = true;
}
return offset;
}
xnoe::tuple<DirectoryEntry*, uint32_t, bool> FAT16FS::getDirectoryEntry(Path p) {
PathElement* current = p.start;
DirectoryEntry* currentDirectory = new DirectoryEntry[*countRDEs];
for (int i=0; i < *countRDEs; i++)
currentDirectory[i] = rootDirEntries[i];
uint32_t count = *countRDEs;
if (!current)
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
escape_for:
while (current != p.end) {
char name83[12] = " ";
pathEntryTo83(current->elem, name83);
for (int i=0; i < count; i++) {
if (strcmp(currentDirectory[i].name, name83, 11)) {
DirectoryEntry found = currentDirectory[i];
if (!(found.directory))
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
delete currentDirectory;
uint32_t sizeBytes = calc_size(found.firstClusterLow);
currentDirectory = (DirectoryEntry*)(new uint8_t[sizeBytes]);
load_file(found.firstClusterLow, (uint8_t*)currentDirectory);
i=0;
count = sizeBytes / sizeof(DirectoryEntry);
current = current->next;
goto escape_for;
}
}
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, 0, false);
}
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
}
xnoe::tuple<DirectoryEntry*, uint32_t, bool> FAT16FS::getDirectoryEntryFull(Path p) {
PathElement* current = p.start;
DirectoryEntry* currentDirectory = new DirectoryEntry[*countRDEs];
for (int i=0; i < *countRDEs; i++)
currentDirectory[i] = rootDirEntries[i];
uint32_t count = *countRDEs;
if (!current)
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
escape_for:
while (current) {
char name83[12] = " ";
pathEntryTo83(current->elem, name83);
for (int i=0; i < count; i++) {
if (strcmp(currentDirectory[i].name, name83, 11)) {
DirectoryEntry found = currentDirectory[i];
if (!(found.directory))
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
delete currentDirectory;
uint32_t sizeBytes = calc_size(found.firstClusterLow);
currentDirectory = (DirectoryEntry*)(new uint8_t[sizeBytes]);
load_file(found.firstClusterLow, (uint8_t*)currentDirectory);
i=0;
count = sizeBytes / sizeof(DirectoryEntry);
current = current->next;
goto escape_for;
}
}
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, 0, false);
}
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
}
FAT16FS::FAT16FS(ReadWriter* disk) {
this->backingDevice = disk;
this->backingDevice->seek(0);
this->backingDevice->read(512, sectorOne);
this->rootDirEntries = new DirectoryEntry[*countRDEs];
this->backingDevice->seek(((*sectorsPerFAT) * (*countFATs) + (*countReserved)) * 512);
this->backingDevice->read((*countRDEs) * sizeof(DirectoryEntry), (uint8_t*)this->rootDirEntries);
this->FAT1 = new uint16_t[(*sectorsPerFAT) * 256];
this->backingDevice->seek((*countReserved) * 512);
this->backingDevice->read((*sectorsPerFAT) * 512, (uint8_t*)FAT1);
}
bool FAT16FS::exists(Path p) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntry(p);
if (!xnoe::get<2>(directory))
return false;
bool found = false;
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
uint32_t count = xnoe::get<1>(directory);
PathElement* end = p.end;
if (!end)
return false;
char name83[12] = " ";
name83[11] = 0;
pathEntryTo83(end->elem, name83);
for (int i=0; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
found = true;
break;
}
}
delete directoryEntries;
return found;
}
FSType FAT16FS::type(Path p) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntry(p);
if (!xnoe::get<2>(directory))
return NoExist;
FSType found = NoExist;
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
uint32_t count = xnoe::get<1>(directory);
PathElement* end = p.end;
if (!end)
return NoExist;
char name83[12] = " ";
pathEntryTo83(end->elem, name83);
for (int i=0; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
if (directoryEntries[i].directory)
found = Directory;
else
found = File;
}
}
delete directoryEntries;
return found;
}
ReadWriter* FAT16FS::open(Path p) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntry(p);
if (!xnoe::get<2>(directory))
return 0;
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
uint32_t count = xnoe::get<1>(directory);
PathElement* end = p.end;
if (!end)
return 0;
uint32_t written=0;
char name83[12] = " ";
name83[11] = 0;
pathEntryTo83(end->elem, name83);
for (int i=0; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
if (!directoryEntries[i].directory)
return new FAT16FileReadWriter(((uint32_t)directoryEntries[i].firstClusterHigh << 16) | directoryEntries[i].firstClusterLow, directoryEntries[i].size, this);
}
}
delete directoryEntries;
return 0;
}
PathEntry name83ToPathEntry(char* name83, char* text) {
uint32_t mainLength = 8;
uint32_t index = 7;
while (name83[index] == ' ' && index--)
mainLength--;
uint32_t extLength = 3;
index = 10;
while (name83[index] == ' ' && index-- > 7)
extLength--;
memcpy(text, name83, mainLength);
if (name83[8] != ' ') {
text[mainLength] = '.';
memcpy(text+mainLength+1, name83+8, extLength);
}
text[mainLength+extLength+1] = 0;
return PathEntry{mainLength+extLength+1, text};
}
uint32_t getRealCount(DirectoryEntry* directoryEntries, uint32_t c) {
uint32_t r = 0;
for (int i = 0; i < c; i++) {
if (directoryEntries[i].name[0] != 0 && directoryEntries[i].name[0] != 0xE5 && !directoryEntries[i].volumeid)
r++;
}
return r;
}
uint32_t FAT16FS::getDentsSize(Path p) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntryFull(p);
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
if (!xnoe::get<2>(directory)) {
delete directoryEntries;
return 0;
}
uint32_t found = 0;
uint32_t count = xnoe::get<1>(directory);
found += sizeof(FSDirectoryListing);
for (int i=0; i<count; i++) {
if (directoryEntries[i].name[0] != 0 && directoryEntries[i].name[0] != 0xE5 && !directoryEntries[i].volumeid) {
found += sizeof(FSDirectoryEntry);
found += 13;
}
}
delete directoryEntries;
return found;
}
void FAT16FS::getDents(Path p, FSDirectoryListing* buffer) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntryFull(p);
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
if (!xnoe::get<2>(directory)) {
delete directoryEntries;
return 0;
}
uint32_t count = xnoe::get<1>(directory);
uint32_t written=0;
buffer->count = getRealCount(directoryEntries, count);
buffer->stringsLength = 0;
char* nameBuffer = ((char*)buffer);
nameBuffer += sizeof(FSDirectoryEntry)*buffer->count + sizeof(FSDirectoryListing);
for (int i=0; i<count; i++) {
if (directoryEntries[i].name[0] != 0 && directoryEntries[i].name[0] != 0xE5 && !directoryEntries[i].volumeid) {
buffer->entries[written] = FSDirectoryEntry {
name83ToPathEntry(directoryEntries[i].name, nameBuffer + 13*written),
directoryEntries[i].directory ? Directory : File,
directoryEntries[i].size
};
written++;
buffer->stringsLength += 13;
}
}
delete directoryEntries;
}

View File

@ -1,119 +0,0 @@
#ifndef FAT16_H
#define FAT16_H
#include "fstree.h"
#include "../memory.h"
#include "../stdio/readwriter.h"
#include "../datatypes/tuple.h"
struct __attribute__((packed)) DirectoryEntry {
char name[11];
uint8_t readonly : 1;
uint8_t hidden : 1;
uint8_t system : 1;
uint8_t volumeid : 1;
uint8_t directory : 1;
uint8_t archive : 1;
uint8_t device : 1;
uint8_t _ignored0 : 1;
uint8_t f1 : 1;
uint8_t f2 : 1;
uint8_t f3 : 1;
uint8_t f4 : 1;
uint8_t _ignored1 : 1;
uint8_t deleteRequiresPassword : 1;
uint8_t writeRequiresPassword : 1;
uint8_t readRequiresPassword : 1;
uint8_t createTime10ms;
uint16_t createdHour : 5;
uint16_t createdMinute : 6;
uint16_t createdSecond : 5;
uint16_t createdYear : 7;
uint16_t createdMonth : 4;
uint16_t createdDay : 5;
uint16_t lastAccessYear : 7;
uint16_t lastAccessMonth : 4;
uint16_t lastAccessDay : 5;
uint16_t firstClusterHigh;
uint16_t modifiedHour : 5;
uint16_t modifiedMinute : 6;
uint16_t modifiedSecond : 5;
uint16_t modifiedYear : 7;
uint16_t modifiedMonth : 4;
uint16_t modifiedDay : 5;
uint16_t firstClusterLow;
uint32_t size;
};
struct Directory {
DirectoryEntry* entry;
uint32_t entries;
};
class FAT16FS;
class FAT16FileReadWriter: public ReadWriter {
private:
uint32_t firstCluster;
uint32_t sizeBytes;
uint32_t currentPosition;
uint32_t offsetBytesToCluster(uint32_t offset);
uint32_t clusterSize;
FAT16FS* backingFS;
public:
FAT16FileReadWriter(uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;
uint32_t size() override;
uint32_t seek(uint32_t position) override;
};
class FAT16FS: public FSTree {
public:
DirectoryEntry* rootDirEntries;
uint16_t* FAT1;
uint8_t sectorOne[512];
uint8_t* sectorsPerCluster = ((uint8_t*)(sectorOne + 0x0d));
uint16_t* countReserved = ((uint16_t*)(sectorOne + 0x0e));
uint8_t* countFATs = ((uint8_t*)(sectorOne + 0x10));
uint16_t* countRDEs = ((uint16_t*)(sectorOne + 0x11));
uint16_t* sectorsPerFAT = ((uint16_t*)(sectorOne + 0x16));
ReadWriter* backingDevice;
void pathEntryTo83(PathEntry pe, char* buffer);
uint32_t clusterToSector(uint32_t cluster);
void load_file(uint32_t location, uint8_t* destination);
uint32_t calc_size(uint32_t location);
xnoe::tuple<DirectoryEntry*, uint32_t, bool> getDirectoryEntry(Path p);
xnoe::tuple<DirectoryEntry*, uint32_t, bool> getDirectoryEntryFull(Path p);
FAT16FS(ReadWriter* disk);
bool exists(Path p) override;
FSType type(Path p) override;
ReadWriter* open(Path p) override;
uint32_t getDentsSize(Path p) override;
void getDents(Path p, FSDirectoryListing* buffer) override;
};
#endif

View File

@ -1,270 +0,0 @@
#include "fstree.h"
bool operator==(const PathEntry& lhs, const PathEntry& rhs) {
if (lhs.length == rhs.length)
if (lhs.length == 0)
return true;
else if (lhs.length < rhs.length)
return strcmp(lhs.path, rhs.path, lhs.length);
else
return strcmp(lhs.path, rhs.path, lhs.length);
return false;
}
bool operator!=(const PathEntry& lhs, const PathEntry& rhs) {
return !(lhs == rhs);
}
// FS Tree Skeleton
bool FSTree::exists(Path p){return;}
FSType FSTree::type(Path p){return;}
ReadWriter* FSTree::open(Path p){return;}
uint32_t FSTree::getDentsSize(Path p){return;}
void FSTree::getDents(Path p, FSDirectoryListing* buffer){return;}
// RootFSTree
RootFSTree::RootFSTree() {
this->node = new FSTreeNode{
PathEntry{0,0},
xnoe::linkedlist<FSTreeNode*>(),
0
};
}
bool pathEntryInFSTreeNode(PathEntry p, FSTreeNode* n) {
xnoe::linkedlistelem<FSTreeNode*>* current = n->children.start;
while (current) {
if (current->elem->self == p)
return true;
current = current->next;
}
return false;
}
FSTreeNode* getNodeFromPathEntry(PathEntry p, FSTreeNode* n) {
if (!n)
return 0;
xnoe::linkedlistelem<FSTreeNode*>* current = n->children.start;
while (current) {
if (current->elem->self == p)
return current->elem;
current = current->next;
}
return 0;
}
FSTreeNode* RootFSTree::makeNodeIfNotExist(Path p) {
PathElement* currentPathElement = p.start;
FSTreeNode* currentNode = this->node;
if (!currentPathElement || currentPathElement == p.end)
return currentNode;
nextPE:
while (currentPathElement) {
xnoe::linkedlistelem<FSTreeNode*>* currentChild = currentNode->children.start;
while (currentChild) {
if (currentChild->elem->self == currentPathElement->elem) {
currentNode = currentChild->elem;
currentPathElement = currentPathElement->next;
goto nextPE;
}
currentChild = currentChild->next;
}
currentNode->children.append(new FSTreeNode{currentPathElement->elem, xnoe::linkedlist<FSTreeNode*>(), 0});
currentNode = currentNode->children.end->elem;
currentPathElement = currentPathElement->next;
}
return currentNode;
}
FSTree* RootFSTree::getLongestMatchingUnder(Path p) {
PathElement* currentPath = p.start;
FSTreeNode* currentNode = this->node;
FSTree* lastMountpoint = 0;
while (currentPath && currentNode) {
if ((currentPath->elem == currentNode->self) && currentNode->mountpoint)
lastMountpoint = currentNode->mountpoint;
currentNode = getNodeFromPathEntry(currentPath->elem, currentNode);
if (currentNode && currentNode->mountpoint)
lastMountpoint = currentNode->mountpoint;
currentPath = currentPath->next;
}
return lastMountpoint;
}
Path* RootFSTree::getRemainingPath(Path p) {
PathElement* currentPath = p.start;
FSTreeNode* currentNode = this->node;
PathElement* lastMountpoint = 0;
while (currentPath && currentNode) {
if (currentPath->elem == currentNode->self && currentNode->mountpoint)
lastMountpoint = currentPath;
currentNode = getNodeFromPathEntry(currentPath->elem, currentNode);
if (currentNode && currentNode->mountpoint)
lastMountpoint = currentPath;
currentPath = currentPath->next;
}
lastMountpoint = lastMountpoint->next;
if (lastMountpoint) {
Path* np = new Path;
PathElement* current = lastMountpoint;
while (current) {
np->append(current->elem);
current = current->next;
}
return np;
}
return 0;
}
FSTreeNode* RootFSTree::getExhaustive(Path p) {
PathElement* currentPath = p.start;
FSTreeNode* currentNode = this->node;
if (!currentPath)
return 0;
if (currentPath->elem != currentNode->self)
return 0;
while (currentPath && currentNode) {
currentNode = getNodeFromPathEntry(currentPath->elem, currentNode);
currentPath = currentPath->next;
}
if (currentPath)
return 0;
else
return currentNode;
}
template<typename T>
T RootFSTree::attempt(T(FSTree::*fn)(Path), Path p, T fallback) {
FSTree* mp = getLongestMatchingUnder(p);
if (mp) {
Path* rp = getRemainingPath(p);
T r;
if (rp) {
r = (mp->*fn)(*rp);
rp->destroy();
} else {
r = (mp->*fn)(Path());
}
return r;
}
return fallback;
}
void RootFSTree::attempt(void(FSTree::*fn)(Path, FSDirectoryListing*), Path p, FSDirectoryListing* b) {
FSTree* mp = getLongestMatchingUnder(p);
if (mp) {
Path* rp = getRemainingPath(p);
if (rp) {
(mp->*fn)(*rp, b);
rp->destroy();
} else {
(mp->*fn)(Path(), b);
}
}
}
bool RootFSTree::exists(Path p) {
return attempt<bool>(&FSTree::exists, p, false);
}
FSType RootFSTree::type(Path p){
return attempt<FSType>(&FSTree::type, p, Directory);
}
ReadWriter* RootFSTree::open(Path p){
return attempt<ReadWriter*>(&FSTree::open, p, 0);
}
uint32_t RootFSTree::getDentsSize(Path p){
uint32_t size = attempt<uint32_t>(&FSTree::getDentsSize, p, 0);
FSTreeNode* n = getExhaustive(p);
if (n) {
xnoe::linkedlistelem<FSTreeNode*>* current = n->children.start;
while (current) {
size += sizeof(FSDirectoryEntry);
size += current->elem->self.length;
current = current->next;
}
}
return size;
}
void RootFSTree::getDents(Path p, FSDirectoryListing* buffer){
attempt(&FSTree::getDents, p, buffer);
uint32_t oldCount = buffer->count;
uint32_t stringsOffset = buffer->count * sizeof(FSDirectoryEntry) + sizeof(FSDirectoryListing);
uint32_t addCount = 0;
char* strings = ((uint32_t)buffer) + stringsOffset;
FSTreeNode* n = getExhaustive(p);
if (n) {
xnoe::linkedlistelem<FSTreeNode*>* current = n->children.start;
while (current) {
addCount++;
current = current->next;
}
if (addCount) {
current = n->children.start;
for (int i=buffer->stringsLength; i>=0; i--)
strings[i+addCount*sizeof(FSDirectoryEntry)] = strings[i];
for (int i=0; i < buffer->count; i++)
buffer->entries[i].path.path += addCount*sizeof(FSDirectoryEntry);
while (current) {
strings += addCount*sizeof(FSDirectoryEntry) + buffer->stringsLength;
memcpy(strings, current->elem->self.path, current->elem->self.length);
buffer->entries[buffer->count++] = FSDirectoryEntry {
PathEntry{
current->elem->self.length,
strings
},
Directory,
0
};
strings += current->elem->self.length;
current = current->next;
}
}
}
}
bool RootFSTree::isMountpoint(Path p) {
Path* mp = getRemainingPath(p);
if (mp->start->next)
return false;
else
return true;
}
void RootFSTree::mount(Path p, FSTree* f) {
FSTreeNode* fstn = makeNodeIfNotExist(p);
fstn->mountpoint = f;
}
void RootFSTree::unmount(Path p) {
}
Path createPathFromString(char* s) {
Path p;
p.start = 0;
p.end = 0;
char* lastPtr = s;
uint32_t length = 0;
char c;
while (c=*(s++)) {
if (c == '/') {
if (length == 0)
p.append(PathEntry{length, 0});
else
p.append(PathEntry{length, lastPtr});
lastPtr = s;
length = 0;
continue;
}
length += 1;
}
if (length)
p.append(PathEntry{length, lastPtr});
return p;
}

View File

@ -1,87 +0,0 @@
#ifndef FSTREE_H
#define FSTREE_H
#include "../datatypes/linkedlist.h"
#include "../stdio/readwriter.h"
#include "../strings.h"
struct PathEntry {
uint16_t length;
uint8_t* path;
};
bool operator==(const PathEntry& lhs, const PathEntry& rhs);
using Path = xnoe::linkedlist<PathEntry>;
using PathElement = xnoe::linkedlistelem<PathEntry>;
enum FSType {
File,
Directory,
CharacterDev,
BlockDev,
NoExist
};
struct FSDirectoryEntry {
PathEntry path;
FSType type;
uint32_t sizeBytes;
};
struct FSDirectoryListing {
uint32_t count;
uint32_t stringsLength;
FSDirectoryEntry entries[];
};
class FSTreeNode;
class FSTree {
public:
virtual bool exists(Path p);
virtual FSType type(Path p);
virtual ReadWriter* open(Path p);
virtual uint32_t getDentsSize(Path p);
virtual void getDents(Path p, FSDirectoryListing* buffer);
};
struct FSTreeNode {
PathEntry self;
xnoe::linkedlist<FSTreeNode*> children;
FSTree* mountpoint;
};
class RootFSTree: public FSTree {
private:
FSTree* getLongestMatchingUnder(Path p);
Path* getRemainingPath(Path p);
FSTreeNode* getExhaustive(Path p);
FSTreeNode* makeNodeIfNotExist(Path p);
template<typename T>
T attempt(T(FSTree::*fn)(Path), Path p, T fallback);
void attempt(void(FSTree::*fn)(Path, FSDirectoryListing*), Path p, FSDirectoryListing* b);
public:
RootFSTree();
FSTreeNode* node;
bool isMountpoint(Path p);
void mount(Path p, FSTree* f);
void unmount(Path p);
bool exists(Path p) override;
FSType type(Path p) override;
ReadWriter* open(Path p) override;
uint32_t getDentsSize(Path p) override;
void getDents(Path p, FSDirectoryListing* buffer) override;
};
Path createPathFromString(char* s);
#endif

View File

@ -1,28 +0,0 @@
#include "sysfs.h"
SysFS::SysFS() {
addEntry(createPathFromString("remainingPages"), [](){
uint32_t remainingPages = Global::kernel->phys->remainingPages;
char str[11];
uint32_t offset = int_to_decimal(remainingPages, str);
return new OneShotReadWriter(str+offset);
});
addEntry(createPathFromString("initPages"), [](){
uint32_t initPages = Global::kernel->phys->initPages;
char str[11];
uint32_t offset = int_to_decimal(initPages, str);
return new OneShotReadWriter(str+offset);
});
addEntry(createPathFromString("terminalWidth"), [](){
uint32_t termWidth = Global::kernel->terminal->width;
char str[11];
uint32_t offset = int_to_decimal(termWidth, str);
return new OneShotReadWriter(str+offset);
});
addEntry(createPathFromString("terminalHeight"), [](){
uint32_t termHeight = Global::kernel->terminal->height;
char str[11];
uint32_t offset = int_to_decimal(termHeight, str);
return new OneShotReadWriter(str+offset);
});
}

View File

@ -1,14 +0,0 @@
#ifndef SYSFS_H
#define SYSFS_H
#include "vfs.h"
#include "../kernel.h"
#include "../strings.h"
#include "../stdio/oneshotreadwriter.h"
class SysFS : public VFS {
public:
SysFS();
};
#endif

View File

@ -1,133 +0,0 @@
#include "vfs.h"
void VFS::addEntry(Path p, ReadWriter*(*constructor)(Path)) {
PathElement* currentPathElement = p.start;
VFSTreeNode* currentNode = this->root;
if (!currentPathElement)
return currentNode;
nextPE:
while (currentPathElement) {
xnoe::linkedlistelem<VFSTreeNode*>* currentChild = currentNode->children.start;
while (currentChild) {
if (currentChild->elem->self == currentPathElement->elem) {
currentNode = currentChild->elem;
currentPathElement = currentPathElement->next;
goto nextPE;
}
currentChild = currentChild->next;
}
if (currentPathElement = p.end) {
currentNode->children.append(new VFSTreeNode{currentPathElement->elem, xnoe::linkedlist<VFSTreeNode*>(), constructor, false});
} else {
if (currentPathElement->elem == PathEntry{1, "*"})
currentNode->children.append(new VFSTreeNode{currentPathElement->elem, xnoe::linkedlist<VFSTreeNode*>(), 0, true});
else
currentNode->children.append(new VFSTreeNode{currentPathElement->elem, xnoe::linkedlist<VFSTreeNode*>(), 0, false});
}
currentNode = currentNode->children.end->elem;
currentPathElement = currentPathElement->next;
}
return currentNode;
}
Constructor VFS::getEntry(Path p) {
PathElement* currentPathElement = p.start;
VFSTreeNode* currentNode = this->root;
if (!currentPathElement)
return 0;
nextPE:
while (currentPathElement) {
xnoe::linkedlistelem<VFSTreeNode*>* currentChild = currentNode->children.start;
while (currentChild) {
if (currentChild->elem->self == currentPathElement->elem || currentChild->elem->wildcard) {
currentNode = currentChild->elem;
currentPathElement = currentPathElement->next;
goto nextPE;
}
currentChild = currentChild->next;
}
return 0;
}
if (currentNode->children.length == 0)
return currentNode->constructor;
return 0;
}
VFSTreeNode* VFS::getNode(Path p) {
PathElement* currentPathElement = p.start;
VFSTreeNode* currentNode = this->root;
nextPE:
while (currentPathElement) {
xnoe::linkedlistelem<VFSTreeNode*>* currentChild = currentNode->children.start;
while (currentChild) {
if (currentChild->elem->self == currentPathElement->elem || currentChild->elem->wildcard) {
currentNode = currentChild->elem;
currentPathElement = currentPathElement->next;
goto nextPE;
}
currentChild = currentChild->next;
}
return 0;
}
return currentNode;
}
bool VFS::exists(Path p) {
return getEntry(p);
}
ReadWriter* VFS::open(Path p) {
Constructor c = getEntry(p);
return c(p);
}
uint32_t VFS::getDentsSize(Path p) {
VFSTreeNode* node = getNode(p);
if (!node)
return 0;
uint32_t total = sizeof(FSDirectoryListing);
xnoe::linkedlistelem<VFSTreeNode*>* currentNode = node->children.start;
while (currentNode) {
total += sizeof(FSDirectoryEntry);
total += currentNode->elem->self.length;
currentNode = currentNode->next;
}
return total;
}
void VFS::getDents(Path p, FSDirectoryListing* buffer) {
VFSTreeNode* node = getNode(p);
if (!node)
return;
uint32_t total = sizeof(FSDirectoryListing);
xnoe::linkedlistelem<VFSTreeNode*>* currentNode = node->children.start;
buffer->count = 0;
while (currentNode) {
buffer->count++;
currentNode = currentNode->next;
}
uint8_t* strings = (uint8_t*)(buffer) + sizeof(FSDirectoryListing) + sizeof(FSDirectoryEntry) * buffer->count;
currentNode = node->children.start;
uint32_t index = 0;
while (currentNode) {
memcpy(strings, currentNode->elem->self.path, currentNode->elem->self.length);
buffer->entries[index++] = FSDirectoryEntry{
PathEntry{currentNode->elem->self.length, strings},
File,
0
};
strings += currentNode->elem->self.length;
buffer->stringsLength += currentNode->elem->self.length;
currentNode = currentNode->next;
}
}

View File

@ -1,29 +0,0 @@
#ifndef VFS_H
#define VFS_H
#include "fstree.h"
using Constructor = ReadWriter*(*)(Path);
struct VFSTreeNode {
PathEntry self;
xnoe::linkedlist<VFSTreeNode*> children;
ReadWriter*(*constructor)(Path);
bool wildcard;
};
class VFS : public FSTree {
VFSTreeNode* root = new VFSTreeNode{PathEntry{0,0},xnoe::linkedlist<VFSTreeNode*>(),0,false};
public:
void addEntry(Path p, ReadWriter*(*)(Path));
Constructor getEntry(Path p);
VFSTreeNode* getNode(Path p);
bool exists(Path p) override;
ReadWriter* open(Path p) override;
uint32_t getDentsSize(Path p) override;
void getDents(Path p, FSDirectoryListing* buffer) override;
};
#endif

View File

@ -38,7 +38,7 @@ tss_struct tss = (tss_struct) {
.ldtr = 0,
._reserved10 = 0,
._reserved11 = 0,
.iopb = sizeof(tss_struct)
.iopb = 104
};
constexpr gdt_entry::gdt_entry(uint32_t limit, uint32_t base, bool rw, bool exec, bool system, uint8_t ring) :
@ -77,8 +77,7 @@ constexpr gdt_entry::gdt_entry() :
base_hi(0)
{}
gdt_and_iopb gai = {
.gdt = {
gdt_entry gdt[] = {
gdt_entry(), // Null Segment
gdt_entry(0xfffff, 0, 1, 1, 1, 0), // Kernel Code Segment
gdt_entry(0xfffff, 0, 1, 0, 1, 0), // Kernel Data Segment
@ -87,19 +86,16 @@ gdt_and_iopb gai = {
gdt_entry(0xfffff, 0, 1, 0, 1, 3), // User Data Segment
gdt_entry() // Empty Task State Segment
}
};
gdt_descr descr = (gdt_descr){
.size = sizeof(gai.gdt) - 1,
.offset = gai.gdt,
.size = sizeof(gdt) - 1,
.offset = gdt,
};
void init_gdt() {
gai.gdt[5] = gdt_entry(sizeof(tss) + 8193, &tss, 0, 1, 0, 0); // Initialise the TSS.
gai.gdt[5].accessed = 1;
for (int i=0; i<8192; i++)
gai.iopb[i] = 0;
gdt[5] = gdt_entry(sizeof(tss), &tss, 0, 1, 0, 0); // Initialise the TSS.
gdt[5].accessed = 1;
asm volatile("lgdt %0;"
"mov $0x10, %%eax;"
"mov %%eax, %%ss;"

View File

@ -76,11 +76,6 @@ struct __attribute__((packed)) gdt_descr {
uint32_t offset;
};
struct __attribute__((packed)) gdt_and_iopb {
gdt_entry gdt[6];
uint8_t iopb[8192];
};
void init_gdt();
#endif

View File

@ -7,9 +7,6 @@ for i ({0..255}); do
echo "isr$i:" >> isr.S
echo " push ebp" >> isr.S
echo " mov ebp, esp" >> isr.S
if (( (i == 8 || i == 17 || (i >= 10 && i <= 14) ) )); then
echo " add ebp, 4" >> isr.S
fi
if (( !(i == 8 || i == 17 || (i >= 10 && i <= 14) ) )); then
echo " push 0" >> isr.S
fi

View File

@ -4,11 +4,9 @@ namespace Global {
Allocator* allocator = 0;
Kernel* kernel = 0;
Process* currentProc = 0;
Thread* currentThread = 0;
tss_struct* tss = 0;
bool currentProcValid = false;
uint32_t milliseconds_elapsed = 0;
uint32_t resp = 0;
xnoe::hashtable<void*, ReadWriter*>* FH; // Map of File Handlers -> Read Writer
}
void* operator new (uint32_t size) {
@ -34,11 +32,3 @@ void* operator new[] (uint32_t size) {
void operator delete[] (void* ptr) {
Global::allocator->deallocate((uint32_t)ptr);
}
int clamp(int a, int b, int c) {
if (a < b)
return b;
if (a > c)
return c;
return a;
}

View File

@ -6,19 +6,20 @@
class Kernel;
class Allocator;
class Process;
class Thread;
struct tss_struct;
class ReadWriter;
namespace xnoe {
template<class, class>
class hashtable;
}
namespace Global {
extern Allocator* allocator;
extern Kernel* kernel;
extern Process* currentProc;
extern Thread* currentThread;
extern tss_struct* tss;
extern bool currentProcValid;
extern uint32_t milliseconds_elapsed;
extern uint32_t resp;
extern xnoe::hashtable<void*, ReadWriter*>* FH;
}
void* operator new (uint32_t size);
@ -29,6 +30,4 @@ void operator delete (void* ptr, unsigned int size);
void* operator new[] (uint32_t size);
void operator delete[] (void* ptr);
int clamp(int a, int b, int c);
#endif

View File

@ -22,12 +22,11 @@ void set_entry(uint8_t interrupt_number, uint16_t code_segment, void(*handler)()
}
void handle_fault(frame_struct* frame) {
//frame_struct* frame = &Global::currentThread->frame;
// Clear interrupts, we don't want to perform a context switch whilst handling a fault.
asm ("cli");
uint32_t problem_address;
asm ("mov %%cr2, %0" : "=a" (problem_address):);
Global::kernel->terminal->printf("\x1b[44;37;1m(CS %x EIP %x): ", frame->cs, frame->eip);
Global::kernel->terminal->printf("(CS %x EIP %x): ", frame->cs, frame->eip);
switch (frame->gate) {
case 0: // Divide by zero
Global::kernel->terminal->printf("Divide by Zero");
@ -37,23 +36,17 @@ void handle_fault(frame_struct* frame) {
break;
case 13: // GPF
Global::kernel->terminal->printf("General Protection Fault!");
if (frame->eflags & 0x00020000) {
Global::kernel->terminal->printf("\x1b[42;37;1mv86 GPF! All is good!\n");
v86_monitor((v8086_frame_struct*)frame);
return;
}
break;
case 14: // Page Fault
Global::kernel->terminal->printf("Page Fault at %x", problem_address);
break;
default:
Global::kernel->terminal->printf("Unkown Fault! Gate: %d", frame->gate);
Global::kernel->terminal->printf("Unkown Fault!");
break;
}
Global::kernel->terminal->printf(" Error Code: %x\n", frame->errcode);
if (!(frame->cs & 3)) {
Global::kernel->terminal->printf("[FATAL] Kernel Fault!!!\n");
((VGAModeTerminal*)Global::kernel->terminal)->bufferToVRAM();
while (1) asm("hlt");
} else {
// Print an error message.
@ -65,14 +58,16 @@ void handle_fault(frame_struct* frame) {
Global::kernel->destroyProcess(Global::currentProc);
Global::currentProcValid = false;
context_switch();
// Go in to an infinite loop
asm ("sti");
while (1) asm ("hlt");
}
}
void ignore_interrupt(frame_struct* _) {}
void ignore_interrupt(frame_struct* frame) {}
void context_switch() {
frame_struct* frame = &Global::currentThread->frame;
void context_switch(frame_struct* frame) {
// When any interrupt occurs (including context_switch), SS:ESP is set to
// the values of SS0:ESP0 in Global::tss
//
@ -88,123 +83,101 @@ void context_switch() {
asm ("cli"); // Disable interrupts whilst handling the context switch.
xnoe::linkedlist<Thread*>* threads = &Global::kernel->threads;
xnoe::linkedlist<Process*>* processes = &Global::kernel->processes;
if (!threads->start) {
if (!processes->start) {
Global::kernel->terminal->printf("[FATAL] No more processes! Halting!\n");
while (1) asm ("hlt");
}
if (Global::currentProcValid)
Global::currentProc->kernelStackPtr = frame->new_esp;
// This cursed bit of code first determines if the processes list is longer than 1 and if it is
// - Determines if it has 2 or more elements
// - If it has two, swap the first and last, update prev and next of each to be null or the other item
// - If it has more than two, add the start to the end then set start to the second element
uint32_t count = 0;
do {
if (count++ == threads->length)
return;
if (Global::currentThread) {
if (threads->start->next != 0) {
if (threads->end->prev == threads->start) {
xnoe::linkedlistelem<Thread*>* tmp = threads->start;
threads->start = threads->end;
threads->end = tmp;
if (Global::currentProc) {
if (processes->start->next != 0) {
if (processes->end->prev == processes->start) {
xnoe::linkedlistelem<Process*>* tmp = processes->start;
processes->start = processes->end;
processes->end = tmp;
threads->start->prev = 0;
threads->end->next = 0;
threads->end->prev = threads->start;
threads->start->next = threads->end;
processes->start->prev = 0;
processes->end->next = 0;
processes->end->prev = processes->start;
processes->start->next = processes->end;
} else {
threads->end->next = threads->start;
threads->start = threads->start->next;
threads->start->prev = 0;
xnoe::linkedlistelem<Thread*>* tmp = threads->end;
threads->end = threads->end->next;
threads->end->next = 0;
threads->end->prev = tmp;
processes->end->next = processes->start;
processes->start = processes->start->next;
processes->start->prev = 0;
xnoe::linkedlistelem<Process*>* tmp = processes->end;
processes->end = processes->end->next;
processes->end->next = 0;
processes->end->prev = tmp;
}
}
}
Global::currentThread = threads->start->elem;
Global::currentProc = threads->start->elem->parent;
} while (Global::currentThread->state != Running);
Global::currentProc = processes->start->elem;
// Select the next processes page directory
Global::currentThread->frame.new_cr3 = Global::currentThread->parent->PD->phys_addr;
frame->new_cr3 = Global::currentProc->PD->phys_addr;
// Restore kernelStackPtr of the new process.
frame->new_esp = Global::currentProc->kernelStackPtr;
Global::tss->esp0 = (uint32_t)Global::currentThread->kernelStackPtrDefault;
Global::tss->esp0 = Global::currentProc->kernelStackPtrDefault;
// Set the current proc to valid
Global::currentProcValid = true;
}
namespace Timer {
// counter, default count, function, argument, oneshot
using TimedEvent = xnoe::tuple<uint32_t, uint32_t, void(*)(void*), void*, bool>;
using TimedEvent = xnoe::tuple<uint32_t, uint32_t, void(*)(frame_struct*, void*), void*>;
xnoe::linkedlist<TimedEvent> timed_events;
void tick(frame_struct* _) {
void tick(frame_struct* frame) {
xnoe::linkedlistelem<TimedEvent>* current = timed_events.start;
while (current) {
TimedEvent t = current->elem;
uint32_t count = xnoe::get<0>(t);
if (--count == 0) {
xnoe::get<2>(t)(xnoe::get<3>(t));
xnoe::get<2>(t)(frame, xnoe::get<3>(t));
count = xnoe::get<1>(t);
if (xnoe::get<4>(t)) {
xnoe::linkedlistelem<TimedEvent>* prev = current;
current = current->next;
timed_events.remove(prev);
delete prev;
continue;
}
}
current->elem = TimedEvent(count, xnoe::get<1>(t), xnoe::get<2>(t), xnoe::get<3>(t), xnoe::get<4>(t));
current->elem = TimedEvent(count, xnoe::get<1>(t), xnoe::get<2>(t), xnoe::get<3>(t));
current = current->next;
}
Global::milliseconds_elapsed++;
}
void register_event(uint32_t milliseconds, void(*function)(void*), void* auxiliary, bool oneshot=false) {
timed_events.append(TimedEvent(milliseconds, milliseconds, function, auxiliary, oneshot));
void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary) {
timed_events.append(TimedEvent(milliseconds, milliseconds, function, auxiliary));
}
}
void awaken(Thread* t) {
t->state = Running;
}
void syscall(frame_struct* _) {
void syscall(frame_struct* frame) {
// Syscall ABI:
// 0: getDentsSize :: char* path -> uint32_t size
// 1: getDents :: char* path -> uint8_t* buffer -> void
// 2: exists :: char* path -> bool
// 3: type :: char* path -> FSType
// 4: localalloc :: uint32_t size -> void* ptr
// 5: localdelete :: void* ptr -> void
// 6: getMillisecondsElapsed :: void -> uint32_t
// 7: exec :: void* filehandler -> int PID // Spawns a process and returns its PID.
// 0: X
// 1: X
// 2: X
// 3: X
// 4: localalloc: LocalAlloc: Allocate under current process (in esi: size; out eax void* ptr)
// 5: localdelete: LocalDelete: Deallocate under current process (in esi: pointer)
// 6: X
// 7: fork :: char* filename esi -> int PID // Spawns a process and returns its PID.
// 8: getPID: returns the current process's PID (out eax: uint32_t)
// 9: die :: destroys the current process void -> void
// 10: read :: uint32_t count -> void* filehandler -> uint8_t* outputbuffer -> int read // Reads from a file handler in to a buffer, returns successful read
// 11: write :: uint32_t count -> void* filehandler -> uint8_t* inputbuffer -> int written // Reads from a buffer in to a file, returns successful written
// 9: getFileHandler :: char* path esi -> void* eax // Returns a file handlers for a specific file
// 10: read :: uint32_t count ebx -> void* filehandler esi -> uint8_t* outputbuffer edi -> int read // Reads from a file handler in to a buffer, returns successful read
// 11: write :: uint32_t count ebx -> void* filehandler esi -> uint8_t* inputbuffer edi -> int written // Reads from a buffer in to a file, returns successful written
// 12: bindToKeyboard :: void -> void // Binds the current process's stdout to the keyboard.
// 13: bindStdout :: int PID -> int filehandler // Returns a filehandler for a CircularRWBuffer binding stdout of another process.
// 14: bindStdin :: int PID -> int filehandler // Returns a filehandler for a CircularRWBuffer binding stdin of another process.
// 13: bindStdout :: int PID esi -> int filehandler // Returns a filehandler for a CircularRWBuffer binding stdout of another process.
// 14: bindStdin :: int PID esi -> int filehandler // Returns a filehandler for a CircularRWBuffer binding stdin of another process.
// 15: fopen :: char* path -> int filehandler // Returns a filehandler to the file.
// 16: fclose :: int filehandler -> void // Closes a file handler.
// 15: fopen :: char* path esi -> int filehandler // Returns a filehandler to the file.
// 16: fclose :: int filehandler esi -> void // Closes a file handler.
// 17: kill :: int PID -> void // Destroys a process.
// 18: sleep :: int time ms -> void // Sleeps the current process for time milliseconds.
// 19: getInitPages :: void -> uint_32 // Returns the amount of physical pages available at boot.
// 20: getRemainingPages :: void -> uint_32 // Returns the amount of physical pages remaining.
// 21: getCurrentTerminalWidth :: void -> uint32_t // Gets the width of the current terminal
// 22: getCurrentTerminalHeight :: void -> uint32_t // Gets the height of the current terminal
// 17: kill :: int PID esi -> void // Destroys a process.
// File handlers:
// 0: Stdout
@ -212,143 +185,136 @@ void syscall(frame_struct* _) {
// 2..7: Reserved
// _: General use
frame_struct* frame = &Global::currentThread->frame;
uint32_t rval = frame->eax;
uint32_t esi = frame->esi;
uint32_t edi = frame->edi;
Process* currentProc = Global::currentProc;
switch (frame->eax) {
case 0: // getDentsSize
frame->eax = Global::kernel->rootfs->getDentsSize(createPathFromString((char*)frame->ebx));
case 0:
break;
case 1: // getDents
Global::kernel->rootfs->getDents(createPathFromString((char*)frame->ebx), (FSDirectoryListing*)frame->ecx);
case 1:
break;
case 2: // exists
frame->eax = Global::kernel->rootfs->exists(createPathFromString((char*)frame->ebx));
case 2:
break;
case 3: // type
frame->eax = Global::kernel->rootfs->type(createPathFromString((char*)frame->ebx));
case 3:
break;
case 4: // malloc
frame->eax = (uint32_t)currentProc->allocate(frame->ebx);
case 4:
rval = currentProc->allocate(esi);
break;
case 5: // free
currentProc->deallocate(frame->ebx);
case 5:
currentProc->deallocate(esi);
break;
case 6: // getMillisecondsElapsed
frame->eax = Global::milliseconds_elapsed;
case 6:
break;
case 7: {// execve
case 7: {
asm("cli");
xnoe::maybe<ReadWriter*> file = Global::currentProc->getFH(frame->ebx);
if (file.is_ok()) {
Process* p = Global::kernel->createProcess(file.get(), (uint8_t**)frame->ecx, (uint8_t**)frame->edx);
// Suspend the current thread and forward the current process's stdin and stdout to the new one.
Global::currentThread->state = Suspended;
p->stdin = Global::currentProc->stdin;
p->stdout = Global::currentProc->stdout;
p->threads.start->elem->suspending = Global::currentThread->TID;
context_switch();
} else {
frame->eax = 0;
}
Process* p = Global::kernel->createProcess(esi);
rval = p->PID;
asm("sti");
break;
}
case 8: // getPID
frame->eax = currentProc->PID;
case 8:
rval = currentProc->PID;
break;
case 9: { // die
Global::kernel->PD->select();
Global::kernel->destroyProcess(Global::currentProc, frame->ebx);
Global::currentProcValid = false;
context_switch();
return;
}
case 9:
break;
case 10: { // read
xnoe::maybe<ReadWriter*> fh = Global::currentProc->getFH(frame->ecx);
case 10: {
if (esi == 1) {
ReadWriter* stdin = currentProc->stdin;
if (!stdin)
break;
rval = stdin->read(frame->ebx, edi);
} else {
xnoe::Maybe<ReadWriter*> fh = Global::FH->get(esi);
if (!fh.is_ok()) {
frame->eax = 0;
rval = 0;
break;
}
ReadWriter* rw = fh.get();
frame->eax = rw->read(frame->ebx, (uint8_t*)frame->edx);
rval = rw->read(frame->ebx, edi);
}
break;
}
case 11: { // write
xnoe::maybe<ReadWriter*> fh = Global::currentProc->getFH(frame->ecx);
case 11: {
if (esi == 0) {
ReadWriter* stdout = currentProc->stdout;
if (!stdout)
break;
rval = stdout->write(frame->ebx, edi);
} else {
xnoe::Maybe<ReadWriter*> fh = Global::FH->get(esi);
if (!fh.is_ok()) {
frame->eax = 0;
rval = 0;
break;
}
ReadWriter* rw = fh.get();
frame->eax = rw->write(frame->ebx, (uint8_t*)frame->edx);
rval = rw->write(frame->ebx, edi);
}
break;
}
case 12: // bindToKeyboard
case 12:
if (currentProc->stdin)
currentProc->stdin->close();
break;
currentProc->stdin = new CircularRWBuffer();
currentProc->stdin = new CircularRWBuffer(currentProc->PID, 0);
Global::kernel->KBListeners.append(currentProc);
break;
case 13: { // bindStdout
xnoe::maybe<Process*> pm = Global::kernel->pid_map->get(frame->ebx);
case 13: {
xnoe::Maybe<Process*> pm = Global::kernel->pid_map->get(esi);
if (!pm.is_ok())
break;
Process* p = pm.get();
//if (!p->stdout) {
//ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, frame->ebx);
//p->stdout = buffer;
p->stdout->open();
frame->eax = Global::currentProc->mapFH(p->stdout);
//}
if (!p->stdout) {
ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, esi);
p->stdout = buffer;
rval = Global::kernel->mapFH(buffer);
}
break;
}
case 14: { // bindStdin
xnoe::maybe<Process*> pm = Global::kernel->pid_map->get(frame->ebx);
case 14: {
xnoe::Maybe<Process*> pm = Global::kernel->pid_map->get(esi);
if (!pm.is_ok())
break;
Process* p = pm.get();
//if (!p->stdin) {
//ReadWriter* buffer = new CircularRWBuffer(frame->ebx, currentProc->PID);
//p->stdin = buffer;
p->stdin->open();
frame->eax = Global::currentProc->mapFH(p->stdin);
//}
if (!p->stdin) {
ReadWriter* buffer = new CircularRWBuffer(esi, currentProc->PID);
p->stdin = buffer;
rval = Global::kernel->mapFH(buffer);
}
break;
}
case 15: { // fopen
ReadWriter* file = Global::kernel->rootfs->open(createPathFromString((char*)frame->ebx));
if (file)
frame->eax = Global::currentProc->mapFH(file);
case 15: {
ReadWriter* file = new FATFileReadWriter(0, esi);
rval = Global::kernel->mapFH(file);
break;
}
case 16: { // fclose
xnoe::maybe<ReadWriter*> f = Global::currentProc->getFH(frame->ebx);
case 16: {
xnoe::Maybe<ReadWriter*> f = Global::FH->get(esi);
if (f.is_ok()) {
f.get()->close();
Global::currentProc->unmapFH(frame->ebx);
delete f.get();
Global::kernel->unmapFH(esi);
}
break;
}
case 17: { // kill
case 17: {
asm("cli");
xnoe::maybe<Process*> p = Global::kernel->pid_map->get(frame->ebx);
xnoe::Maybe<Process*> p = Global::kernel->pid_map->get(esi);
if (p.is_ok()) {
Process* proc = p.get();
Global::kernel->destroyProcess(proc);
@ -357,118 +323,11 @@ void syscall(frame_struct* _) {
break;
}
case 18: { // sleep
Global::currentThread->state = Suspended;
Timer::register_event(frame->ebx, (void(*)(void*))&awaken, (void*)Global::currentThread, true);
context_switch();
break;
}
case 19: // getRemainingPages
frame->eax = Global::kernel->phys->remainingPages;
break;
case 20: // getInitPages
frame->eax = Global::kernel->phys->initPages;
break;
case 21: // getTerminalWidth
frame->eax = Global::kernel->terminal->width;
break;
case 22: // getTerminalHeight
frame->eax = Global::kernel->terminal->height;
break;
case 23: { // getProcessState
xnoe::maybe<Process*> p = Global::kernel->pid_map->get(frame->ebx);
if (p.is_ok()) {
Process* proc = p.get();
//frame->eax = proc->state;
}
break;
}
case 25: { // fork
Process* p = new Process(Global::currentProc);
Thread* t = new Thread(Global::currentThread, p);
t->parent = p;
p->threads.append(t);
Global::kernel->registerThread(t);
Global::kernel->registerProcess(p);
frame->eax = p->PID;
t->frame.eax = 0;
break;
}
case 24: { // spawnThread
Thread* thread = new Thread(Global::currentProc);
thread->initKernelStack((void*)frame->ebx, thread->stack);
Global::kernel->registerThread(thread);
break;
}
case 26: {// programRunning
xnoe::maybe<Process*> p = Global::kernel->pid_map->get(frame->ebx);
frame->eax = p.is_ok();
break;
}
default:
break;
}
}
void v86_monitor(v8086_frame_struct* frame) {
uint8_t* ip = (uint8_t*)((frame->cs<<4) + frame->eip);
uint16_t* sp = (uint16_t*)frame->esp;
uint16_t flags = (uint16_t)frame->eflags;
switch (*ip) {
case 0x9c:
*(--sp) = (uint16_t)frame->eflags;
frame->eip++;
break;
case 0x9d:
frame->eflags &= 0xffff0000;
frame->eflags |= *(sp++);
frame->eip++;
break;
case 0xcd: {
// Handle int
if (!ip[1]) {
asm("mov %0, %%esp"::"a"(Global::resp));
asm("popa");
asm("ret");
}
uint32_t vector_data = *(uint32_t*)(ip[1]<<2);
*(--sp) = flags;
frame->eflags &= ~(0x00040300);
*(--sp) = (uint16_t)frame->cs;
*(--sp) = (uint16_t)(frame->eip);
uint16_t* vector = (uint16_t*)&vector_data;
frame->cs = vector[1];
frame->eip = (uint32_t)vector[0];
break;
}
case 0xcf: {
// Handle iret
frame->eip = *(sp++) + 2;
frame->cs = *(sp++);
frame->eflags &= 0xffff0000;
frame->eflags |= *(sp++);
break;
}
case 0xfa:
asm("cli");
frame->eip++;
break;
case 0xfb:
asm("sti");
frame->eip++;
break;
default: {
break;
}
}
frame->esp = (uint16_t)sp;
frame->eax = rval;
}
void init_idt() {
@ -481,6 +340,7 @@ void init_idt() {
for (int i=0; i<256; i++)
gates[i] = &ignore_interrupt;
gates[32] = &Timer::tick;
gates[0] = &handle_fault;
gates[5] = &handle_fault;
gates[6] = &handle_fault;
@ -500,9 +360,9 @@ void init_idt() {
gates[29] = &handle_fault;
gates[30] = &handle_fault;
gates[31] = &handle_fault;
gates[128] = &syscall;
gates[127] = &syscall;
idt[128].privilege = 3;
idt[127].privilege = 3;
outb(0x20, 0x11);
outb(0xA0, 0x11);
@ -521,10 +381,9 @@ void init_idt() {
outb(0x40, _counter[0]);
outb(0x40, _counter[1]);
Timer::register_event(30, (void(*)(void*))&context_switch, 0);
Timer::register_event(30, &context_switch, 0);
}
void enable_idt() {
gates[32] = &Timer::tick;
asm ("sti");
}

View File

@ -2,12 +2,13 @@
#define IDT_H
#include "types.h"
#include "screenstuff.h"
#include "global.h"
#include "kernel.h"
#include "gdt.h"
#include "stdio/circularrwbuffer.h"
struct __attribute__((packed)) v8086_frame_struct {
struct __attribute__((packed)) frame_struct {
uint32_t new_cr3;
uint32_t new_esp;
@ -28,17 +29,9 @@ struct __attribute__((packed)) v8086_frame_struct {
uint16_t cs;
uint16_t _ignored0;
uint32_t eflags;
uint32_t esp;
uint16_t ss;
uint16_t _ignored1;
uint16_t es;
uint16_t _ignored2;
uint16_t ds;
uint16_t _ignored3;
uint16_t fs;
uint16_t _ignored4;
uint16_t gs;
uint16_t _ignored5;
uint32_t esp;
};
extern void(*gates[256])(frame_struct*);
@ -64,10 +57,4 @@ struct __attribute__((packed)) idt_desc {
uint32_t offset;
};
void context_switch();
void handle_fault(frame_struct* frame);
void syscall();
void ignore_interrupt();
void v86_monitor(v8086_frame_struct* frame);
#endif

View File

@ -19,21 +19,3 @@ extern "C" {
return result;
}
}
Port::Port(uint16_t a) {
this->addr = a;
}
uint8_t Port::readb() {
return inb(this->addr);
}
uint16_t Port::readw() {
return inw(this->addr);
}
void Port::writeb(uint8_t d) {
outb(this->addr, d);
}
void Port::writew(uint16_t d) {
outw(this->addr, d);
}

View File

@ -11,17 +11,4 @@ extern "C" {
uint16_t inw(uint16_t portnumber);
}
class Port {
private:
uint16_t addr;
public:
Port(uint16_t a);
uint8_t readb();
uint16_t readw();
void writeb(uint8_t d);
void writew(uint16_t d);
};
#endif

View File

@ -6,72 +6,64 @@ global catchall_return
catchall: ; At this point the gate number has been pushed to the stack
pushad
mov eax, cr3
push esp
sub esp, 4
push eax
push 0
mov eax, cr3
mov [esp+4], eax
pop eax
; Pushed 40 bytes
mov eax, [esp+40]
mov ebx, gates
mov eax, [ebx+4*eax]
; Check if we came from Ring 3
movzx ecx, word [esp+56]
and ecx, 3
cmp ecx, 3
jne no_copy
mov ecx, 72
mov esi, esp
mov edi, [_ZN6Global13currentThreadE]
rep movsb
mov ecx, [_ZN6Global13currentThreadE]
push ecx
jmp call
no_copy:
push esp
jmp call
call:
; Increment the current thread's count
mov ecx, [_ZN6Global13currentThreadE]
mov edx, [ecx]
add edx, 1
mov [ecx], edx
call eax
catchall_return:
add esp, 4
push 0x20
push 0x20
call outb
add esp, 8
; Decrement and check the current thread's count
mov ecx, [_ZN6Global13currentThreadE]
mov edx, [ecx]
sub edx, 1
mov [ecx], edx
cmp edx, 0
jne skip_copying
sub esp, 72
mov ecx, 72
mov esi, [_ZN6Global13currentThreadE]
mov edi, esp
rep movsb
skip_copying:
add esp, 4
pop eax
push eax
mov eax, [esp+4]
mov cr3, eax
pop eax
add esp, 4
pop esp
popad
add esp, 8
mov esp, ebp
pop ebp
iret
extern gates ; (void(*)(frame_struct))*
extern outb
extern _ZN6Global13currentThreadE
; struct frame_struct __attribute__((packed)) {
; popad
; uint32_t edi;
; uint32_t esi;
; uint32_t ebp;
; uint32_t esp;
; uint32_t ebx;
; uint32_t edx;
; uint32_t ecx;
; uint32_t eax;
;
; interrupt
; uint32_t eip;
; uint32_t cs;
; uint32_t eflags;
; uint32_t esp;
; uint32_t ss;
;
; if it's an error
; uint32_t err_code;
; }

View File

@ -1,185 +1,60 @@
#include "kernel.h"
Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base, uint32_t stack)
: Process(0x8a000, page_directory, phys, virt, virt_alloc_base)
: Process(0, 0x8a000, page_directory, phys, virt, virt_alloc_base)
{
this->currentPID = 1;
Global::allocator = this;
Global::kernel = this;
Global::currentProc = this;
Global::currentProc = 0;
this->stack = stack;
this->lastFH = 8;
//this->processes.append(this);
}
void Kernel::init_kernel() {
this->pid_map = new xnoe::hashtable<uint32_t, Process*>();
this->tid_map = new xnoe::hashtable<uint32_t, Thread*>();
Global::FH = new xnoe::hashtable<void*, ReadWriter*>();
this->globalISRStack = (new uint8_t[0x8000]) + 0x8000;
Global::currentThread = new Thread(this);
Global::currentThread->frame.count++;
}
Process* Kernel::createProcess(ReadWriter* file, uint8_t** argv, uint8_t** envp) {
// argv is currently stored on the stack of the calling process
// We need to create a copy of it in the kernel stack for createProcess
Process* Kernel::createProcess(uint32_t fh) {
Process* p = new Process(currentPID, this->PD, 0xc0000000, fh);
this->pid_map->set(currentPID, p);
currentPID++;
// Determine the length of argv (null terminated)
uint32_t argc = 0;
for (int i=0; argv[i]; i++)
argc++;
// Determine the length of all stings under argv
uint32_t argv_strings_length = 0;
for (int i=0; i<argc; i++)
argv_strings_length += strlen(argv[i]);
// Allocate space for the strings + new argv
char argv_strings[argv_strings_length];
char* argv_new[argc];
// Copy the strings, fill argv_new
for (int i=0, string_index=0; argv[i]; string_index+=strlen(argv[i++])) {
memcpy(&argv_strings[string_index], argv[i], strlen(argv[i]));
argv_new[i] = &argv_strings[string_index];
}
// envp is currently stored on the stack of the calling process
// We need to create a copy of it in the kernel stack for createProcess
// Determine the length of envp (null terminated)
uint32_t envc = 0;
if (envp)
for (int i=0; envp[i]; i++)
envc++;
// Determine the length of all stings under envp
uint32_t envp_strings_length = 0;
for (int i=0; i<envc; i++)
envp_strings_length += strlen(envp[i]);
// Allocate space for the strings + new envp
char envp_strings[envp_strings_length];
char* envp_new[envc];
// Copy the strings, fill envp_new
if (envc) {
for (int i=0, string_index=0; envp[i]; string_index+=strlen(envp[i++])) {
memcpy(&envp_strings[string_index], envp[i], strlen(envp[i]));
envp_new[i] = &envp_strings[string_index];
}
}
Process* p = new Process(this->PD, 0xc0000000, file, argc, argv_new, envc, envp_new);
this->pid_map->set(p->PID, p);
registerThread(p->threads.start->elem);
this->processes.append(p);
return p;
}
Process* Kernel::createProcess(ReadWriter* file, uint8_t** argv, ReadWriter* stdout) {
char* zero = 0;
Process* p = this->createProcess(file, argv, &zero);
Process* Kernel::createProcess(uint32_t fh, ReadWriter* stdout) {
Process* p = this->createProcess(fh);
p->stdout = stdout;
return p;
}
void Kernel::registerProcess(Process* p) {
this->pid_map->set(p->PID, p);
}
void Kernel::destroyProcess(Process* p, uint32_t exit_code) {
xnoe::linkedlistelem<Thread*>* currentThread = p->threads.start;
while (currentThread) {
destroyThread(currentThread->elem, exit_code);
currentThread = currentThread->next;
}
void Kernel::destroyProcess(Process* p) {
if (Global::currentProc == p)
Global::currentProcValid = false;
this->processes.remove(p);
this->pid_map->remove(p->PID);
delete p;
}
void Kernel::registerThread(Thread* t) {
this->threads.append(t);
this->tid_map->set(t->TID, t);
int Kernel::mapFH(ReadWriter* fh) {
Global::FH->set(this->lastFH++, fh);
return this->lastFH - 1;
}
void Kernel::destroyThread(Thread* t, uint32_t exit_code) {
this->tid_map->remove(t->TID);
t->parent->threads.remove(t);
this->threads.remove(t);
if (t->suspending) {
xnoe::maybe<Thread*> ts = this->tid_map->get(t->suspending);
if (ts.is_ok()) {
Thread* st = ts.get();
st->state = Running;
st->frame.eax = exit_code;
}
}
delete t;
void Kernel::unmapFH(uint32_t fh) {
Global::FH->remove((void*)fh);
}
void Kernel::v86(uint16_t ax, uint16_t bx, uint16_t cx, uint16_t es, uint16_t di, uint8_t intn) {
// Create the payload to perform an interrupt.
uint8_t payload[21] = {
0xb8, 0x00, 0x00, // mov ax, 0
0x8e, 0xc0, // mov es, ax
0xb8, 0x00, 0x00, // mov ax, 0
0xbb, 0x00, 0x00, // mov bx, 0
0xb9, 0x00, 0x00, // mov cx, 0
0xbf, 0x00, 0x00, // mov di, 0
0xcd, 0x00, // int 0
0xcd, 0x00 // int 0
};
// Set the values in the payload.
uint16_t* ax1 = (uint16_t*)(payload+1);
uint16_t* ax2 = (uint16_t*)(payload+6);
uint16_t* bx1 = (uint16_t*)(payload+9);
uint16_t* cx1 = (uint16_t*)(payload+12);
uint16_t* di1 = (uint16_t*)(payload+15);
uint8_t* intn1 = (uint8_t*)(payload+18);
*ax1 = es;
*ax2 = ax;
*bx1 = bx;
*cx1 = cx;
*di1 = di;
*intn1 = intn;
// Construct a stack.
uint32_t* stack = 0x9000;
*(--stack) = 0; // GS
*(--stack) = 0; // FS
*(--stack) = 0; // DS
*(--stack) = 0; // ES
*(--stack) = 0; // SS
*(--stack) = 0x9000; // ESP
*(--stack) = 0x00020000; // EFLAGS
*(--stack) = 0; // CS
*(--stack) = 0x7c00; // EIP
// Copy 19 bytes from payload to 0x7c00
memcpy((uint8_t*)0x7c00, payload, 21);
asm("lea _after_iret, %eax");
asm("push %eax");
asm("pusha");
asm("mov %%esp, %0":"=m"(Global::resp)::);
asm("xor %eax, %eax; xor %ebx, %ebx; xor %ecx, %ecx; xor %edi, %edi");
asm("mov %0, %%esp"::"m"(stack):);
asm("iret");
asm("_after_iret:");
}
//void Kernel::loadPrimaryStack() {
// asm volatile("mov %0, %%esp"::"m"(this->stack - 64));
//}

View File

@ -5,38 +5,32 @@
#include "datatypes/hashtable.h"
#include "global.h"
#include "terminal.h"
#include "filesystem/fstree.h"
#include "gdt.h"
class Kernel : public Process {
private:
int lastFH;
public:
uint32_t currentPID;
uint32_t stack;
uint32_t globalISRStack;
Terminal* terminal;
xnoe::hashtable<uint32_t, Process*>* pid_map; // Map of PIDs -> Process*s
xnoe::hashtable<uint32_t, Thread*>* tid_map; // Map of TIDs -> Thread*s
xnoe::linkedlist<Process*> processes;
xnoe::linkedlist<Process*> KBListeners;
RootFSTree* rootfs;
Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base, uint32_t stack);
void init_kernel();
Process* createProcess(ReadWriter* file, uint8_t** argv, uint8_t** envp);
Process* createProcess(ReadWriter* file, uint8_t** argv, ReadWriter* stdout);
void registerProcess(Process* p);
void destroyProcess(Process* p, uint32_t exit_code=0);
Process* createProcess(uint32_t fh);
Process* createProcess(uint32_t fh, ReadWriter* stdout);
void destroyProcess(Process* p);
void registerThread(Thread* t);
void destroyThread(Thread* t, uint32_t exit_code=0);
void v86(uint16_t ax, uint16_t bx, uint16_t cx, uint16_t es, uint16_t di, uint8_t intn);
int mapFH(ReadWriter* fh);
void unmapFH(uint32_t fh);
//void loadPrimaryStack();
};
#endif

View File

@ -3,6 +3,7 @@
#include <stdbool.h>
#include "io.h"
#include "screenstuff.h"
#include "idt.h"
void init_keyboard();

View File

@ -1,9 +1,10 @@
#include "types.h"
#include "screenstuff.h"
#include "io.h"
#include "idt.h"
#include "keyboard.h"
#include "strings.h"
#include "ata.h"
#include "atapio.h"
#include "gdt.h"
#include "paging.h"
#include "allocate.h"
@ -13,36 +14,24 @@
#include "datatypes/hashtable.h"
#include "terminal.h"
#include "kernel.h"
#include "filesystem/fstree.h"
#include "filesystem/fat16.h"
#include "filesystem/devfs.h"
#include "filesystem/sysfs.h"
struct KernelInformationStruct {
PDE* pde;
uint32_t page_directory_phys_addr;
uint32_t page_directory_phys_offset;
uint32_t page_bitmap_phys;
uint32_t page_bitmap_virt;
uint32_t stack_ptr;
uint32_t vga_addr;
uint32_t remainingPages;
};
int main(KernelInformationStruct kstruct) {
int main() {
init_gdt();
init_term();
PageDirectory kernel_pd = PageDirectory(kstruct.pde, kstruct.page_directory_phys_addr, kstruct.page_directory_phys_offset);
PageDirectory kernel_pd = PageDirectory(0xc0100000, 0x120000, 0xbffe0000);
kernel_pd.select();
kernel_pd.unmap(0x8000);
PageMap phys_pm(kstruct.page_bitmap_phys, kstruct.remainingPages);
PageMap virt_pm(kstruct.page_bitmap_virt);
PageMap phys_pm(0xc0600000);
PageMap virt_pm(0xc0620000);
Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, kstruct.stack_ptr);
Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, 0xc1006000);
kernel.init_kernel();
init_atapio();
VGAModeTerminal* term = new VGAModeTerminal(kstruct.vga_addr);
VGAModeTerminal* term = new VGAModeTerminal(0xc07a0000);
kernel.terminal = term;
@ -51,31 +40,17 @@ int main(KernelInformationStruct kstruct) {
term->activate();
term->clear_screen();
/*kernel.v86(
0x4F00,
0,
0,
0,
0,
0x10
);*/
term->printf("Hello, World!\n\nWe are running XnoeOS Code in C++ now, Protected Mode has been achieved (as well as Virtual Memory / Paging!!!) and everything is working super nicely!\n\nHow wonderful!\n\nNow I just need to hope my print function works properly too~~\n");
term->printf("KERNEL OK!\n");
kernel.rootfs = new RootFSTree();
kernel.rootfs->mount(createPathFromString("/dev"), new DevFS());
kernel.rootfs->mount(createPathFromString("/sys"), new SysFS());
kernel.rootfs->mount(createPathFromString("/"), new FAT16FS(kernel.rootfs->open(createPathFromString("/dev/ata"))));
ReadWriter* init = kernel.rootfs->open(createPathFromString("/init.bin"));
ReadWriter* worldbin = new FATFileReadWriter(0, "etc/world.bin");
uint32_t fh = kernel.mapFH(worldbin);
char* zero = 0;
Process* p1 = kernel.createProcess(init, &zero, term);
Global::tss->esp0 = (new uint8_t[8192]) + 8192;
Process* p1 = kernel.createProcess(fh, term);
init_keyboard();
enable_idt();
while (1) asm ("hlt");

View File

@ -5,14 +5,13 @@ void memset(uint8_t* address, uint32_t count, uint8_t value) {
address[i] = value;
}
void memcpy(uint8_t* dst, uint8_t* src, uint32_t count) {
void memcpy(uint8_t* src, uint8_t* dst, uint32_t count) {
for (int i = 0; i<count; i++)
dst[i] = src[i];
}
PageMap::PageMap(uint32_t map, uint32_t remainingPages) {
PageMap::PageMap(uint32_t map) {
this->pagemap = (uint8_t*)map;
this->initPages = this->remainingPages = remainingPages;
}
PageMap::PageMap() {
@ -39,8 +38,6 @@ void PageMap::unset_bit(uint32_t index) {
}
bool PageMap::bit_set(uint32_t index) {
if (!index)
return false;
uint32_t offset = index % 8;
uint32_t i = index / 8;
@ -49,24 +46,20 @@ bool PageMap::bit_set(uint32_t index) {
void PageMap::mark_unavailable(uint32_t address) {
unset_bit(address >> 12);
this->remainingPages--;
}
void PageMap::mark_unavailable(uint32_t address, uint32_t count) {
for (int i=0; i<count; i++)
unset_bit((address >> 12) + i);
this->remainingPages -= count;
}
void PageMap::mark_available(uint32_t address) {
set_bit(address >> 12);
this->remainingPages++;
}
void PageMap::mark_available(uint32_t address, uint32_t count) {
for (int i=0; i<count; i++)
set_bit((address >> 12) + i);
this->remainingPages += count;
}
bool PageMap::available(uint32_t address) {
@ -98,7 +91,6 @@ PageTable::PageTable(uint32_t phys, uint32_t virt) {
virt_addr = virt;
page_table = (PTE*)virt;
valid = 1;
}
PageTable::PageTable(){
@ -108,7 +100,6 @@ PageTable::PageTable(){
phys_addr = (Global::allocator->virtual_to_physical(virt_addr)) >> 12;
page_table = (PTE*)virt_addr;
valid = 1;
}
PageTable::~PageTable() {
@ -158,7 +149,7 @@ PageDirectory::PageDirectory(PDE* page_directory, uint32_t phys_addr, uint32_t o
for (int i=0; i<1024; i++) {
uint32_t table_phys_addr = page_directory[i].getPhysicalPTAddress();
new (&page_tables[i]) PageTable(table_phys_addr >> 12, table_phys_addr + offset);
new (page_tables + i) PageTable(table_phys_addr >> 12, table_phys_addr + offset);
}
}
@ -174,7 +165,7 @@ PageDirectory::PageDirectory() {
PageDirectory::~PageDirectory() {
for (int i=0; i<1024; i++)
if (page_tables[i].valid)
if (page_tables[i].virt_addr)
page_tables[i].~PageTable();
delete page_directory;
}
@ -182,8 +173,8 @@ PageDirectory::~PageDirectory() {
void PageDirectory::map(uint32_t phys, uint32_t virt, uint8_t privilege) {
split_addr* split = (split_addr*)&virt;
if (!page_tables[split->pd_index].valid)
new (&page_tables[split->pd_index]) PageTable();
if (!page_tables[split->pd_index].virt_addr)
new (page_tables + split->pd_index) PageTable();
page_directory[split->pd_index] = (PDE){
.present = 1,

View File

@ -3,12 +3,13 @@
#include "paging.h"
#include "allocate.h"
#include "screenstuff.h"
#include "global.h"
void memset(uint8_t* address, uint32_t count, uint8_t value);
void memcpy(uint8_t* dst, uint8_t* src, uint32_t count);
void memcpy(uint8_t* src, uint8_t* dst, uint32_t count);
class PageMap {
class __attribute__((packed)) PageMap {
private:
uint8_t* pagemap;
@ -18,10 +19,7 @@ private:
bool bit_set(uint32_t index);
public:
uint32_t remainingPages;
uint32_t initPages;
PageMap(uint32_t map, uint32_t remainingPages=0x100000);
PageMap(uint32_t map);
PageMap();
~PageMap();
@ -43,8 +41,6 @@ struct PageTable {
uint32_t phys_addr;
uint32_t virt_addr;
uint32_t valid = 0;
uint32_t reserved;
PageTable(uint32_t phys, uint32_t virt);
PageTable();
@ -82,12 +78,12 @@ public:
class Allocator {
protected:
uint32_t virt_alloc_base;
uint8_t privilege;
public:
static PageMap* phys;
PageMap* virt;
uint32_t virt_alloc_base;
uint8_t privilege;
public:
PageDirectory* PD;
Allocator(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
@ -98,8 +94,6 @@ public:
virtual void* allocate(uint32_t size);
virtual void deallocate(uint32_t virt_addr);
void* getMappingOf(uint32_t phys_addr, uint32_t length_pages);
uint32_t virtual_to_physical(uint32_t virt);
};

View File

@ -1,6 +1,7 @@
#ifndef PAGING_H
#define PAGING_H
#include <stdbool.h>
#include "types.h"
struct __attribute__((packed)) split_addr {

View File

@ -3,214 +3,90 @@
extern void(*catchall_return)();
AllocTracker::AllocTracker(void* base, uint32_t size, uint32_t count) : page_base(base), page_size(size), alloc_count(count) {}
AllocTracker::AllocTracker() {}
xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*> Process::get_alloc_tracker(uint32_t address) {
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> Process::get_alloc_tracker(uint32_t address) {
xnoe::linkedlistelem<AllocTracker>* current = this->allocations.start;
while (current) {
if (current->elem.page_base <= address && (current->elem.page_base + 4096 * current->elem.page_size) > address) {
return xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*>(current);
return xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*>(current);
}
current = current->next;
}
return xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*>();
return xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*>();
}
uint32_t Process::currentPID = 0;
Process::Process(void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base)
Process::Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base)
: Allocator(page_directory, phys, virt, virt_alloc_base) {
this->PID = this->currentPID++;
this->PID = PID;
this->page_remaining = 0;
this->last_page_pointer = virt_alloc_base;
this->stack = stack;
}
Process::Process()
Process::Process(uint32_t PID)
: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) {
this->PID = 0;
this->PID = PID;
this->page_remaining = 0;
this->last_page_pointer = 0;
this->file_handlers = new xnoe::dynarray<ReadWriter*>(8);
this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x1000]) + 0x1000;
}
Process::Process(PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc, char** argv, uint32_t envc, char** envp)
Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uint32_t fh)
: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) {
this->stdout = 0;
this->stdin = 0;
this->PID = this->currentPID++;
this->firstRun = true;
this->PID = PID;
this->page_remaining = 0;
this->last_page_pointer = 0;
this->file_handlers = new xnoe::dynarray<ReadWriter*>(8);
for (int index = inheritBase >> 22; index < 1024; index++)
this->PD->page_directory[index] = inherit->page_directory[index];
xnoe::Maybe<ReadWriter*> file = Global::FH->get(fh);
if (file.is_ok()) {
ReadWriter* filereader = file.get();
uint32_t filesize = filereader->size();
uint8_t* program_data = this->allocate(filesize + 12) + 12;
Thread* thread = new Thread(this);
this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x1000]) + 0xffc;
this->kernelStackPtrDefault = this->kernelStackPtr;
uint32_t pCR3;
asm ("mov %%cr3, %0" : "=a" (pCR3) :);
this->PD->select();
uint32_t* stack = thread->stack + 0x8000;
uint8_t* argenvarea = this->allocate(0x2000) + 0x2000;
// Copy envp
// envp is null terminated
*(--stack) = 0;
for (int i=envc; i>0; i--) {
char* s = envp[i-1];
uint32_t c = strlen(s);
memcpy((uint8_t*)(argenvarea -= c), (uint8_t*)envp[i-1], c);
*(--stack) = argenvarea;
}
uint32_t envp_p = ((uint32_t)stack);
// Copy argv
for (int i=argc; i>0; i--) {
char* s = argv[i-1];
uint32_t c = strlen(s);
memcpy((uint8_t*)(argenvarea -= c), (uint8_t*)argv[i-1], c);
*(--stack) = argenvarea;
}
uint32_t argv_p = ((uint32_t)stack);
*(--stack) = envp_p;
*(--stack) = argv_p;
*(--stack) = argc;
filereader->seek(0);
filereader->read(filesize, program_data);
asm ("mov %0, %%cr3" : : "r" (pCR3));
thread->initKernelStack(program_data, stack);
this->threads.append(thread);
}
Process::Process(Process* p)
: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) {
// Clone a Process and produce an entirely new process.
this->file_handlers = new xnoe::dynarray<ReadWriter*>(p->file_handlers);
this->PID = this->currentPID++;
// Set up page directory.
for (int index = 0xc0000000 >> 22; index < 1024; index++)
this->PD->page_directory[index] = p->PD->page_directory[index];
// First, we need to switch in to p's memory space
uint32_t pCR3;
asm("mov %%cr3, %0":"=a"(pCR3)::);
p->PD->select();
// First, we need to copy all of p's allocations.
xnoe::linkedlist<xnoe::tuple<AllocTracker, void*>> allocations;
xnoe::linkedlistelem<AllocTracker>* current_old = p->allocations.start;
while (current_old) {
allocations.append(xnoe::tuple<AllocTracker, void*>(current_old->elem, new uint8_t[4096 * current_old->elem.page_size]));
void* location = xnoe::get<1>(allocations.end->elem);
memcpy((uint8_t*)location, (uint8_t*)current_old->elem.page_base, 4096 * current_old->elem.page_size);
current_old = current_old->next;
}
// Select our own CR3
this->PD->select();
// Go through every allocation from the old process, allocate it here, copy the data over, then free the buffer we created.
xnoe::linkedlistelem<xnoe::tuple<AllocTracker, void*>>* current_new = allocations.start;
while (current_new) {
AllocTracker at = xnoe::get<0>(current_new->elem);
uint8_t* buf = (uint8_t*)xnoe::get<1>(current_new->elem);
uint8_t* dbuf = (uint8_t*)this->allocate((at.page_size-1) * 4096, at.alloc_count);
memcpy(dbuf, buf + 0x14, at.page_size * 4096 - 0x14);
delete buf;
current_new = current_new->next;
}
// Restore CR3
asm("mov %0, %%cr3"::"r"(pCR3):);
// Setting up threads, etc will be left to the caller.
this->stdin = p->stdin;
this->stdout = p->stdout;
}
uint32_t Thread::currentTID = 1;
Thread::Thread(Process* parent) {
this->TID = this->currentTID++;
this->parent = parent;
this->stack = this->parent->allocate(0x8000);
this->kspRaw = (new uint8_t[0x4000]);
this->kernelStackPtr = this->kspRaw + 0x4000;
this->kernelStackPtrDefault = this->kernelStackPtr;
}
Thread::Thread(Thread* t, Process* parent) {
this->TID = this->currentTID++;
this->stack = t->stack;
uint8_t* s = new uint8_t[0x8000];
// Copy the kernel stack
this->kspRaw = (new uint8_t[0x4000]);
memcpy(this->kspRaw, t->kspRaw, 0x4000);
memcpy((uint8_t*)&this->frame, (uint8_t*)&t->frame, sizeof(frame_struct));
this->frame.new_cr3 = parent->PD->phys_addr;
this->kernelStackPtr = this->kspRaw + 0x4000;
this->kernelStackPtrDefault = this->kernelStackPtr;
this->frame.ebp = this->kernelStackPtr;
this->frame.oesp = this->kernelStackPtr;
}
Thread::~Thread() {
//delete kernelStackPtr;
}
void Thread::initKernelStack(void* entryPoint, void* esp) {
uint32_t pCR3;
asm ("mov %%cr3, %0" : "=a" (pCR3) :);
this->parent->PD->select();
// We also need to initialise ESP and the stack
uint32_t* stack32 = ((uint32_t)this->kernelStackPtr);
*(--stack32) = 0x23; // SS
*(--stack32) = ((uint32_t)esp); // ESP
*(--stack32) = ((uint32_t)this->stack + 0x8000); // ESP
*(--stack32) = 0x200; // EFLAGS
*(--stack32) = 27; // CS
*(--stack32) = (uint32_t)entryPoint; // EIP
*(--stack32);
*(--stack32);
*(--stack32);
*(--stack32) = (uint32_t)program_data; // EIP
*(--stack32) = ((uint32_t)this->stack + 0x8000); // EBP
uint32_t rEBP = stack32;
*(--stack32) = 0; // EAX
*(--stack32) = 0; // ECX
*(--stack32) = 0; // EDX
*(--stack32) = 0; // EBX
*(--stack32) = 0; // ESP
*(--stack32) = 0; // EBP
*(--stack32) = rEBP; // EBP
*(--stack32) = 0; // ESI
*(--stack32) = 0; // EDI
*(--stack32) = 0; // CR3
*(--stack32) = 1;
memcpy((uint8_t*)&this->frame, (uint8_t*)stack32, 72);
this->kernelStackPtr = stack32;
filereader->read(filesize, program_data);
asm ("mov %0, %%cr3" : : "r" (pCR3));
}
}
Process::~Process() {
@ -222,60 +98,13 @@ Process::~Process() {
xnoe::linkedlistelem<AllocTracker>* active = next;
next = next->next;
this->deallocate(active->elem.page_base);
//printf("Deleted %x\n", active->elem.page_base);
this->deallocate(active->elem.page_base+1);
}
this->deallocate(stack);
asm ("mov %0, %%cr3" : : "r" (pCR3));
for (int i=0; i<file_handlers->length();i++) {
xnoe::maybe<ReadWriter*> r;
if ((r=file_handlers->get(i)).is_ok())
if (r.get())
r.get()->close();
}
/*xnoe::linkedlistelem<Thread*>* currentThread = threads.start;
while (currentThread) {
delete currentThread->elem;
currentThread = currentThread->next;
}*/
}
void* Process::allocate(uint32_t size, uint32_t alloc_count) {
bool switched_PD = false;
uint32_t pCR3;
asm ("mov %%cr3, %0" : "=a" (pCR3) :);
if (Global::currentProc != this) {
switched_PD = true;
this->PD->select();
}
void* ptr;
// For cloning a process, always allocate new
uint32_t elem_size = sizeof(xnoe::linkedlistelem<AllocTracker>);
// Determine how many pages we'll allocate, and the remainder
uint32_t pages = size / 4096;
uint32_t remainder = 4096 - (size % 4096);
ptr = this->Allocator::allocate(size);
// Update local values
this->last_page_pointer = ptr + pages * 4096;
this->page_remaining = remainder;
// Create allocations entry
xnoe::linkedlistelem<AllocTracker>* elem = (xnoe::linkedlistelem<AllocTracker>*)ptr;
elem->next = 0;
elem->prev = 0;
elem->elem = AllocTracker(ptr, pages + 1, alloc_count);
this->allocations.append(elem);
ptr += elem_size;
asm ("mov %0, %%cr3" : : "r" (pCR3));
return ptr;
delete kernelStackPtr;
}
void* Process::allocate(uint32_t size) {
@ -297,7 +126,7 @@ void* Process::allocate(uint32_t size) {
uint32_t elem_size = sizeof(xnoe::linkedlistelem<AllocTracker>);
size += elem_size;
// Determine how many pages we'll allocate, and the remainder
// Determine how many pages we'll allocate, and the remainder;
uint32_t pages = size / 4096;
uint32_t remainder = 4096 - (size % 4096);
@ -323,7 +152,7 @@ void* Process::allocate(uint32_t size) {
}
void Process::deallocate(uint32_t virt_addr) {
xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*> alloc_tracker = this->get_alloc_tracker(virt_addr);
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> alloc_tracker = this->get_alloc_tracker(virt_addr);
if (alloc_tracker.is_ok()) {
AllocTracker* ac = &alloc_tracker.get()->elem;
ac->alloc_count--;
@ -342,41 +171,10 @@ void Process::deallocate(uint32_t virt_addr) {
}
uint32_t Process::count_allocations(uint32_t address) {
xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*> alloc_tracker = this->get_alloc_tracker(address);
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> alloc_tracker = this->get_alloc_tracker(address);
if (alloc_tracker.is_ok())
return alloc_tracker.get()->elem.alloc_count;
else
return 0;
}
uint32_t Process::mapFH(ReadWriter* rw) {
file_handlers->push(rw);
return file_handlers->length()-1;
}
void Process::unmapFH(uint32_t file_handler) {
file_handlers->set(file_handler, 0);
}
xnoe::maybe<ReadWriter*> Process::getFH(uint32_t file_handler) {
if (file_handler == 1)
if (stdin)
return xnoe::maybe<ReadWriter*>(stdin);
else
return xnoe::maybe<ReadWriter*>();
if (file_handler == 0)
if (stdout)
return xnoe::maybe<ReadWriter*>(stdout);
else
return xnoe::maybe<ReadWriter*>();
xnoe::maybe<ReadWriter*> rw = file_handlers->get(file_handler);
if (!rw.is_ok())
return rw;
if (!rw.get())
return xnoe::maybe<ReadWriter*>();
return rw;
}

View File

@ -6,70 +6,17 @@
#include "datatypes/linkedlist.h"
#include "datatypes/hashtable.h"
#include "datatypes/maybe.h"
#include "screenstuff.h"
#include "global.h"
#include "processstate.h"
#include "atapio.h"
#include "stdio/readwriter.h"
#include "datatypes/dynarray.h"
#include "filesystem/fstree.h"
#include "stdio/circularrwbuffer.h"
struct __attribute__((packed)) frame_struct {
uint32_t count;
uint32_t new_cr3;
uint32_t edi;
uint32_t esi;
uint32_t ebp;
uint32_t oesp;
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
uint32_t eax;
uint32_t gate;
uint32_t __ignored2;
uint32_t errcode;
uint32_t eip;
uint16_t cs;
uint16_t _ignored0;
uint32_t eflags;
uint32_t esp;
uint16_t ss;
uint16_t _ignored1;
};
class Process;
class Thread {
private:
static uint32_t currentTID;
public:
frame_struct frame;
uint32_t TID;
void* stack;
void* kspRaw;
void* kernelStackPtr;
void* kernelStackPtrDefault;
Process* parent;
ProcessState state;
bool firstRun;
uint32_t suspending=0;
Thread(Process* parent);
Thread(Thread* t, Process* parent);
~Thread();
void Thread::initKernelStack(void* entryPoint, void* esp);
};
struct AllocTracker {
void* page_base;
uint32_t page_size;
uint32_t alloc_count;
AllocTracker();
AllocTracker(void* base, uint32_t size, uint32_t count);
};
@ -78,43 +25,35 @@ private:
uint32_t last_page_pointer;
uint32_t page_remaining;
xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*> get_alloc_tracker(uint32_t address);
Path currentWorkingDirectory;
static uint32_t currentPID;
public:
xnoe::dynarray<ReadWriter*>* file_handlers;
uint32_t PID;
uint32_t esp;
ReadWriter* stdout;
ReadWriter* stdin;
xnoe::linkedlist<Thread*> threads;
void* stack;
// List of pages this process has allocated
xnoe::linkedlist<AllocTracker> allocations;
Process(void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
Process();
Process(PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc=0, char** argv=0, uint32_t envc=0, char** envp=0);
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> get_alloc_tracker(uint32_t address);
Process(Process* p);
public:
uint32_t PID;
uint32_t esp;
void* kernelStackPtr;
void* kernelStackPtrDefault;
ReadWriter* stdout;
ReadWriter* stdin;
bool firstRun;
Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
Process(uint32_t PID);
Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uint32_t fh);
~Process(); // Iterate through allocations and free those; delete stack
void* allocate(uint32_t size, uint32_t alloc_count);
void* allocate(uint32_t size) override;
void deallocate(uint32_t virt_addr) override;
uint32_t count_allocations(uint32_t address);
uint32_t mapFH(ReadWriter* rw);
void unmapFH(uint32_t file_handler);
xnoe::maybe<ReadWriter*> getFH(uint32_t file_handler);
};
#endif

View File

@ -1,9 +0,0 @@
#ifndef PROCESSSTATE_H
#define PROCESSSTATE_H
enum ProcessState {
Running=0,
Suspended=1
};
#endif

133
src/kernel/screenstuff.cpp Normal file
View File

@ -0,0 +1,133 @@
#include "screenstuff.h"
uint16_t* VMEM_ADDR = (uint16_t*)0xc0501000;
const int TERM_WIDTH = 80;
const int TERM_HEIGHT = 25;
int cursor_x = 0;
int cursor_y = 0;
uint16_t get_curpos() {
uint16_t cursor_position = 0;
uint8_t* cursor_position_split = (uint8_t*)&cursor_position;
outb(0x3D4, 0x0F);
cursor_position_split[0] = inb(0x3D5);
outb(0x3D4, 0x0E);
cursor_position_split[1] = inb(0x3D5);
return cursor_position;
}
void init_term() {
uint16_t cursor_position = get_curpos();
cursor_y = cursor_position / TERM_WIDTH;
cursor_x = cursor_position % TERM_WIDTH;
}
void clear_screen() {
for (int i=0; i<TERM_WIDTH*TERM_HEIGHT; i++) {
VMEM_ADDR[i] = 0x0720;
}
}
void clear_line(int line) {
for (int x=0; x<TERM_WIDTH; x++) {
VMEM_ADDR[TERM_WIDTH*line + x] = 0x0720;
}
}
void set_curpos_raw(int curpos) {
uint8_t* cursor_position_split = (uint8_t*)&curpos;
outb(0x3D4, 0x0F);
outb(0x3D5, cursor_position_split[0]);
outb(0x3D4, 0x0E);
outb(0x3D5, cursor_position_split[1]);
cursor_x = (*(uint16_t*)cursor_position_split) % TERM_WIDTH;
cursor_y = (*(uint16_t*)cursor_position_split) / TERM_WIDTH;
}
void set_curpos(int x, int y) {
set_curpos_raw(y * TERM_WIDTH + x);
cursor_x = x;
cursor_y = y;
}
void printf(const char* string, ...) {
va_list ptr;
va_start(ptr, string);
int index = 0;
int count = 0;
char current;
while (current=string[index++]) {
count++;
if (current == '\n') {
cursor_x = 0;
cursor_y++;
}
if (cursor_x == TERM_WIDTH) {
cursor_x = 0;
cursor_y++;
}
if (cursor_y == TERM_HEIGHT) {
for (int i=1; i<TERM_HEIGHT; i++) {
for (int x=0; x<TERM_WIDTH; x++) {
int from = i * TERM_WIDTH + x;
int to = (i-1) * TERM_WIDTH + x;
VMEM_ADDR[to] = VMEM_ADDR[from];
}
}
clear_line(24);
cursor_y--;
}
if (current == '%') {
int type = string[index++];
int offset;
switch (type) {
case 'd': {
char decimal_buffer[11];
offset = int_to_decimal(va_arg(ptr, int), decimal_buffer);
printf(decimal_buffer + offset);
break;
}
case 'x': {
char hex_buffer[8];
offset = int_to_hex(va_arg(ptr, int), hex_buffer);
printf(hex_buffer);
break;
}
case 's': {
printf(va_arg(ptr, const char*));
break;
}
case 'c': {
int mem_pos = cursor_y * TERM_WIDTH + cursor_x++;
int promoted = va_arg(ptr, int);
char charred = promoted;
VMEM_ADDR[mem_pos] = charred + (0x07<<8);
break;
}
}
continue;
}
if (current != '\n') {
int mem_pos = cursor_y * TERM_WIDTH + cursor_x++;
VMEM_ADDR[mem_pos] = current + (0x07<<8);
}
}
set_curpos(cursor_x, cursor_y);
va_end(ptr);
}
void non_moving_put(char chr) {
int mem_pos = cursor_y * TERM_WIDTH + cursor_x;
VMEM_ADDR[mem_pos] = chr + (0x07<<8);
}

18
src/kernel/screenstuff.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef SCREENSTUFF_H
#define SCREENSTUFF_H
#include <stdarg.h>
#include "types.h"
#include "io.h"
#include "strings.h"
uint16_t get_curpos();
void init_term();
void clear_screen();
void clear_line(int line);
void set_curpos_raw(int curpos);
void set_curpos(int x, int y);
void printf(const char* string, ...);
void non_moving_put(char chr);
#endif

View File

@ -1,8 +0,0 @@
#include "spinlock.h"
void Spinlock::lock() {
asm volatile ("spin_lock: mov $1, %%eax; lock xchg %0, %%eax; test %%eax, %%eax; jnz spin_lock" :: "m"(locked) : "eax");
}
void Spinlock::unlock() {
asm volatile ("xor %%eax, %%eax; lock xchg %0, %%eax" :: "m"(locked) : "eax");
}

View File

@ -1,14 +0,0 @@
#ifndef SPINLOCK_H
#define SPINLOCK_H
#include "types.h"
class Spinlock {
private:
uint32_t locked = 0;
public:
void lock();
void unlock();
};
#endif

View File

@ -1,16 +1,16 @@
#include "circularrwbuffer.h"
CircularRWBuffer::CircularRWBuffer() {
CircularRWBuffer::CircularRWBuffer(uint32_t reader, uint32_t writer)
: ReadWriter(0) {
this->giveReadPerm(reader);
this->giveWritePerm(writer);
this->bufferSize = 3072;
this->buffer = new uint8_t[this->bufferSize];
this->readPtr = 0;
this->writePtr = 0;
}
CircularRWBuffer::~CircularRWBuffer() {
delete this->buffer;
}
uint32_t CircularRWBuffer::write(uint32_t count, uint8_t* buffer) {
int i=0;
while (i < count) {

View File

@ -10,8 +10,7 @@ private:
uint32_t writePtr;
uint32_t bufferSize;
public:
CircularRWBuffer();
~CircularRWBuffer();
CircularRWBuffer(uint32_t reader, uint32_t writer);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;

View File

@ -1,26 +0,0 @@
#include "oneshotreadwriter.h"
OneShotReadWriter::OneShotReadWriter(uint8_t* toRead) {
this->length = strlen(toRead);
this->buffer = new uint8_t[this->length];
memcpy(this->buffer, toRead, this->length);
}
uint32_t OneShotReadWriter::read(uint32_t count, uint8_t* buffer) {
uint32_t c=0;
while (index < length && c < count) {
buffer[c++] = this->buffer[index++];
}
return c;
}
uint32_t OneShotReadWriter::size() {
return length;
}
uint32_t OneShotReadWriter::seek(uint32_t position) {
index = clamp(0, length, position);
return index;
}

View File

@ -1,22 +0,0 @@
#ifndef ONESHOTREADWRITER_H
#define ONESHOTREADWRITER_H
#include "readwriter.h"
#include "../strings.h"
#include "../memory.h"
class OneShotReadWriter : public ReadWriter {
private:
uint8_t* buffer=0;
uint32_t length;
uint32_t index=0;
public:
OneShotReadWriter(uint8_t* toRead);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t size() override;
uint32_t seek(uint32_t position) override;
};
#endif

View File

@ -1,16 +1,37 @@
#include "readwriter.h"
uint32_t ReadWriter::read(uint32_t count, uint8_t* buffer){return;}
uint32_t ReadWriter::write(uint32_t count, uint8_t* buffer){return;}
uint32_t ReadWriter::seek(uint32_t position){return;}
uint32_t ReadWriter::size(){return;}
void ReadWriter::open() {
this->opens++;
ReadWriter::ReadWriter(uint32_t owner) {
this->owner = owner;
}
void ReadWriter::close() {
this->opens--;
if (this->opens == 0)
delete this;
void ReadWriter::giveReadPerm(uint32_t PID) {
this->allowedRead.append(PID);
}
void ReadWriter::giveWritePerm(uint32_t PID) {
this->allowedWrite.append(PID);
}
uint32_t ReadWriter::read(uint32_t count, uint8_t* buffer){}
uint32_t ReadWriter::write(uint32_t count, uint8_t* buffer){}
uint32_t ReadWriter::size(){}
bool ReadWriter::canRead(uint32_t PID) {
if (this->owner == PID)
return true;
if (this->allowedRead.has(PID))
return true;
return false;
}
bool ReadWriter::canWrite(uint32_t PID) {
if (this->owner == PID)
return true;
if (this->allowedWrite.has(PID))
return true;
return false;
}

View File

@ -6,17 +6,21 @@
class ReadWriter {
private:
uint32_t opens=1;
uint32_t owner;
xnoe::linkedlist<uint32_t> allowedRead;
xnoe::linkedlist<uint32_t> allowedWrite;
public:
ReadWriter(uint32_t owner);
void giveReadPerm(uint32_t PID);
void giveWritePerm(uint32_t PID);
virtual uint32_t read(uint32_t count, uint8_t* buffer);
virtual uint32_t write(uint32_t count, uint8_t* buffer);
virtual uint32_t size();
virtual uint32_t seek(uint32_t position);
uint32_t getOwner();
void open();
void close();
bool canRead(uint32_t PID);
bool canWrite(uint32_t PID);
};
#endif

View File

@ -1,11 +1,5 @@
#include "strings.h"
uint32_t strlen(char* s) {
uint32_t c = 0;
while (s[c++]);
return c;
}
bool strcmp(char* a, char* b, int max) {
int index = 0;
while (index < max) {

View File

@ -1,9 +1,8 @@
#ifndef STRINGS_H
#define STRINGS_H
#include "types.h"
#include <stdbool.h>
uint32_t strlen(char* s);
bool strcmp(char* a, char* b, int max);
char* split_on_first(char delimeter, char* string);
int string_split(char delimeter, char* string, char** pointer_array);

View File

@ -1,18 +1,6 @@
#include "terminal.h"
int strToInt(char* str, uint32_t max) {
int r=0;
int i=0;
while (*str >= 0x30 && *str <= 0x39 && i < max) {
r *= 10;
r += *(str++) - 0x30;
i++;
}
return r;
}
void Terminal::scroll_up(uint32_t count) {
for (int i=0; i<count; i++) {
void Terminal::scroll_up() {
// Scroll the entire buffer up.
for (int y = 0; y < (height * pages); y++) {
uint16_t* cline = buffer + y * width;
@ -24,198 +12,27 @@ void Terminal::scroll_up(uint32_t count) {
// Clear the last line
uint16_t* last_line = buffer + (height * pages - 1) * width;
for (int x = 0; x < width; x++) {
last_line[x] = 0x0720; //| (edata << 8);
last_line[x] = 0x0720;
}
this->cur_y--;
}
this->update();
}
void Terminal::scroll_down(uint32_t count) {
for (int i=0; i<count; i++) {
// Scroll the entire buffer up.
for (int y = (height * pages)-2; y >= 0; y--) {
uint16_t* nline = buffer + y * width;
uint16_t* cline = buffer + (y+1) * width;
for (int x = 0; x < width; x++) {
cline[x] = nline[x];
}
}
// Clear the last line
uint16_t* last_line = buffer + (height * (pages - 1)) * width;
for (int x = 0; x < width; x++) {
last_line[x] = 0x0720;// | (edata << 8);
}
this->cur_y--;
}
this->update();
}
void Terminal::putchar(uint8_t c) {
again:
switch (this->state) {
case None:
switch (c) {
case 0x1b:
this->state = EscapeCode;
break;
case '\n':
this->cur_x = 0;
this->cur_y++;
break;
case '\b':
if (this->cur_x == 0) {
if (this->cur_y > 0) {
this->cur_x = this->width-1;
this->cur_y--;
}
} else {
this->cur_x--;
}
last_page_pointer[this->cur_y*this->width+this->cur_x] = ' ' | (edata<<8);
if (active)
putchar_internal(this->cur_y*this->width+this->cur_x, ' ',this->edata);
break;
default:
if (this->cur_x == this->width) {
this->cur_x = 0;
this->cur_y++;
}
void Terminal::putchar(uint32_t ptr, uint8_t c, uint8_t edata) {
// All modifications to the screen are done to the last page.
last_page_pointer[this->cur_y*this->width+this->cur_x] = c | (edata<<8);
last_page_pointer[ptr] = c | (edata<<8);
if (active)
putchar_internal(this->cur_y*this->width+this->cur_x, c, this->edata);
this->cur_x++;
break;
}
break;
case EscapeCode:
switch (c) {
case '[':
this->state = CSI;
break;
default:
break;
}
break;
case CSI:
this->state = ParameterBytes;
this->parameterIndex = 0;
this->intermediaryIndex = 0;
goto again;
break;
case ParameterBytes:
if (parameterIndex < 128 && c >= 0x30 && c <= 0x3F) {
parameterBytes[parameterIndex++] = c;
} else {
parameterIndex;
this->state = IntermediaryBytes;
goto again;
}
break;
case IntermediaryBytes:
if (intermediaryIndex < 128 && c >= 0x20 && c <= 0x2F) {
intermediaryBytes[intermediaryIndex++] = c;
} else {
intermediaryIndex;
this->state = FinalByte;
goto again;
}
break;
case FinalByte:
switch (c) {
case 'A':
this->cur_y -= clamp(strToInt(parameterBytes, parameterIndex), 0, this->cur_y);
break;
case 'B':
this->cur_y += clamp(strToInt(parameterBytes, parameterIndex), 0, this->height - this->cur_y);
break;
case 'C':
this->cur_x += clamp(strToInt(parameterBytes, parameterIndex), 0, this->width - this->cur_x);
break;
case 'D':
this->cur_x -= clamp(strToInt(parameterBytes, parameterIndex), 0, this->cur_x);
break;
case 'E':
this->cur_y += clamp(strToInt(parameterBytes, parameterIndex), 0, this->height - this->cur_y);
this->cur_x = 0;
break;
case 'F':
this->cur_y -= clamp(strToInt(parameterBytes, parameterIndex), 0, this->cur_y);
this->cur_x = 0;
break;
case 'G':
this->cur_x = clamp(strToInt(parameterBytes, parameterIndex), 0, this->width);
break;
case 'f':
case 'H': {
uint32_t semicolonIndex = 0;
while (parameterBytes[semicolonIndex++] != ';' && semicolonIndex <= parameterIndex);
this->cur_y = clamp(strToInt(parameterBytes, parameterIndex) - 1, 0, this->height) ;
this->cur_x = clamp(strToInt(parameterBytes+semicolonIndex, parameterIndex-semicolonIndex) - 1, 0, this->width);
break;
}
case 'm':
this->state = SGR;
goto again;
break;
default:
break;
}
this->state = None;
break;
case SGR: {
uint32_t index = 0;
while (index <= parameterIndex) {
uint32_t n = strToInt(parameterBytes+index, parameterIndex-index);
switch (n) {
case 0:
this->edata = 0xf;
break;
case 1:
if ((this->edata&0xf) <= 0x7)
this->edata += 8;
break;
case 2:
if ((this->edata&0xf) >= 0x7)
this->edata -= 8;
break;
case 30 ... 37:
this->edata &= 0xf0;
this->edata |= n-30;
break;
case 40 ... 47:
this->edata &= 0x0f;
this->edata |= (n-40)<<4;
break;
case 49:
this->edata &= 0x0f;
this->edata |= 0xf0;
default:
break;
}
while (parameterBytes[index++] != ';' && index <= parameterIndex);
}
this->state = None;
}
default:
break;
}
if (this->cur_y == this->height) {
this->cur_y--;
scroll_up();
}
putchar_internal(ptr, c, edata);
}
void Terminal::update(){}
void Terminal::update_cur(){}
void Terminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) {}
Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages) {
Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages)
: ReadWriter(0) {
this->width = width;
this->height = height;
this->pages = pages;
@ -229,19 +46,21 @@ Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages) {
this->active = false;
}
void Terminal::resize(uint32_t width, uint32_t height, uint32_t pages) {
delete this->buffer;
this->width = width;
this->height = height;
this->pages = pages;
this->buffer = new uint16_t[width * height * pages];
this->last_page_pointer = buffer + (width * height * pages) - (width * height);
this->current_page_pointer = last_page_pointer;
int strToInt(char* str) {
int r=0;
while (*str >= 0x30 && *str <= 0x39) {
r *= 10;
r += *(str++) - 0x30;
}
return r;
}
this->cur_x = 0;
this->cur_y = 0;
this->active = false;
int clamp(int a, int b, int c) {
if (a < b)
return b;
if (a > c)
return c;
return a;
}
void Terminal::printf(const char* string, ...) {
@ -252,6 +71,73 @@ void Terminal::printf(const char* string, ...) {
char current;
while (current=string[index++]) {
if (current == '\n') {
this->cur_x = 0;
this->cur_y++;
}
if (current == 0x1b && string[index] == '[') {
index++;
char* parameterStart = (string+index);
while (string[index] >= 0x30 && string[index] <= 0x3F)
index++;
char* parameterEnd = (string+index);
char* intermediateStart = (string+index);
while (string[index] >= 0x20 && string[index] <= 0x2F)
index++;
char final = *(string+(index++));
switch (final) {
case 'A':
this->cur_y -= clamp(strToInt(parameterStart), 0, this->cur_y);
break;
case 'B':
this->cur_y += clamp(strToInt(parameterStart), 0, this->height - this->cur_y);
break;
case 'C':
this->cur_x += clamp(strToInt(parameterStart), 0, this->width - this->cur_x);
break;
case 'D':
this->cur_x -= clamp(strToInt(parameterStart), 0, this->cur_x);
break;
case 'H': {
char* s=parameterStart;
while (*s != ';' && s < parameterEnd)
s++;
s++;
this->cur_y = clamp(strToInt(parameterStart), 1, this->height) - 1;
this->cur_x = clamp(strToInt(s), 1, this->width) - 1;
break;
}
}
continue;
}
if (current == '\b') {
if (this->cur_x > 0) {
this->cur_x--;
} else if (this->cur_y > 0) {
this->cur_y--;
this->cur_x = this->width-1;
}
int mem_pos = this->cur_y * this->width + this->cur_x;
this->putchar(mem_pos, ' ');
continue;
}
if (this->cur_x == this->width) {
this->cur_x = 0;
this->cur_y++;
}
if (this->cur_y == this->height)
this->scroll_up();
if (current == '%') {
int type = string[index++];
int offset;
@ -273,17 +159,22 @@ void Terminal::printf(const char* string, ...) {
break;
}
case 'c': {
int mem_pos = this->cur_y * this->width + this->cur_x++;
int promoted = va_arg(ptr, int);
char charred = promoted;
this->putchar(charred);
this->putchar(mem_pos, charred);
break;
}
}
continue;
}
this->putchar(current);
if (current != '\n') {
int mem_pos = this->cur_y * this->width + this->cur_x++;
this->putchar(mem_pos, current);
}
}
this->set_curpos(this->cur_x, this->cur_y);
@ -292,14 +183,89 @@ void Terminal::printf(const char* string, ...) {
}
uint32_t Terminal::write(uint32_t count, uint8_t* string) {
for (int index=0; index < count; index++)
this->putchar(string[index]);
int index = 0;
char current;
while (index < count) {
current=string[index++];
if (current == '\n') {
this->cur_x = 0;
this->cur_y++;
}
if (current == 0x1b && string[index] == '[') {
index++;
char* parameterStart = (string+index);
while (string[index] >= 0x30 && string[index] <= 0x3F)
index++;
char* parameterEnd = (string+index);
char* intermediateStart = (string+index);
while (string[index] >= 0x20 && string[index] <= 0x2F)
index++;
char final = *(string+(index++));
switch (final) {
case 'A':
this->cur_y -= clamp(strToInt(parameterStart), 0, this->cur_y);
break;
case 'B':
this->cur_y += clamp(strToInt(parameterStart), 0, this->height - this->cur_y);
break;
case 'C':
this->cur_x += clamp(strToInt(parameterStart), 0, this->width - this->cur_x);
break;
case 'D':
this->cur_x -= clamp(strToInt(parameterStart), 0, this->cur_x);
break;
case 'H': {
char* s=parameterStart;
while (*s != ';' && s < parameterEnd)
s++;
s++;
this->cur_y = clamp(strToInt(parameterStart), 1, this->height) - 1;
this->cur_x = clamp(strToInt(s), 1, this->width) - 1;
break;
}
}
continue;
}
if (current == '\b') {
if (this->cur_x > 0) {
this->cur_x--;
} else if (this->cur_y > 0) {
this->cur_y--;
this->cur_x = this->width-1;
}
int mem_pos = this->cur_y * this->width + this->cur_x;
this->putchar(mem_pos, ' ');
continue;
}
if (this->cur_x == this->width) {
this->cur_x = 0;
this->cur_y++;
}
if (this->cur_y == this->height)
this->scroll_up();
if (current != '\n') {
int mem_pos = this->cur_y * this->width + this->cur_x++;
this->putchar(mem_pos, current);
}
}
this->set_curpos(this->cur_x, this->cur_y);
return count;
}
uint32_t Terminal::read(uint32_t count, uint8_t* buffer) {return;}
uint32_t Terminal::read(uint32_t count, uint8_t* buffer) {}
void Terminal::clear_screen() {
for (int i=0; i < width * height * pages; i++) {
@ -364,29 +330,10 @@ TextModeTerminal::TextModeTerminal(uint16_t* text_mode_pointer): Terminal(80, 25
this->text_mode_pointer = text_mode_pointer;
}
uint32_t color_map[16] = {
0, // Black
0x00000080, // Blue
0x00008000, // Green
0x00008080, // Cyan
0x00800000, // Red
0x00800080, // Magenta
0x00008080, // Yellow
0x00808080, // White
0x00404040, // Black
0x000000ff, // Blue
0x0000ff00, // Green
0x0000ffff, // Cyan
0x000000ff, // Red
0x00ff00ff, // Magenta
0x00ffff00, // Yellow
0x00ffffff // White
};
void VGAModeTerminal::update() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
putchar_internal(y * width + x, (uint8_t)(current_page_pointer[y * width + x]), (uint8_t)(current_page_pointer[y * width + x]>>8));
putchar_internal(y * width + x, (uint8_t)(current_page_pointer[y * width + x]), 0);
}
}
}
@ -406,12 +353,15 @@ void VGAModeTerminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) {
return;
uint8_t* char_data = font[c];
for (int y=0; y<8; y++)
put_pixels_byte(sx, sy+y, edata, char_data[y]);
for (int y=0; y<8; y++) {
//for (int x=0; x<8; x++) {
put_pixels_byte(sx, sy+y, 15, char_data[y]);
//}
}
}
void VGAModeTerminal::put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte) {
uint32_t pixel = y * pixelWidth + x;
uint32_t pixel = y * 720 + x;
uint32_t pixelindex = pixel / 8;
uint8_t trbyte = 0;
@ -421,18 +371,17 @@ void VGAModeTerminal::put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uin
}
for (int i=0; i<4; i++) {
this->planes[i][pixelindex] = 0;
if (color & (1<<i))
this->planes[i][pixelindex] |= trbyte;
if ((color>>4) & (1<<i))
this->planes[i][pixelindex] |= ~trbyte;
this->planes[i][pixelindex] = trbyte;
else
this->planes[i][pixelindex] = 0;
}
}
void VGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) {
// For any pixel we need to write 1 bit to planes 0, 1, 2, and 3
uint32_t pixel = y * pixelWidth + x;
uint32_t pixel = y * 720 + x;
uint32_t pixelindex = pixel / 8;
uint32_t pixelbitindex = pixel % 8;
@ -444,37 +393,40 @@ void VGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) {
}
}
void VGAModeTerminal::bufferToVRAM() {
uint32_t count4 = (this->pixelWidth * this->pixelHeight) / 8 / 4;
static void VGAModeTerminal::bufferToVRAM(frame_struct* frame, VGAModeTerminal* terminal) {
uint32_t count4 = (720 * 480) / 8 / 4;
for (int i=0; i<4; i++) {
outb(0x3c4, 2);
outb(0x3c5, 1<<i);
for (int c=0; c<count4; c++) {
((uint32_t*)this->vga_pointer)[c] = ((uint32_t*)this->planes[i])[c];
((uint32_t*)terminal->vga_pointer)[c] = ((uint32_t*)terminal->planes[i])[c];
}
}
}
VGAModeTerminal::VGAModeTerminal(uint8_t* vga_pointer): Terminal(0, 0, 1) {
VGAModeTerminal::VGAModeTerminal(uint8_t* vga_pointer): Terminal(90, 60, 1) {
this->vga_pointer = vga_pointer;
for (int i=0; i<4; i++) {
for (int i=0; i<4; i++) {
this->planes[i] = new uint8_t[720 * 480 / 8];
}
this->resize(pixelWidth / 8, pixelHeight / 8, 1);
unsigned char g_720x480x16[] =
{
/* MISC */
0xE7,
/* SEQ */
0x03, 0x01, 0x08, 0x00, 0x06,
/* CRTC */
0x6B, 0x59, 0x5A, 0x82, 0x60, 0x8D, 0x0B, 0x3E,
0x00, 0x40, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
0xEA, 0x0C, 0xDF, 0x2D, 0x08, 0xE8, 0x05, 0xE3,
0xFF,
/* GC */
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
0xFF,
/* AC */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x01, 0x00, 0x0F, 0x00, 0x00,
@ -526,86 +478,5 @@ for (int i=0; i<4; i++) {
}
}
Timer::register_event(16, (void(*)(void*))&VGAModeTerminal::bufferToVRAM, this);
}
void BGAModeTerminal::update() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
putchar_internal(y * width + x, (uint8_t)(current_page_pointer[y * width + x]), (uint8_t)(current_page_pointer[y * width + x]>>8));
}
}
}
void BGAModeTerminal::update_cur() {
// Todo: Implement cursor for VGAModeTerminal
}
void BGAModeTerminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) {
uint32_t col = ptr % width;
uint32_t row = ptr / width;
uint32_t sx = col * 8;
uint32_t sy = row * 8;
if (c>127)
return;
uint8_t* char_data = font[c];
for (int y=0; y<8; y++)
put_pixels_byte(sx, sy+y, edata, char_data[y]);
}
void BGAModeTerminal::put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte) {
uint32_t pixel = y * pixelWidth + x;
for (int i=0; i<8; i++)
if (pixel_byte&(1<<i))
this->fb[pixel+i] = color_map[color&0xf];
else
this->fb[pixel+i] = color_map[(color>>4)&0xf];
}
void BGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) {
// For any pixel we need to write 1 bit to planes 0, 1, 2, and 3
uint32_t pixel = y * pixelWidth + x;
uint32_t pixelindex = pixel / 8;
uint32_t pixelbitindex = pixel % 8;
this->fb[pixel] = color_map[color];
}
void BGAModeTerminal::bufferToVRAM() {
uint32_t c = this->pixelWidth * this->pixelHeight;
uint32_t bank=0;
uint32_t ctr=0;
for (int i=0; i<c; i++) {
if (i%16384 == 0) {
outw(0x1ce, 5);
outw(0x1cf, bank++);
}
((uint32_t*)this->vga_pointer)[i%16384] = ((uint32_t*)this->fb)[i];
}
}
BGAModeTerminal::BGAModeTerminal(uint8_t* vga_pointer): Terminal(0, 0, 1) {
this->vga_pointer = vga_pointer;
this->fb = new uint32_t[pixelWidth * pixelHeight];
this->resize(pixelWidth / 8, pixelHeight / 8, 1);
outw(0x1ce, 4);
outw(0x1cf, 0);
outw(0x1ce, 1);
outw(0x1cf, pixelWidth);
outw(0x1ce, 2);
outw(0x1cf, pixelHeight);
outw(0x1ce, 3);
outw(0x1cf, 32);
outw(0x1ce, 4);
outw(0x1cf, 1);
Timer::register_event(16, (void(*)(void*))&BGAModeTerminal::bufferToVRAM, this);
Timer::register_event(16, &VGAModeTerminal::bufferToVRAM, this);
}

View File

@ -14,38 +14,23 @@
struct frame_struct;
namespace Timer {
void register_event(uint32_t milliseconds, void(*function)(void*), void* auxiliary, bool oneshot=false);
void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary);
}
enum TerminalState {
None,
EscapeCode,
CSI,
ParameterBytes,
IntermediaryBytes,
FinalByte,
SGR
};
class Terminal: public ReadWriter {
private:
virtual void update();
virtual void update_cur();
virtual void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata);
virtual void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata=0x07);
void scroll_up(uint32_t count=1);
void scroll_down(uint32_t count=1);
void scroll_up();
void putchar(uint8_t c);
TerminalState state = None;
uint8_t parameterBytes[128];
uint8_t intermediaryBytes[128];
uint32_t parameterIndex = 0;
uint32_t intermediaryIndex = 0;
void putchar(uint32_t ptr, uint8_t c, uint8_t edata=0x07);
protected:
uint16_t* buffer;
uint32_t width;
uint32_t height;
uint32_t pages;
uint32_t cur_x;
@ -55,14 +40,7 @@ protected:
uint16_t* last_page_pointer;
bool active;
uint8_t edata=0x07;
void resize(uint32_t width, uint32_t height, uint32_t pages);
public:
uint32_t width;
uint32_t height;
Terminal(uint32_t width, uint32_t height, uint32_t pages);
void printf(const char* string, ...);
@ -84,52 +62,29 @@ class TextModeTerminal : public Terminal {
private:
void update() override;
void update_cur() override;
void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) override;
void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata=0x07) override;
uint16_t* text_mode_pointer;
public:
TextModeTerminal(uint16_t* text_mode_pointer);
};
class VGAModeTerminal : public Terminal {
private:
void update() override;
void update_cur() override;
void putchar_internal(uint32_t ptr, uint8_t c,uint8_t edata) override;
void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata=0x07) override;
void put_pixel(uint32_t x, uint32_t y, uint8_t color);
void put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte);
static void bufferToVRAM(frame_struct* frame, VGAModeTerminal* terminal);
public:
void bufferToVRAM();
uint32_t pixelWidth = 720;
uint32_t pixelHeight = 480;
uint8_t* vga_pointer;
uint8_t* planes[4];
VGAModeTerminal(uint8_t* vga_pointer);
};
class BGAModeTerminal : public Terminal {
private:
void update() override;
void update_cur() override;
void putchar_internal(uint32_t ptr, uint8_t c,uint8_t edata) override;
void put_pixel(uint32_t x, uint32_t y, uint8_t color);
void put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte);
public:
void bufferToVRAM();
uint32_t pixelWidth = 720;
uint32_t pixelHeight = 480;
uint8_t* vga_pointer;
uint32_t* fb;
BGAModeTerminal(uint8_t* vga_pointer);
};
#endif

20
src/program/program.c Normal file
View File

@ -0,0 +1,20 @@
#include "../kernel/types.h"
#include "../common/common.h"
int main() {
print("Testing C code program\n");
print("My strings are messed up for some reason...\n");
uint32_t alpha_size = filesize("HELLO TXT");
char sizebuf[32];
uint32_t index = int_to_decimal(alpha_size, sizebuf);
print(sizebuf+index);
print("\n");
uint8_t* alpha_buffer = (uint8_t*)localalloc(alpha_size + 32);
print("alpha_buffer: ");
index = int_to_hex(alpha_buffer, sizebuf);
print(sizebuf+index);
print("\n");
readfile("HELLO TXT", alpha_buffer);
print(alpha_buffer);
}

14
src/program/program.ld Normal file
View File

@ -0,0 +1,14 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:i386)
OUTPUT(build/program/program.bin)
SECTIONS {
. = 0x20;
.text : {
build/program_code_entry.o(.text)
build/program/program.o(.text)
build/common/common.o(.text)
}
}

View File

@ -1,17 +0,0 @@
#include "common/common.h"
int main(int argc, char** argv) {
for (int i=1; i<argc; i++) {
if (exists(argv[i])) {
uint32_t fh = fopen(argv[i]);
char buf[128];
uint32_t count;
while (count=read(128, fh, buf))
write(count, 0, buf);
fclose(fh);
} else {
printf("No such file or directory: %s", argv[i]);
break;
}
}
}

View File

@ -1,7 +0,0 @@
#include "common/common.h"
int main(int argc, char** argv) {
for (int i=1; i<argc; i++) {
printf("%s%s", argv[i], (i==argc-1)?"\n":" ");
}
}

View File

@ -1,11 +0,0 @@
[BITS 32]
_start:
call __setup
call main
push eax
call die
extern die
extern main
extern __setup

View File

@ -1,10 +0,0 @@
#include "common/common.h"
int main() {
uint32_t pid = fork();
if (pid) {
printf("Parent PID: %d\nChild PID: %d\n", getPID(), pid);
} else {
printf("CHILD: Hello!\n");
}
}

View File

@ -1,21 +0,0 @@
#include "common/common.h"
int main() {
// The job of init will be to load the system configuration, mount devices, etc
bindToKeyboard();
char* fn = "/xosh.bin";
uint8_t* argv[] = {
fn,
0
};
uint8_t* envp[] = {
"PATH=/",
0
};
uint32_t xosh_fh = fopen(fn);
uint32_t xosh = execve(xosh_fh, argv, envp);
while (1);
}

View File

@ -1,8 +0,0 @@
#include "common/common.h"
int main(uint32_t argc, char** argv, char** envp) {
printf("Environment: \n");
for (int i=0; envp[i]; i++)
printf("- %s\n", envp[i]);
printf("\n");
}

View File

@ -1,35 +0,0 @@
#include "common/common.h"
char* filetype(FSType t) {
switch (t) {
case File:
return "File";
case Directory:
return "Directory";
case CharacterDev:
return "CharacterDev";
case BlockDev:
return "BlockDev";
case NoExist:
return "NoExist";
}
return "";
}
int main(int argc, char** argv) {
if (argc != 2) {
printf("Usage: %s <directory>", argv[0]);
return 1;
}
char* directory = argv[1];
uint32_t dentsSize = getDentsSize(directory);
FSDirectoryListing* dents = (FSDirectoryListing*)malloc(dentsSize);
getDents(directory, (uint8_t*)dents);
for (int i=0; i<dents->count; i++) {
FSDirectoryEntry e = dents->entries[i];
printf("%.s %d %s\n", e.path.length, e.path.path, e.sizeBytes, filetype(e.type));
}
}

View File

@ -1,11 +0,0 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:i386)
SECTIONS {
. = 0x1020;
.text : {
build/programs/entry.o(.text)
build/common/common.o(.text)
}
}

View File

@ -1,107 +0,0 @@
#include "common/common.h"
void readline(char* buf, uint32_t lim) {
uint32_t idx = 0;
while (1) {
char c;
if (idx == lim) {
printf("\n");
break;
}
if (read(1, 1, &c)) {
if (c == '\n') {
write(1, 0, &c);
break;
} else if (c == '\b') {
if (idx > 0) {
buf[--idx] = 0;
write(1, 0, &c);
}
} else if (c == 0) {
continue;
} else {
buf[idx++] = c;
write(1, 0, &c);
}
}
}
}
typedef enum {
Normal,
StringLiteral,
Escaped
} ParseState;
int main(int argc, char** argv, char** envp) {
// XOSH - The XnoeOS Shell
// XoSH is going to be a simple shell that can be used to execute programs.
printf("Welcome to %s!\n\n", argv[0]);
printf("Environment:\n");
for (int i=0; envp[i]; i++)
printf("- %s\n", envp[i]);
printf("\n");
while (1) {
printf("\x1b[0m# ");
char input[128];
memset(input, 0, 128);
readline(input, 128);
// Parse the input
char* result[32];
uint32_t ridx=0;
memset(result, 0, 32 * sizeof(char));
char c;
uint32_t idx=0;
char* lp = input;
ParseState s = Normal;
while (c=input[idx++]) {
switch (s) {
case Normal:
switch (c) {
case '"':
s = StringLiteral;
break;
case '\\':
s = Escaped;
break;
case ' ':
input[idx-1] = 0;
result[ridx++] = lp;
lp = (char*)(input+idx);
break;
default:
break;
}
break;
case StringLiteral:
if (c == '"') {
s = Normal;
}
break;
case Escaped:
break;
default:
break;
}
}
result[ridx++] = lp;
if (ridx > 0) {
char* programName = result[0];
if (exists(programName)) {
char** argv = result;
uint32_t program = fopen(programName);
uint32_t e = execv(program, argv);
printf("\nExit code: %d\n\n", e);
} else if (strcmp(result[0], "set")) {
if (result[1] && result[2]) setenv(result[1], result[2]);
} else {
printf("No such executable file: `%s`\n\n", programName);
}
}
}
}

283
src/world/world.c Normal file
View File

@ -0,0 +1,283 @@
#include "../common/common.h"
#include <stdbool.h>
typedef struct {
char* buffer;
int x;
int y;
uint32_t process;
uint32_t stdin;
uint32_t stdout;
} procbuffer;
void scrollBuffer(char* buf) {
for (int y=0; y<56; y++)
for (int x=0; x<43; x++)
if (y != 55)
buf[y*43+x] = buf[(y+1)*43+x];
else
buf[y*43+x] = ' ';
}
void writeToBuf(char c, procbuffer* buf) {
switch (c) {
case '\n':
buf->x = 0;
buf->y++;
break;
case '\b':
if (buf->x > 0)
buf->x--;
else if (buf->y > 0) {
buf->x = 42;
buf->y--;
}
buf->buffer[buf->y*43+buf->x] = ' ';
break;
default:
buf->buffer[buf->y*43+buf->x++] = c;
}
if (buf->x == 43) {
buf->x = 0;
buf->y++;
}
if (buf->y == 56) {
buf->y--;
scrollBuffer(buf->buffer);
}
}
void writeCountToBuf(int count, char* c, procbuffer* buf) {
while (count--) {
writeToBuf(*(c++), buf);
}
}
void clearBuf(procbuffer* buf) {
for (int i=0; i<56*43;i++) {
buf->buffer[i] = ' ';
}
buf->x = 0;
buf->y = 0;
}
void writeStrToBuf(char* c, procbuffer* b) {
char* s = c;
while(*s)
writeToBuf(*(s++), b);
}
void displayBuf(procbuffer* b, int dx, int dy) {
char pset[9] = "\x1b[00;00H";
for (int i=0; i<dy;i++) {
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<dx;i++) {
pset[6]++;
if (pset[6] == 0x3a) {
pset[6] = 0x30;
pset[5]++;
}
}
for (int i=0; i<56; i++) {
print(pset);
write(43, 0, b->buffer+(43*i));
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
}
void setCurPos(int x, int y) {
char pset[9] = "\x1b[00;00H";
for (int i=0; i<y;i++) {
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<x;i++) {
pset[6]++;
if (pset[6] == 0x3a) {
pset[6] = 0x30;
pset[5]++;
}
}
print(pset);
}
void readline(int count, char* buffer) {
int index = 0;
char c;
while (index < count) {
if (read(1, 1, &c)) {
if (c == '\n')
break;
if (c == '\b') {
if (index == 0)
continue;
else {
index--;
buffer[index] = 0;
write(1, 0, &c);
continue;
}
}
buffer[index++] = c;
write(1, 0, &c);
}
}
}
bool strcmp(char* a, char* b) {
int index=0;
while (a[index])
if (a[index] == b[index])
index++;
else
return false;
return true;
}
bool strcmpcnt(int count, char* a, char* b) {
int index=0;
while (index < count)
if (a[index] == b[index])
index++;
else
return false;
return true;
}
int main() {
bindToKeyboard();
char space = ' ';
char plus = '+';
print("\x1b[1;1H");
for (int i=0; i < 1000; i++)
write(1, 0, &space);
print("\x1b[1;1H");
char* mid = "+ ++ +";
char* bottom = "+ +";
for (int i=0; i<90;i++)
write(1, 0, &plus);
for (int i=0; i<56;i++)
write(90, 0, mid);
for (int i=0; i<90;i++)
write(1, 0, &plus);
write(90, 0, bottom);
for (int i=0; i<90;i++)
write(1, 0, &plus);
uint32_t program = fopen("hello.bin");
uint32_t p1 = fork(program);
uint32_t p1out = bindStdout(p1);
uint32_t p1in = bindStdin(p1);
fclose(program);
program = fopen("hello.bin");
uint32_t p2 = fork(program);
uint32_t p2out = bindStdout(p2);
uint32_t p2in = bindStdin(p2);
fclose(program);
procbuffer b1 = {
.buffer = localalloc(56 * 43),
.x = 0,
.y = 0,
.process = p1,
.stdin = p1in,
.stdout = p1out
};
procbuffer b2 = {
.buffer = localalloc(56 * 43),
.x = 0,
.y = 0,
.process = p2,
.stdin = p2in,
.stdout = p2out
};
procbuffer* selectedBuf = &b1;
writeStrToBuf("XoSH (XOS SHell) v0.0.1\nPress : to use commands.\n :help for help.\n", &b1);
while (1) {
char c[128];
int succ = 0;
if (b1.process)
if (succ = read(128, b1.stdout, c))
writeCountToBuf(succ, c, &b1);
if (b2.process)
if (succ = read(128, b2.stdout, c))
writeCountToBuf(succ, c, &b2);
if (read(1, 1, c)) {
if (c[0] == ':') {
char buf[32] = {0};
print("\x1b[59;2H");
print(": ");
print("\x1b[59;3H");
readline(32, buf);
if (strcmpcnt(6, buf, "switch")) {
if (selectedBuf == &b1) {
selectedBuf = &b2;
} else {
selectedBuf = &b1;
}
} else if (strcmpcnt(4, buf, "help")) {
writeStrToBuf("\n--------\n", selectedBuf);
writeStrToBuf(":help\n", selectedBuf);
writeStrToBuf(" Displays this message.\n", selectedBuf);
writeStrToBuf(":switch\n", selectedBuf);
writeStrToBuf(" Switches which process you're using\n", selectedBuf);
writeStrToBuf(":kill\n", selectedBuf);
writeStrToBuf(" Kills the current process\n", selectedBuf);
writeStrToBuf(":load <filename>\n", selectedBuf);
writeStrToBuf(" Loads and executes the program <filename>\n", selectedBuf);
writeStrToBuf("--------\n", selectedBuf);
} else if (strcmpcnt(4, buf, "kill")) {
if (selectedBuf->process) {
kill(selectedBuf->process);
clearBuf(selectedBuf);
selectedBuf->process = 0;
selectedBuf->stdin = 0;
selectedBuf->stdout = 0;
if (selectedBuf == &b1) {
selectedBuf = &b2;
} else {
selectedBuf = &b1;
}
}
} else if (strcmpcnt(4, buf, "load")) {
if (!selectedBuf->process) {
char* potFn = buf+5;
uint32_t fh = fopen(potFn);
selectedBuf->process = fork(fh);
selectedBuf->stdout = bindStdout(selectedBuf->process);
selectedBuf->stdin = bindStdin(selectedBuf->process);
fclose(fh);
}
}
} else {
if (selectedBuf->process)
write(1, selectedBuf->stdin, c);
}
}
displayBuf(&b1, 2, 2);
displayBuf(&b2, 47, 2);
}
}

14
src/world/world.ld Normal file
View File

@ -0,0 +1,14 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:i386)
OUTPUT(build/world/world.bin)
SECTIONS {
. = 0x20;
.text : {
build/program_code_entry.o(.text)
build/world/world.o(.text)
build/common/common.o(.text)
}
}