Compare commits

..

15 Commits

Author SHA1 Message Date
b00f6d6217
Added multiple threads per process 2022-06-18 17:45:16 +01:00
f3b1bfc5ef
Added VFS, updated DevFS, Added SysFS 2022-06-18 15:41:32 +01:00
437c78d374
Fixed sleep 2022-06-18 15:12:20 +01:00
fdb77277a7
Renamed Maybe to maybe. Moved tracking of filehandlers to be per-process rather than global. Various improvements to code. 2022-06-18 11:42:09 +01:00
da5fc52afe
Updated the KernelInformationStruct, added BGA (Bochs Graphics Extensions) mode termimal, added new system calls to get terminal width. Updated world.bin to calculate sizes. Fixed a bug where GetExhaustive would crash when given a completely null path. Started work on V86 for VBE support. 2022-05-16 09:57:09 +01:00
6339b3e4bd
Added spinlocks 2022-04-15 21:10:10 +01:00
dc2fe698a3
Added oneshot timer functionality. Added sleep function. Added proper tracking of physical pages allocated. Made the 0th page invalid. Fixed a 4KiB memory leak when destroying processes. Fixed scrolling colour in terminal.cpp 2022-04-15 16:15:51 +01:00
0fc40ad5e4
Add system calls for more file system related functionality. Add ls command to world.c. Remove and reorganise certain source code files. Update terminal to no longer have two copies of ANSI escape code handling between write and printf. Massively simplify my printf function. Combine io and ioports. 2022-04-12 03:42:13 +01:00
8f4382793c
Fixed spelling mistake 2022-04-09 00:31:08 +01:00
bb69d6b713
Update how syscalls accept arguments in registers, change how syscalls are defined in common.c and common.h 2022-04-08 18:00:56 +01:00
7e5f20ef66
Added sleep syscall 2022-04-08 02:01:25 +01:00
c2f857fc88
Removed extra directories 2022-04-08 00:49:26 +01:00
edd6e82c2c
Remove old boot_stage2 directory 2022-04-06 20:59:33 +01:00
a0d0454e32
Moved to a new Filesystem, ATA and FAT16 driver. 2022-04-06 14:46:47 +01:00
ed34174d68
Rename boot_stage2 to bootstage2 2022-03-04 20:25:17 +00:00
82 changed files with 3040 additions and 1532 deletions

View File

@ -1,67 +1,60 @@
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.
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/
LDFLAGS =
DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt \
build/hello/hello.bin
DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt
KERNEL_CPP_SRCS = $(wildcard src/kernel/*.cpp) $(wildcard src/kernel/*/*.cpp)
KERNEL_ASM_SRCS = $(wildcard src/kernel/*.asm)
KERNEL_CPP_SRCS = $(shell find src/kernel/ -name '*.cpp')
KERNEL_ASM_SRCS = $(shell find src/kernel/ -name '*.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/boot_stage2/*.c)
STAGE2_C_SRCS = $(wildcard src/bootstage2/*.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/program_code_entry.o build/common/common.o
PROGRAM_COMMON = build/programs/entry.o build/common/common.o
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)
SRC_DIRS = $(shell find src/ -type d)
BUILD_DIRS = $(subst src/,build/,$(SRC_DIRS))
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)
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)) \
)
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
.PHONY: run debug prepare clean cleanbuild
run: disk.img
qemu-system-i386 disk.img
debug: disk.img
cleanbuild: clean disk.img
qemu-system-i386 disk.img
debug: clean disk.img
qemu-system-i386 -s -S -no-reboot -no-shutdown disk.img & gdb --command=gdbscript
disk.img: prepare build/boot/boot.bin build/boot_stage2/boot.bin $(DISK_IMG_FILES) build/world/world.bin
disk.img: prepare build/boot/boot.bin build/bootstage2/boot.bin $(DISK_IMG_FILES)
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/boot_stage2/boot.bin of=disk.img conv=notrunc
dd obs=512 seek=1 if=build/bootstage2/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/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
mkdir -p $(BUILD_DIRS)
mountpoint img.d | grep not || umount img.d
clean:
@ -71,10 +64,10 @@ build/boot/boot.bin: src/boot/boot.asm
nasm $< -o $@
# Boot Stage 2
build/boot_stage2/boot.bin: src/boot_stage2/boot_stage2.ld $(STAGE2_OBJS)
build/bootstage2/boot.bin: src/bootstage2/bootstage2.ld $(STAGE2_OBJS)
ld $(LDFLAGS) -T $< $(STAGE2_OBJS)
build/boot_stage2/%.o: src/boot_stage2/%.c
build/bootstage2/%.o: src/bootstage2/%.c
gcc $(CFLAGS) -o $@ -c $<
# Kernel
@ -101,12 +94,6 @@ src/kernel/isr.S: src/kernel/isr.S.base src/kernel/gen_isr_asm.sh
# Program
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)
.SECONDEXPANSION:
build/programs/%.bin: src/programs/userspace.ld build/programs/entry.o $$(src/programs/$$(basename $$(notdir $$*))_OBJS) $(PROGRAM_COMMON)
ld -o $@ -T $^

View File

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

View File

@ -1,165 +0,0 @@
#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

@ -1,19 +0,0 @@
#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

View File

@ -1,69 +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;
}
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];
}
}

View File

@ -1,11 +0,0 @@
#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,14 +1,14 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:i386)
OUTPUT(build/boot_stage2/boot.bin)
OUTPUT(build/bootstage2/boot.bin)
SECTIONS {
. = 0x7E00;
.text : {
build/c_code_entry.o(.text)
build/boot_stage2/main.o(.text)
build/boot_stage2/*(.text)
build/bootstage2/main.o(.text)
build/bootstage2/*(.text)
}
}

View File

@ -1,5 +1,4 @@
#include "atapio.h"
#include "screenstuff.h"
#include "paging.h"
typedef struct {
@ -47,23 +46,18 @@ void mark_unavailble(uint32_t address, uint32_t size, uint8_t* buffer) {
}
}
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";
}
}
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;
void main() {
init_term();
init_atapio();
// e820 memory map exists at 0x20000
@ -72,14 +66,10 @@ void main() {
// Zero out the bitmap.
memset(bitmap, 0x20000, 0);
// Ensure the bitmap data is clear
for (int i=0; i<0x20000; i++)
if (bitmap[i])
printf("Found data in bitmap at %x!\n", (bitmap+i));
uint32_t pages;
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;
@ -96,8 +86,7 @@ void main() {
}
}
uint32_t page_index = base / 4096;
printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096);
pages += length / 4096;
for (int j=0; length > 4096; length -= 4096, j++) {
set_bit(page_index + j, bitmap);
@ -105,6 +94,7 @@ void main() {
}
mark_unavailble(bitmap, 0x20000, bitmap);
mark_unavailble(0, 0xFFFFF, bitmap);
// Page Directory
PDE* kernel_page_directory = bitmap + 0x20000;
@ -146,9 +136,9 @@ void main() {
// But first, we should load the kernel somewhere
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.
mark_unavailble(kernel_location, 0x20000, bitmap); // Just treat the kernel as not growing beyond 128k for now.
map_many_4k_phys_to_virt(kernel_location, 0xc0000000, kernel_page_directory, kernel_page_tables, 0x10); // Map 16 pages from 0x522000 to 0xc0000000;
map_many_4k_phys_to_virt(kernel_location, 0xc0000000, kernel_page_directory, kernel_page_tables, 0x20); // Map 32 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
@ -163,7 +153,7 @@ void main() {
memset(vm_bitmap, 0x20000, 0xff);
mark_unavailble(0xc07a0000, 0x20000, vm_bitmap);
mark_unavailble(0xc0000000, 0x10000, vm_bitmap);
mark_unavailble(0xc0000000, 0x20000, vm_bitmap);
mark_unavailble(0xc0100000, 0x1000, vm_bitmap);
mark_unavailble(0xc0101000, 0x400000, vm_bitmap);
mark_unavailble(0xc0501000, 0x1000, vm_bitmap);
@ -183,17 +173,31 @@ 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));
((void(*)(void))0xc0000000)();
asm volatile ("mov %0, %%esp":: "r"(0xc1000000 + 16*0x1000));
KernelInformationStruct kstruct= (KernelInformationStruct){
.pde = 0xc0100000,
.page_directory_phys_addr = 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);
}

View File

@ -6,6 +6,40 @@ 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;
@ -40,6 +74,11 @@ 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);

11
src/bootstage2/strings.c Normal file
View File

@ -0,0 +1,11 @@
#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;
}

8
src/bootstage2/strings.h Normal file
View File

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

View File

@ -1,5 +1,24 @@
#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"
void print(char* string) {
char* c = string;
int i=0;
@ -8,54 +27,6 @@ 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;
@ -87,3 +58,48 @@ int int_to_hex(unsigned int number, char* string_buffer) {
}
return (index+1);
}
void printf(const char* string, ...) {
va_list ptr;
va_start(ptr, string);
int index = 0;
char current;
while (current=string[index++]) {
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 promoted = va_arg(ptr, int);
char charred = promoted;
write(1, 0, &charred);
break;
}
}
continue;
}
write(1, 0, &current);
}
va_end(ptr);
}

View File

@ -2,28 +2,47 @@
#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"
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, ...);
#endif

31
src/common/syscalls.h Normal file
View File

@ -0,0 +1,31 @@
#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_1(uint32_t, exec, "7", uint32_t, filehandler);
syscall_hdlr_0(uint32_t, getPID, "8");
syscall_hdlr_0(void, die, "9");
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);

View File

@ -1,14 +0,0 @@
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,12 +8,6 @@ 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,7 +3,6 @@
#include "paging.h"
#include "datatypes/tuple.h"
//void init_allocator();
extern uint8_t* bitmap;
extern PDE* kernel_page_directory;

169
src/kernel/ata.cpp Normal file
View File

@ -0,0 +1,169 @@
#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 owner, uint32_t bus):
ATA(bus),
ReadWriter(owner) {
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;
}

110
src/kernel/ata.h Normal file
View File

@ -0,0 +1,110 @@
#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 owner, 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

View File

@ -1,255 +0,0 @@
#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;
}

View File

@ -1,77 +0,0 @@
#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

@ -0,0 +1,63 @@
#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;
}
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,7 +5,6 @@
#include "linkedlist.h"
#include "../memory.h"
#include "maybe.h"
#include "../screenstuff.h"
namespace xnoe {
template <class key, class value>
@ -40,19 +39,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) {

View File

@ -1,7 +1,9 @@
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "../types.h"
#include "../memory.h"
#include "../spinlock.h"
namespace xnoe {
template<typename T>
@ -19,25 +21,38 @@ namespace xnoe {
template<typename T>
struct linkedlist {
xnoe::linkedlistelem<T>* start;
xnoe::linkedlistelem<T>* end;
xnoe::linkedlistelem<T>* start=0;
xnoe::linkedlistelem<T>* end=0;
Spinlock lock = Spinlock();
uint32_t length = 0;
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;
@ -47,6 +62,8 @@ namespace xnoe {
this->start = llelem;
this->end = llelem;
}
length++;
lock.unlock();
}
void prepend(T t) {
@ -55,6 +72,7 @@ namespace xnoe {
}
void prepend(xnoe::linkedlistelem<T>* llelem) {
lock.lock();
if (this->start && this->end) {
this->start->prev = llelem;
llelem->next = this->start;
@ -64,14 +82,19 @@ 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) {
@ -85,6 +108,7 @@ namespace xnoe {
}*/
void remove(linkedlistelem<T>* elem) {
lock.lock();
linkedlistelem<T>* current = start;
while (current) {
if (current == elem) {
@ -95,18 +119,22 @@ namespace xnoe {
current->next->prev = current->prev;
if (current == start)
start = 0;
start = current->next;
if (current = end)
end = 0;
end = current->prev;
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) {
@ -124,10 +152,13 @@ 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,7 +1,6 @@
[BITS 32]
_start:
mov esp, 0xc100a000
jmp main
extern main

View File

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

View File

@ -0,0 +1,14 @@
#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

@ -0,0 +1,401 @@
#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 owner, uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS)
: ReadWriter(owner) {
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) {}
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;
}
}
bool 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[11] = {' '};
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[11] = {' '};
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(0, ((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

@ -0,0 +1,119 @@
#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 owner, 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;
bool 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

@ -0,0 +1,270 @@
#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){}
FSType FSTree::type(Path p){}
ReadWriter* FSTree::open(Path p){}
uint32_t FSTree::getDentsSize(Path p){}
void FSTree::getDents(Path p, FSDirectoryListing* buffer){}
// 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

@ -0,0 +1,87 @@
#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

@ -0,0 +1,28 @@
#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(0, 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(0, 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(0, 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(0, str+offset);
});
}

View File

@ -0,0 +1,14 @@
#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

@ -0,0 +1,133 @@
#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 false;
}
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

@ -0,0 +1,29 @@
#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 = 104
.iopb = sizeof(tss_struct)
};
constexpr gdt_entry::gdt_entry(uint32_t limit, uint32_t base, bool rw, bool exec, bool system, uint8_t ring) :
@ -77,7 +77,8 @@ constexpr gdt_entry::gdt_entry() :
base_hi(0)
{}
gdt_entry gdt[] = {
gdt_and_iopb gai = {
.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
@ -86,16 +87,19 @@ gdt_entry gdt[] = {
gdt_entry(0xfffff, 0, 1, 0, 1, 3), // User Data Segment
gdt_entry() // Empty Task State Segment
}
};
gdt_descr descr = (gdt_descr){
.size = sizeof(gdt) - 1,
.offset = gdt,
.size = sizeof(gai.gdt) - 1,
.offset = gai.gdt,
};
void init_gdt() {
gdt[5] = gdt_entry(sizeof(tss), &tss, 0, 1, 0, 0); // Initialise the TSS.
gdt[5].accessed = 1;
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;
asm volatile("lgdt %0;"
"mov $0x10, %%eax;"
"mov %%eax, %%ss;"

View File

@ -76,6 +76,11 @@ 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,6 +7,9 @@ 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,9 +4,11 @@ namespace Global {
Allocator* allocator = 0;
Kernel* kernel = 0;
Process* currentProc = 0;
Thread* currentThread = 0;
tss_struct* tss = 0;
bool currentProcValid = false;
xnoe::hashtable<void*, ReadWriter*>* FH; // Map of File Handlers -> Read Writer
uint32_t milliseconds_elapsed = 0;
uint32_t resp = 0;
}
void* operator new (uint32_t size) {
@ -32,3 +34,11 @@ 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,20 +6,19 @@
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 xnoe::hashtable<void*, ReadWriter*>* FH;
extern uint32_t milliseconds_elapsed;
extern uint32_t resp;
}
void* operator new (uint32_t size);
@ -30,4 +29,6 @@ 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

@ -26,31 +26,35 @@ void handle_fault(frame_struct* frame) {
asm ("cli");
uint32_t problem_address;
asm ("mov %%cr2, %0" : "=a" (problem_address):);
Global::kernel->terminal->printf("(CS %x EIP %x): ", frame->cs, frame->eip);
/*Global::kernel->terminal->printf("\x1b[44;37;1m(CS %x EIP %x): ", frame->cs, frame->eip);*/
switch (frame->gate) {
case 0: // Divide by zero
Global::kernel->terminal->printf("Divide by Zero");
//Global::kernel->terminal->printf("Divide by Zero");
break;
case 6: // Invalid Opcode
Global::kernel->terminal->printf("Invalid Opcode");
//Global::kernel->terminal->printf("Invalid Opcode");
break;
case 13: // GPF
Global::kernel->terminal->printf("General Protection Fault!");
//Global::kernel->terminal->printf("General Protection Fault!");
if (frame->eflags & 0x00020000) {
v86_monitor((v8086_frame_struct*)frame);
return;
}
break;
case 14: // Page Fault
Global::kernel->terminal->printf("Page Fault at %x", problem_address);
//Global::kernel->terminal->printf("Page Fault at %x", problem_address);
break;
default:
Global::kernel->terminal->printf("Unkown Fault!");
//Global::kernel->terminal->printf("Unkown Fault!");
break;
}
Global::kernel->terminal->printf(" Error Code: %x\n", frame->errcode);
/*Global::kernel->terminal->printf(" Error Code: %x\n", frame->errcode);*/
if (!(frame->cs & 3)) {
Global::kernel->terminal->printf("[FATAL] Kernel Fault!!!\n");
while (1) asm("hlt");
} else {
// Print an error message.
Global::kernel->terminal->printf("PID %d Terminated due to fault!\n", Global::currentProc->PID);
//Global::kernel->terminal->printf("PID %d Terminated due to fault!\n", Global::currentProc->PID);
asm volatile ("mov %0, %%esp" ::"m"(Global::kernel->globalISRStack));
Global::kernel->PD->select();
@ -58,10 +62,7 @@ void handle_fault(frame_struct* frame) {
Global::kernel->destroyProcess(Global::currentProc);
Global::currentProcValid = false;
// Go in to an infinite loop
asm ("sti");
while (1) asm ("hlt");
context_switch(frame);
}
}
@ -83,58 +84,65 @@ void context_switch(frame_struct* frame) {
asm ("cli"); // Disable interrupts whilst handling the context switch.
xnoe::linkedlist<Process*>* processes = &Global::kernel->processes;
xnoe::linkedlist<Thread*>* threads = &Global::kernel->threads;
if (!processes->start) {
if (!threads->start) {
Global::kernel->terminal->printf("[FATAL] No more processes! Halting!\n");
while (1) asm ("hlt");
}
if (Global::currentProcValid)
Global::currentProc->kernelStackPtr = frame->new_esp;
Global::currentThread->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
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;
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;
processes->start->prev = 0;
processes->end->next = 0;
processes->end->prev = processes->start;
processes->start->next = processes->end;
threads->start->prev = 0;
threads->end->next = 0;
threads->end->prev = threads->start;
threads->start->next = threads->end;
} else {
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;
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;
}
}
}
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
frame->new_cr3 = Global::currentProc->PD->phys_addr;
frame->new_cr3 = Global::currentThread->parent->PD->phys_addr;
// Restore kernelStackPtr of the new process.
frame->new_esp = Global::currentProc->kernelStackPtr;
frame->new_esp = Global::currentThread->kernelStackPtr;
Global::tss->esp0 = Global::currentProc->kernelStackPtrDefault;
Global::tss->esp0 = Global::currentThread->kernelStackPtrDefault;
// Set the current proc to valid
Global::currentProcValid = true;
}
namespace Timer {
using TimedEvent = xnoe::tuple<uint32_t, uint32_t, void(*)(frame_struct*, void*), void*>;
// counter, default count, function, argument, oneshot
using TimedEvent = xnoe::tuple<uint32_t, uint32_t, void(*)(frame_struct*, void*), void*, bool>;
xnoe::linkedlist<TimedEvent> timed_events;
void tick(frame_struct* frame) {
xnoe::linkedlistelem<TimedEvent>* current = timed_events.start;
@ -144,40 +152,61 @@ namespace Timer {
if (--count == 0) {
xnoe::get<2>(t)(frame, xnoe::get<3>(t));
count = xnoe::get<1>(t);
}
current->elem = TimedEvent(count, xnoe::get<1>(t), xnoe::get<2>(t), xnoe::get<3>(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 = current->next;
}
Global::milliseconds_elapsed++;
}
void register_event(uint32_t milliseconds, void(*function)(frame_struct*, 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(frame_struct* frame, Thread* t) {
t->state = Running;
}
void syscall(frame_struct* frame) {
// Syscall ABI:
// 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.
// 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.
// 8: getPID: returns the current process's PID (out eax: uint32_t)
// 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
// 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
// 12: bindToKeyboard :: void -> void // Binds the current process's stdout to the keyboard.
// 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.
// 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.
// 15: fopen :: char* path esi -> int filehandler // Returns a filehandler to the file.
// 16: fclose :: int filehandler esi -> void // Closes a file handler.
// 15: fopen :: char* path -> int filehandler // Returns a filehandler to the file.
// 16: fclose :: int filehandler -> void // Closes a file handler.
// 17: kill :: int PID esi -> void // Destroys a process.
// 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
// File handlers:
// 0: Stdout
@ -187,83 +216,81 @@ void syscall(frame_struct* 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:
case 0: // getDentsSize
rval = Global::kernel->rootfs->getDentsSize(createPathFromString(frame->ebx));
break;
case 1:
case 1: // getDents
Global::kernel->rootfs->getDents(createPathFromString(frame->ebx), frame->ecx);
break;
case 2:
case 2: // exists
rval = Global::kernel->rootfs->exists(createPathFromString(frame->ebx));
break;
case 3:
case 3: // type
rval = Global::kernel->rootfs->type(createPathFromString(frame->ebx));
break;
case 4:
rval = currentProc->allocate(esi);
case 4: // malloc
rval = currentProc->allocate(frame->ebx);
break;
case 5:
currentProc->deallocate(esi);
case 5: // free
currentProc->deallocate(frame->ebx);
break;
case 6:
case 6: // getMillisecondsElapsed
rval = Global::milliseconds_elapsed;
break;
case 7: {
case 7: { // exec
asm("cli");
Process* p = Global::kernel->createProcess(esi);
xnoe::maybe<ReadWriter*> file = Global::currentProc->getFH(frame->ebx);
if (file.is_ok()) {
Process* p = Global::kernel->createProcess(file.get());
rval = p->PID;
} else {
rval = 0;
}
asm("sti");
break;
}
case 8:
case 8: // getPID
rval = currentProc->PID;
break;
case 9:
case 9: // die
Global::kernel->PD->select();
// We can now safely delete the current process
Global::kernel->destroyProcess(Global::currentProc);
Global::currentProcValid = false;
context_switch(frame);
break;
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);
case 10: { // read
xnoe::maybe<ReadWriter*> fh = Global::currentProc->getFH(frame->ecx);
if (!fh.is_ok()) {
rval = 0;
break;
}
ReadWriter* rw = fh.get();
rval = rw->read(frame->ebx, edi);
}
rval = rw->read(frame->ebx, frame->edx);
break;
}
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);
case 11: { // write
xnoe::maybe<ReadWriter*> fh = Global::currentProc->getFH(frame->ecx);
if (!fh.is_ok()) {
rval = 0;
break;
}
ReadWriter* rw = fh.get();
rval = rw->write(frame->ebx, edi);
}
rval = rw->write(frame->ebx, frame->edx);
break;
}
case 12:
case 12: // bindToKeyboard
if (currentProc->stdin)
break;
@ -271,50 +298,51 @@ void syscall(frame_struct* frame) {
Global::kernel->KBListeners.append(currentProc);
break;
case 13: {
xnoe::Maybe<Process*> pm = Global::kernel->pid_map->get(esi);
case 13: { // bindStdout
xnoe::maybe<Process*> pm = Global::kernel->pid_map->get(frame->ebx);
if (!pm.is_ok())
break;
Process* p = pm.get();
if (!p->stdout) {
ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, esi);
ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, frame->ebx);
p->stdout = buffer;
rval = Global::kernel->mapFH(buffer);
rval = Global::currentProc->mapFH(buffer);
}
break;
}
case 14: {
xnoe::Maybe<Process*> pm = Global::kernel->pid_map->get(esi);
case 14: { // bindStdin
xnoe::maybe<Process*> pm = Global::kernel->pid_map->get(frame->ebx);
if (!pm.is_ok())
break;
Process* p = pm.get();
if (!p->stdin) {
ReadWriter* buffer = new CircularRWBuffer(esi, currentProc->PID);
ReadWriter* buffer = new CircularRWBuffer(frame->ebx, currentProc->PID);
p->stdin = buffer;
rval = Global::kernel->mapFH(buffer);
rval = Global::currentProc->mapFH(buffer);
}
break;
}
case 15: {
ReadWriter* file = new FATFileReadWriter(0, esi);
rval = Global::kernel->mapFH(file);
case 15: { // fopen
ReadWriter* file = Global::kernel->rootfs->open(createPathFromString(frame->ebx));
if (file)
rval = Global::currentProc->mapFH(file);
break;
}
case 16: {
xnoe::Maybe<ReadWriter*> f = Global::FH->get(esi);
case 16: { // fclose
xnoe::maybe<ReadWriter*> f = Global::currentProc->getFH(frame->ebx);
if (f.is_ok()) {
delete f.get();
Global::kernel->unmapFH(esi);
Global::currentProc->unmapFH(frame->ebx);
}
break;
}
case 17: {
case 17: { // kill
asm("cli");
xnoe::Maybe<Process*> p = Global::kernel->pid_map->get(esi);
xnoe::maybe<Process*> p = Global::kernel->pid_map->get(frame->ebx);
if (p.is_ok()) {
Process* proc = p.get();
Global::kernel->destroyProcess(proc);
@ -323,6 +351,43 @@ void syscall(frame_struct* frame) {
break;
}
case 18: { // sleep
Global::currentThread->state = Suspended;
Timer::register_event(frame->ebx, &awaken, (void*)Global::currentThread, true);
context_switch(frame);
break;
}
case 19: // getRemainingPages
rval = Global::kernel->phys->remainingPages;
break;
case 20: // getInitPages
rval = Global::kernel->phys->initPages;
break;
case 21: // getTerminalWidth
rval = Global::kernel->terminal->width;
break;
case 22: // getTerminalHeight
rval = 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();
//rval = proc->state;
}
break;
}
case 24: { // Spawn Thread
Thread* thread = new Thread(Global::currentProc);
thread->initKernelStack(frame->ebx, thread->stack);
Global::kernel->threads.append(thread);
break;
}
default:
break;
}
@ -330,6 +395,60 @@ void syscall(frame_struct* frame) {
frame->eax = rval;
}
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++);
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 = sp;
}
void init_idt() {
idt_desc desc = {.size = 256 * sizeof(GateEntry) - 1, .offset = (uint32_t)idt};
asm volatile("lidt %0" : : "m" (desc));
@ -340,7 +459,6 @@ 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;
@ -360,9 +478,9 @@ void init_idt() {
gates[29] = &handle_fault;
gates[30] = &handle_fault;
gates[31] = &handle_fault;
gates[127] = &syscall;
gates[128] = &syscall;
idt[127].privilege = 3;
idt[128].privilege = 3;
outb(0x20, 0x11);
outb(0xA0, 0x11);
@ -385,5 +503,6 @@ void init_idt() {
}
void enable_idt() {
gates[32] = &Timer::tick;
asm ("sti");
}

View File

@ -2,7 +2,6 @@
#define IDT_H
#include "types.h"
#include "screenstuff.h"
#include "global.h"
#include "kernel.h"
#include "gdt.h"
@ -29,9 +28,43 @@ struct __attribute__((packed)) frame_struct {
uint16_t cs;
uint16_t _ignored0;
uint32_t eflags;
uint32_t esp;
uint16_t ss;
uint16_t _ignored1;
};
struct __attribute__((packed)) v8086_frame_struct {
uint32_t new_cr3;
uint32_t new_esp;
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;
uint16_t es;
uint16_t _ignored2;
uint16_t ds;
uint16_t _ignored3;
uint16_t fs;
uint16_t _ignored4;
uint16_t gs;
uint16_t _ignored5;
};
extern void(*gates[256])(frame_struct*);
@ -57,4 +90,10 @@ struct __attribute__((packed)) idt_desc {
uint32_t offset;
};
void context_switch(frame_struct* frame);
void handle_fault(frame_struct* frame);
void syscall(frame_struct* frame);
void ignore_interrupt(frame_struct* frame);
void v86_monitor(v8086_frame_struct* frame);
#endif

View File

@ -19,3 +19,21 @@ 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,4 +11,17 @@ 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

@ -12,28 +12,26 @@ Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint
this->stack = stack;
this->lastFH = 8;
//this->processes.append(this);
}
void Kernel::init_kernel() {
this->pid_map = new xnoe::hashtable<uint32_t, Process*>();
Global::FH = new xnoe::hashtable<void*, ReadWriter*>();
this->globalISRStack = (new uint8_t[0x8000]) + 0x8000;
}
Process* Kernel::createProcess(uint32_t fh) {
Process* p = new Process(currentPID, this->PD, 0xc0000000, fh);
Process* Kernel::createProcess(ReadWriter* file) {
char* name = "test";
Process* p = new Process(currentPID, this->PD, 0xc0000000, file, 1, &name);
this->pid_map->set(currentPID, p);
currentPID++;
this->processes.append(p);
this->threads.append(p->threads.start->elem);
return p;
}
Process* Kernel::createProcess(uint32_t fh, ReadWriter* stdout) {
Process* p = this->createProcess(fh);
Process* Kernel::createProcess(ReadWriter* file, ReadWriter* stdout) {
Process* p = this->createProcess(file);
p->stdout = stdout;
return p;
}
@ -41,20 +39,69 @@ Process* Kernel::createProcess(uint32_t fh, ReadWriter* stdout) {
void Kernel::destroyProcess(Process* p) {
if (Global::currentProc == p)
Global::currentProcValid = false;
this->processes.remove(p);
xnoe::linkedlistelem<Thread*>* currentThread = p->threads.start;
while (currentThread) {
this->threads.remove(currentThread->elem);
currentThread = currentThread->next;
}
this->pid_map->remove(p->PID);
delete p;
}
int Kernel::mapFH(ReadWriter* fh) {
Global::FH->set(this->lastFH++, fh);
return this->lastFH - 1;
}
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
};
void Kernel::unmapFH(uint32_t fh) {
Global::FH->remove((void*)fh);
}
// 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);
//void Kernel::loadPrimaryStack() {
// asm volatile("mov %0, %%esp"::"m"(this->stack - 64));
//}
*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:");
}

View File

@ -5,6 +5,8 @@
#include "datatypes/hashtable.h"
#include "global.h"
#include "terminal.h"
#include "filesystem/fstree.h"
#include "gdt.h"
class Kernel : public Process {
private:
@ -20,17 +22,17 @@ public:
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(uint32_t fh);
Process* createProcess(uint32_t fh, ReadWriter* stdout);
Process* createProcess(ReadWriter* file);
Process* createProcess(ReadWriter* file, ReadWriter* stdout);
void destroyProcess(Process* p);
int mapFH(ReadWriter* fh);
void unmapFH(uint32_t fh);
//void loadPrimaryStack();
void v86(uint16_t ax, uint16_t bx, uint16_t cx, uint16_t es, uint16_t di, uint8_t intn);
};
#endif

View File

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

View File

@ -1,10 +1,9 @@
#include "types.h"
#include "screenstuff.h"
#include "io.h"
#include "idt.h"
#include "keyboard.h"
#include "strings.h"
#include "atapio.h"
#include "ata.h"
#include "gdt.h"
#include "paging.h"
#include "allocate.h"
@ -14,24 +13,36 @@
#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"
int main() {
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) {
init_gdt();
init_term();
PageDirectory kernel_pd = PageDirectory(0xc0100000, 0x120000, 0xbffe0000);
PageDirectory kernel_pd = PageDirectory(kstruct.pde, kstruct.page_directory_phys_addr, kstruct.page_directory_phys_offset);
kernel_pd.select();
kernel_pd.unmap(0x8000);
PageMap phys_pm(0xc0600000);
PageMap virt_pm(0xc0620000);
PageMap phys_pm(kstruct.page_bitmap_phys, kstruct.remainingPages);
PageMap virt_pm(kstruct.page_bitmap_virt);
Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, 0xc1006000);
Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, kstruct.stack_ptr);
kernel.init_kernel();
init_atapio();
VGAModeTerminal* term = new VGAModeTerminal(0xc07a0000);
VGAModeTerminal* term = new VGAModeTerminal(kstruct.vga_addr);
kernel.terminal = term;
@ -44,13 +55,19 @@ int main() {
term->printf("KERNEL OK!\n");
ReadWriter* worldbin = new FATFileReadWriter(0, "etc/world.bin");
uint32_t fh = kernel.mapFH(worldbin);
ReadWriter* atareadwriter = new ATAReadWriter(0, 0);
Process* p1 = kernel.createProcess(fh, term);
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* worldbin = kernel.rootfs->open(createPathFromString("/world.bin"));
Process* p1 = kernel.createProcess(worldbin, term);
Global::tss->esp0 = (new uint8_t[8192]) + 8192;
init_keyboard();
enable_idt();
while (1) asm ("hlt");

View File

@ -5,13 +5,14 @@ void memset(uint8_t* address, uint32_t count, uint8_t value) {
address[i] = value;
}
void memcpy(uint8_t* src, uint8_t* dst, uint32_t count) {
void memcpy(uint8_t* dst, uint8_t* src, uint32_t count) {
for (int i = 0; i<count; i++)
dst[i] = src[i];
}
PageMap::PageMap(uint32_t map) {
PageMap::PageMap(uint32_t map, uint32_t remainingPages) {
this->pagemap = (uint8_t*)map;
this->initPages = this->remainingPages = remainingPages;
}
PageMap::PageMap() {
@ -38,6 +39,8 @@ 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;
@ -46,20 +49,24 @@ 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) {
@ -91,6 +98,7 @@ PageTable::PageTable(uint32_t phys, uint32_t virt) {
virt_addr = virt;
page_table = (PTE*)virt;
valid = 1;
}
PageTable::PageTable(){
@ -100,6 +108,7 @@ PageTable::PageTable(){
phys_addr = (Global::allocator->virtual_to_physical(virt_addr)) >> 12;
page_table = (PTE*)virt_addr;
valid = 1;
}
PageTable::~PageTable() {
@ -149,7 +158,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);
}
}
@ -165,7 +174,7 @@ PageDirectory::PageDirectory() {
PageDirectory::~PageDirectory() {
for (int i=0; i<1024; i++)
if (page_tables[i].virt_addr)
if (page_tables[i].valid)
page_tables[i].~PageTable();
delete page_directory;
}
@ -173,8 +182,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].virt_addr)
new (page_tables + split->pd_index) PageTable();
if (!page_tables[split->pd_index].valid)
new (&page_tables[split->pd_index]) PageTable();
page_directory[split->pd_index] = (PDE){
.present = 1,

View File

@ -3,13 +3,12 @@
#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* src, uint8_t* dst, uint32_t count);
void memcpy(uint8_t* dst, uint8_t* src, uint32_t count);
class __attribute__((packed)) PageMap {
class PageMap {
private:
uint8_t* pagemap;
@ -19,7 +18,10 @@ private:
bool bit_set(uint32_t index);
public:
PageMap(uint32_t map);
uint32_t remainingPages;
uint32_t initPages;
PageMap(uint32_t map, uint32_t remainingPages=0x100000);
PageMap();
~PageMap();
@ -41,6 +43,8 @@ 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();
@ -78,12 +82,12 @@ public:
class Allocator {
protected:
static PageMap* phys;
PageMap* virt;
uint32_t virt_alloc_base;
uint8_t privilege;
public:
static PageMap* phys;
PageMap* virt;
PageDirectory* PD;
Allocator(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
@ -94,6 +98,8 @@ 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,7 +1,6 @@
#ifndef PAGING_H
#define PAGING_H
#include <stdbool.h>
#include "types.h"
struct __attribute__((packed)) split_addr {

View File

@ -4,16 +4,16 @@ extern void(*catchall_return)();
AllocTracker::AllocTracker(void* base, uint32_t size, uint32_t count) : page_base(base), page_size(size), alloc_count(count) {}
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>*>();
}
Process::Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base)
@ -21,7 +21,6 @@ Process::Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageM
this->PID = PID;
this->page_remaining = 0;
this->last_page_pointer = virt_alloc_base;
this->stack = stack;
}
Process::Process(uint32_t PID)
@ -29,46 +28,79 @@ Process::Process(uint32_t PID)
this->PID = PID;
this->page_remaining = 0;
this->last_page_pointer = 0;
this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x1000]) + 0x1000;
this->file_handlers = new xnoe::dynarray<ReadWriter*>(8);
}
Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uint32_t fh)
Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc, char** argv)
: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) {
this->stdout = 0;
this->stdin = 0;
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;
this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x1000]) + 0xffc;
this->kernelStackPtrDefault = this->kernelStackPtr;
Thread* thread = new Thread(this);
uint32_t pCR3;
asm ("mov %%cr3, %0" : "=a" (pCR3) :);
this->PD->select();
// We also need to initialise ESP and the stack
uint32_t* stack = thread->stack + 0x8000;
uint8_t* argenvarea = this->allocate(0x2000);
uint32_t argenv = argenvarea + 0x2000;
for (int i=argc; i>0; i--) {
char* s = argv[i-1];
uint32_t c = 0;
while (*(c++, s++));
memcpy((uint8_t*)(argenv -= c), (uint8_t*)argv[i-1], c);
*(--stack) = argenv;
}
*(--stack) = ((uint32_t)stack);
*(--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);
}
Thread::Thread(Process* parent) {
this->parent = parent;
this->stack = this->parent->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x4000]) + 0x4000;
this->kernelStackPtrDefault = 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();
uint32_t* stack32 = ((uint32_t)this->kernelStackPtr);
*(--stack32) = 0x23; // SS
*(--stack32) = ((uint32_t)this->stack + 0x8000); // ESP
*(--stack32) = ((uint32_t)esp); // ESP
*(--stack32) = 0x200; // EFLAGS
*(--stack32) = 27; // CS
*(--stack32) = (uint32_t)program_data; // EIP
*(--stack32) = ((uint32_t)this->stack + 0x8000); // EBP
*(--stack32) = (uint32_t)entryPoint; // EIP
*(--stack32) = ((uint32_t)esp); // EBP
uint32_t rEBP = stack32;
@ -82,12 +114,8 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uin
*(--stack32) = 0; // EDI
this->kernelStackPtr = stack32;
filereader->read(filesize, program_data);
asm ("mov %0, %%cr3" : : "r" (pCR3));
}
}
Process::~Process() {
uint32_t pCR3;
@ -98,13 +126,22 @@ Process::~Process() {
xnoe::linkedlistelem<AllocTracker>* active = next;
next = next->next;
//printf("Deleted %x\n", active->elem.page_base);
this->deallocate(active->elem.page_base+1);
this->deallocate(active->elem.page_base);
}
this->deallocate(stack);
asm ("mov %0, %%cr3" : : "r" (pCR3));
delete kernelStackPtr;
for (int i=0; i<file_handlers->length();i++) {
xnoe::maybe<ReadWriter*> r;
if ((r=file_handlers->get(i)).is_ok())
if (r.get())
delete r.get();
}
xnoe::linkedlistelem<Thread*>* currentThread = threads.start;
while (currentThread) {
delete currentThread->elem;
currentThread = currentThread->next;
}
}
void* Process::allocate(uint32_t size) {
@ -152,7 +189,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--;
@ -171,10 +208,41 @@ 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,11 +6,27 @@
#include "datatypes/linkedlist.h"
#include "datatypes/hashtable.h"
#include "datatypes/maybe.h"
#include "screenstuff.h"
#include "global.h"
#include "atapio.h"
#include "processstate.h"
#include "stdio/readwriter.h"
#include "datatypes/dynarray.h"
#include "filesystem/fstree.h"
class Process;
class Thread {
public:
void* stack;
void* kernelStackPtr;
void* kernelStackPtrDefault;
Process* parent;
ProcessState state;
bool firstRun;
Thread(Process* parent);
~Thread();
void Thread::initKernelStack(void* entryPoint, void* esp);
};
struct AllocTracker {
void* page_base;
@ -25,28 +41,27 @@ private:
uint32_t last_page_pointer;
uint32_t page_remaining;
void* stack;
// List of pages this process has allocated
xnoe::linkedlist<AllocTracker> allocations;
xnoe::Maybe<xnoe::linkedlistelem<AllocTracker>*> get_alloc_tracker(uint32_t address);
xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*> get_alloc_tracker(uint32_t address);
xnoe::dynarray<ReadWriter*>* file_handlers;
Path currentWorkingDirectory;
public:
uint32_t PID;
uint32_t esp;
void* kernelStackPtr;
void* kernelStackPtrDefault;
ReadWriter* stdout;
ReadWriter* stdin;
bool firstRun;
xnoe::linkedlist<Thread*> threads;
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(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc=0, char** argv=0);
~Process(); // Iterate through allocations and free those; delete stack
@ -54,6 +69,10 @@ public:
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

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

View File

@ -1,133 +0,0 @@
#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);
}

View File

@ -1,18 +0,0 @@
#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

8
src/kernel/spinlock.cpp Normal file
View File

@ -0,0 +1,8 @@
#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");
}

14
src/kernel/spinlock.h Normal file
View File

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

View File

@ -0,0 +1,26 @@
#include "oneshotreadwriter.h"
OneShotReadWriter::OneShotReadWriter(uint32_t owner, uint8_t* toRead) : ReadWriter(owner) {
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

@ -0,0 +1,22 @@
#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(uint32_t owner, 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

@ -14,6 +14,7 @@ void ReadWriter::giveWritePerm(uint32_t PID) {
uint32_t ReadWriter::read(uint32_t count, uint8_t* buffer){}
uint32_t ReadWriter::write(uint32_t count, uint8_t* buffer){}
uint32_t ReadWriter::seek(uint32_t position){}
uint32_t ReadWriter::size(){}
bool ReadWriter::canRead(uint32_t PID) {

View File

@ -18,6 +18,7 @@ public:
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();
bool canRead(uint32_t PID);
bool canWrite(uint32_t PID);

View File

@ -1,5 +1,11 @@
#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,8 +1,9 @@
#ifndef STRINGS_H
#define STRINGS_H
#include <stdbool.h>
#include "types.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,6 +1,18 @@
#include "terminal.h"
void Terminal::scroll_up() {
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++) {
// Scroll the entire buffer up.
for (int y = 0; y < (height * pages); y++) {
uint16_t* cline = buffer + y * width;
@ -12,19 +24,191 @@ void Terminal::scroll_up() {
// Clear the last line
uint16_t* last_line = buffer + (height * pages - 1) * width;
for (int x = 0; x < width; x++) {
last_line[x] = 0x0720;
last_line[x] = 0x0720; //| (edata << 8);
}
this->cur_y--;
}
this->update();
}
void Terminal::putchar(uint32_t ptr, uint8_t c, uint8_t edata) {
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++;
}
// All modifications to the screen are done to the last page.
last_page_pointer[ptr] = c | (edata<<8);
last_page_pointer[this->cur_y*this->width+this->cur_x] = c | (edata<<8);
if (active)
putchar_internal(ptr, c, edata);
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();
}
}
void Terminal::update(){}
@ -46,21 +230,19 @@ Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages)
this->active = false;
}
int strToInt(char* str) {
int r=0;
while (*str >= 0x30 && *str <= 0x39) {
r *= 10;
r += *(str++) - 0x30;
}
return r;
}
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 clamp(int a, int b, int c) {
if (a < b)
return b;
if (a > c)
return c;
return a;
this->cur_x = 0;
this->cur_y = 0;
this->active = false;
}
void Terminal::printf(const char* string, ...) {
@ -71,73 +253,6 @@ 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;
@ -159,22 +274,17 @@ 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(mem_pos, charred);
this->putchar(charred);
break;
}
}
continue;
}
if (current != '\n') {
int mem_pos = this->cur_y * this->width + this->cur_x++;
this->putchar(mem_pos, current);
}
this->putchar(current);
}
this->set_curpos(this->cur_x, this->cur_y);
@ -183,84 +293,8 @@ void Terminal::printf(const char* string, ...) {
}
uint32_t Terminal::write(uint32_t count, uint8_t* string) {
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);
}
}
for (int index=0; index < count; index++)
this->putchar(string[index]);
this->set_curpos(this->cur_x, this->cur_y);
}
@ -330,10 +364,29 @@ 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]), 0);
putchar_internal(y * width + x, (uint8_t)(current_page_pointer[y * width + x]), (uint8_t)(current_page_pointer[y * width + x]>>8));
}
}
}
@ -353,15 +406,12 @@ 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++) {
//for (int x=0; x<8; x++) {
put_pixels_byte(sx, sy+y, 15, char_data[y]);
//}
}
for (int y=0; y<8; y++)
put_pixels_byte(sx, sy+y, edata, 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 * 720 + x;
uint32_t pixel = y * pixelWidth + x;
uint32_t pixelindex = pixel / 8;
uint8_t trbyte = 0;
@ -371,17 +421,18 @@ void VGAModeTerminal::put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uin
}
for (int i=0; i<4; i++) {
if (color & (1<<i))
this->planes[i][pixelindex] = trbyte;
else
this->planes[i][pixelindex] = 0;
if (color & (1<<i))
this->planes[i][pixelindex] |= trbyte;
if ((color>>4) & (1<<i))
this->planes[i][pixelindex] |= ~trbyte;
}
}
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 * 720 + x;
uint32_t pixel = y * pixelWidth + x;
uint32_t pixelindex = pixel / 8;
uint32_t pixelbitindex = pixel % 8;
@ -394,7 +445,7 @@ void VGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) {
}
static void VGAModeTerminal::bufferToVRAM(frame_struct* frame, VGAModeTerminal* terminal) {
uint32_t count4 = (720 * 480) / 8 / 4;
uint32_t count4 = (terminal->pixelWidth * terminal->pixelHeight) / 8 / 4;
for (int i=0; i<4; i++) {
outb(0x3c4, 2);
outb(0x3c5, 1<<i);
@ -405,28 +456,25 @@ static void VGAModeTerminal::bufferToVRAM(frame_struct* frame, VGAModeTerminal*
}
}
VGAModeTerminal::VGAModeTerminal(uint8_t* vga_pointer): Terminal(90, 60, 1) {
VGAModeTerminal::VGAModeTerminal(uint8_t* vga_pointer): Terminal(0, 0, 1) {
this->vga_pointer = vga_pointer;
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,
@ -480,3 +528,84 @@ VGAModeTerminal::VGAModeTerminal(uint8_t* vga_pointer): Terminal(90, 60, 1) {
Timer::register_event(16, &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];
}
static void BGAModeTerminal::bufferToVRAM(frame_struct* frame, BGAModeTerminal* terminal) {
uint32_t c = terminal->pixelWidth * terminal->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*)terminal->vga_pointer)[i%16384] = ((uint32_t*)terminal->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, &BGAModeTerminal::bufferToVRAM, this);
}

View File

@ -14,23 +14,38 @@
struct frame_struct;
namespace Timer {
void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary);
void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary, bool oneshot=false);
}
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=0x07);
virtual void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata);
void scroll_up();
void scroll_up(uint32_t count=1);
void scroll_down(uint32_t count=1);
void putchar(uint32_t ptr, uint8_t c, uint8_t edata=0x07);
void putchar(uint8_t c);
TerminalState state = None;
uint8_t parameterBytes[128];
uint8_t intermediaryBytes[128];
uint32_t parameterIndex = 0;
uint32_t intermediaryIndex = 0;
protected:
uint16_t* buffer;
uint32_t width;
uint32_t height;
uint32_t pages;
uint32_t cur_x;
@ -40,7 +55,14 @@ 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, ...);
@ -62,19 +84,18 @@ class TextModeTerminal : public Terminal {
private:
void update() override;
void update_cur() override;
void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata=0x07) override;
void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) 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=0x07) 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);
@ -82,9 +103,33 @@ private:
static void bufferToVRAM(frame_struct* frame, VGAModeTerminal* terminal);
public:
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);
static void bufferToVRAM(frame_struct* frame, BGAModeTerminal* terminal);
public:
uint32_t pixelWidth = 720;
uint32_t pixelHeight = 480;
uint8_t* vga_pointer;
uint32_t* fb;
BGAModeTerminal(uint8_t* vga_pointer);
};
#endif

View File

@ -1,20 +0,0 @@
#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);
}

View File

@ -1,14 +0,0 @@
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

@ -0,0 +1,4 @@
int main() {
// Cause a Division by zero by trying to divide by zero.
int x = 1 / 0;
}

8
src/programs/entry.asm Normal file
View File

@ -0,0 +1,8 @@
[BITS 32]
_start:
call main
call die
extern die
extern main

View File

@ -1,4 +1,4 @@
#include "../common/common.h"
#include "common/common.h"
void readline(int count, char* buffer) {
int index = 0;
@ -25,7 +25,9 @@ void readline(int count, char* buffer) {
print("\n");
}
int main() {
int main(int argc, char** argv) {
printf("Hi, I am %s, running with PID %d!\n", argv[0], getPID());
print("Hello, World!\n");
char buffer[32];
while (1) {

View File

@ -0,0 +1,16 @@
#include "common/common.h"
int main() {
uint32_t crashBin = fopen("/crash.bin");
uint32_t pid = getPID();
while (1) {
printf("Time Elapsed: %dms\n", getMillisecondsElapsed());
printf("Init. Pages: %d\nRemaining Pages: %d\n", getInitPages(), getRemainingPages());
printf("PID 2 State: %s\n", (!getProcessState(2))?"Running":"Suspended");
printf("I am PID %d\n", pid);
//exec(crashBin);
sleep(1000);
}
}

11
src/programs/userspace.ld Normal file
View File

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

View File

@ -1,4 +1,4 @@
#include "../common/common.h"
#include "common/common.h"
#include <stdbool.h>
typedef struct {
@ -8,15 +8,17 @@ typedef struct {
uint32_t process;
uint32_t stdin;
uint32_t stdout;
uint32_t width;
uint32_t height;
} 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];
void scrollBuffer(procbuffer* buf) {
for (int y=0; y<buf->height; y++)
for (int x=0; x<buf->width; x++)
if (y != buf->height-1)
buf->buffer[y*buf->width+x] = buf->buffer[(y+1)*buf->width+x];
else
buf[y*43+x] = ' ';
buf->buffer[y*buf->width+x] = ' ';
}
void writeToBuf(char c, procbuffer* buf) {
@ -30,22 +32,22 @@ void writeToBuf(char c, procbuffer* buf) {
if (buf->x > 0)
buf->x--;
else if (buf->y > 0) {
buf->x = 42;
buf->x = buf->width-1;
buf->y--;
}
buf->buffer[buf->y*43+buf->x] = ' ';
buf->buffer[buf->y*buf->width+buf->x] = ' ';
break;
default:
buf->buffer[buf->y*43+buf->x++] = c;
buf->buffer[buf->y*buf->width+buf->x++] = c;
}
if (buf->x == 43) {
if (buf->x == buf->width) {
buf->x = 0;
buf->y++;
}
if (buf->y == 56) {
if (buf->y == buf->height) {
buf->y--;
scrollBuffer(buf->buffer);
scrollBuffer(buf);
}
}
@ -56,7 +58,7 @@ void writeCountToBuf(int count, char* c, procbuffer* buf) {
}
void clearBuf(procbuffer* buf) {
for (int i=0; i<56*43;i++) {
for (int i=0; i<buf->height*buf->width;i++) {
buf->buffer[i] = ' ';
}
buf->x = 0;
@ -69,52 +71,42 @@ void writeStrToBuf(char* c, procbuffer* b) {
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";
char pset[11] = "\x1b[000;000H";
for (int i=0; i<y;i++) {
pset[4]++;
if (pset[4] == 0x3a) {
pset[4] = 0x30;
pset[3]++;
}
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<x;i++) {
pset[8]++;
if (pset[8] == 0x3a) {
pset[8] = 0x30;
pset[7]++;
}
if (pset[7] == 0x3a) {
pset[7] = 0x30;
pset[6]++;
if (pset[6] == 0x3a) {
pset[6] = 0x30;
pset[5]++;
}
}
print(pset);
}
void displayBuf(procbuffer* b, int dx, int dy) {
print("\x1b[42;36;1m");
char pset[9] = "\x1b[000;000H";
for (int i=0; i<b->height; i++) {
setCurPos(dx, dy++);
write(b->width, 0, b->buffer+(b->width*i));
}
}
void readline(int count, char* buffer) {
int index = 0;
char c;
@ -159,7 +151,40 @@ bool strcmpcnt(int count, char* a, char* b) {
return true;
}
procbuffer b1;
procbuffer b2;
int bufferWidth;
void displayBuffer1() {
char c[128];
int succ=0;
while (1) {
if (b1.process)
if (succ = read(128, b1.stdout, c))
writeCountToBuf(succ, c, &b1);
displayBuf(&b1, 2, 2);
}
}
void displayBuffer2() {
char c[128];
int succ=0;
while (1) {
if (b2.process)
if (succ = read(128, b2.stdout, c))
writeCountToBuf(succ, c, &b2);
displayBuf(&b2, bufferWidth+4, 2);
}
}
int main() {
int width = getCurrentTerminalWidth();
int height = getCurrentTerminalHeight();
bufferWidth = (width - 4) / 2;
int bufferHeight = (height - 4);
bindToKeyboard();
char space = ' ';
@ -169,48 +194,65 @@ int main() {
for (int i=0; i < 1000; i++)
write(1, 0, &space);
print("\x1b[1;1H");
print("\x1b[45;33;1m");
char* mid = "+ ++ +";
char* bottom = "+ +";
for (int i=0; i<90;i++)
for (int i=0; i<width;i++)
write(1, 0, &plus);
for (int i=0; i<56;i++)
write(90, 0, mid);
for (int i=0; i<90;i++)
for (int i=0; i<bufferHeight;i++) {
write(1, 0, &plus);
write(90, 0, bottom);
for (int i=0; i<90;i++)
for (int j=0; j<bufferWidth; j++)
write(1, 0, &space);
write(1, 0, &plus);
write(1, 0, &plus);
for (int j=0; j<bufferWidth; j++)
write(1, 0, &space);
write(1, 0, &plus);
}
for (int i=0; i<width;i++)
write(1, 0, &plus);
write(1, 0, &plus);
for (int i=0; i< width - 2; i++)
write(1, 0, &space);
write(1, 0, &plus);
for (int i=0; i<width;i++)
write(1, 0, &plus);
uint32_t program = fopen("hello.bin");
uint32_t p1 = fork(program);
uint32_t program = fopen("/hello.bin");
uint32_t p1 = exec(program);
uint32_t p1out = bindStdout(p1);
uint32_t p1in = bindStdin(p1);
fclose(program);
program = fopen("hello.bin");
uint32_t p2 = fork(program);
program = fopen("/timer.bin");
uint32_t p2 = exec(program);
uint32_t p2out = bindStdout(p2);
uint32_t p2in = bindStdin(p2);
fclose(program);
procbuffer b1 = {
.buffer = localalloc(56 * 43),
b1 = (procbuffer) {
.buffer = malloc(bufferWidth * bufferHeight),
.x = 0,
.y = 0,
.process = p1,
.stdin = p1in,
.stdout = p1out
.stdout = p1out,
.width = bufferWidth,
.height = bufferHeight
};
procbuffer b2 = {
.buffer = localalloc(56 * 43),
b2 = (procbuffer) {
.buffer = malloc(bufferWidth * bufferHeight),
.x = 0,
.y = 0,
.process = p2,
.stdin = p2in,
.stdout = p2out
.stdout = p2out,
.width = bufferWidth,
.height = bufferHeight
};
spawnThread(&displayBuffer1);
spawnThread(&displayBuffer2);
procbuffer* selectedBuf = &b1;
writeStrToBuf("XoSH (XOS SHell) v0.0.1\nPress : to use commands.\n :help for help.\n", &b1);
@ -218,18 +260,16 @@ int main() {
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("\x1b[45;33;1m");
setCurPos(2, height-1);
print(": ");
print("\x1b[59;3H");
setCurPos(3, height-1);
readline(32, buf);
if (strcmpcnt(6, buf, "switch")) {
if (selectedBuf == &b1) {
@ -247,6 +287,13 @@ int main() {
writeStrToBuf(" Kills the current process\n", selectedBuf);
writeStrToBuf(":load <filename>\n", selectedBuf);
writeStrToBuf(" Loads and executes the program <filename>\n", selectedBuf);
writeStrToBuf(":ls <path>\n", selectedBuf);
writeStrToBuf(" Lists the files in directory <path>\n", selectedBuf);
writeStrToBuf(":clear\n", selectedBuf);
writeStrToBuf(" Clears the buffer\n", selectedBuf);
writeStrToBuf(":type <filename>\n", selectedBuf);
writeStrToBuf(" Writes out the contents of the file <filename>\n", selectedBuf);
writeStrToBuf("--------\n", selectedBuf);
} else if (strcmpcnt(4, buf, "kill")) {
if (selectedBuf->process) {
@ -255,29 +302,39 @@ int main() {
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->process = exec(fh);
selectedBuf->stdout = bindStdout(selectedBuf->process);
selectedBuf->stdin = bindStdin(selectedBuf->process);
fclose(fh);
}
} else if (strcmpcnt(2, buf, "ls")) {
uint32_t size = getDentsSize((char*)(buf+3));
FSDirectoryListing* listing = (FSDirectoryListing*)malloc(size);
getDents((char*)(buf+3), listing);
writeStrToBuf("\n", selectedBuf);
for (int i=0; i<listing->count; i++) {
writeCountToBuf(listing->entries[i].path.length, listing->entries[i].path.path, selectedBuf);
writeStrToBuf("\n", selectedBuf);
}
free(listing);
} else if (strcmpcnt(5, buf, "clear")) {
clearBuf(selectedBuf);
} else if (strcmpcnt(4, buf, "type")) {
uint32_t f = fopen(buf+5);
char c;
while (read(1, f, &c))
writeCountToBuf(1, &c, selectedBuf);
fclose(f);
}
} else {
if (selectedBuf->process)
write(1, selectedBuf->stdin, c);
}
}
displayBuf(&b1, 2, 2);
displayBuf(&b2, 47, 2);
}
}

View File

@ -1,14 +0,0 @@
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)
}
}