diff --git a/.gitignore b/.gitignore index 6827c05..ee3f05e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ blankos.iso iso/ i386-elf-7.5.0-Linux-x86_64/ i386-elf-7.5.0-Linux-x86_64.tar.xz +src/initrd/*.bin diff --git a/docs/DEVELOPERS.md b/docs/DEVELOPERS.md index 045ccdc..262ed34 100644 --- a/docs/DEVELOPERS.md +++ b/docs/DEVELOPERS.md @@ -42,6 +42,8 @@ sudo qemu-system-i386 -drive if=pflash,format=raw,readonly=on,file=/usr/share/OV Be warned, these are not actual programs in the sense you'd expect. These are indeed functions that are called from the shell, and embedded in the kernel ELF binary. Real programs apart from the kernel are not yet a thing here, but might be one day. +(Now, there is a 'beginning' of something that we could call real programs, but I still suck at making the syscalls work. One day, one day...) + ### Step 1 - Making the program and the entry point To make a program for the OS, first create the appropriate C source file and header file in the `src/programs` subfolder. Name it appropriately, for example `myprogram.c`. diff --git a/docs/USERS.md b/docs/USERS.md index a0fe44e..554c431 100644 --- a/docs/USERS.md +++ b/docs/USERS.md @@ -143,3 +143,7 @@ Starts a simplified and buggy snake game. You can choose the speed by setting th Controls: - `q` to quit - `wasd` to move + +#### `exec ` + +Executes a binary file. Warning: this is highly broken and syscalls aren't working. It's written in a childish manner. Help is always appreciated (lol). diff --git a/makefile b/makefile index c6eb216..a7d9edf 100644 --- a/makefile +++ b/makefile @@ -1,22 +1,27 @@ CC = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-gcc -CFLAGS = -ffreestanding -g -Wall -Wextra -Wno-builtin-declaration-mismatch -mno-sse -mno-mmx -mno-avx -march=i386 -c -I src/ +CFLAGS = -ffreestanding -g -Wall -Wextra -mno-sse -mno-mmx -mno-avx -march=i386 -c -I src/ +LD = ld LDFLAGS = -T link.ld -melf_i386 AS = nasm ASFLAGS = -f elf +AR = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-ar SRC_DIR = src KERNEL_DIR = $(SRC_DIR)/kernel LIBC_DIR = $(SRC_DIR)/libc -PROGRAMS_DIR = $(SRC_DIR)/programs +UTILS_DIR = $(SRC_DIR)/utils DRIVERS_DIR = $(SRC_DIR)/drivers +PROGRAMS_DIR = $(SRC_DIR)/programs INCLUDE_DIR = include FONTS_DIR = $(INCLUDE_DIR)/fonts OBJ_DIR = build -C_SOURCES = $(wildcard $(KERNEL_DIR)/*.c) $(wildcard $(LIBC_DIR)/*.c) $(wildcard $(PROGRAMS_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c) -ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(LIBC_DIR)/*.s) $(wildcard $(PROGRAMS_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s) +C_SOURCES = $(wildcard $(KERNEL_DIR)/*.c) $(wildcard $(LIBC_DIR)/*.c) $(wildcard $(UTILS_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c) +ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(LIBC_DIR)/*.s) $(wildcard $(UTILS_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s) +PROGRAM_SOURCES = $(wildcard $(PROGRAMS_DIR)/*.c) OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o)) +PROGRAM_OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(PROGRAM_SOURCES:.c=.o)) TOOLCHAIN_SRC = https://newos.org/toolchains/i386-elf-7.5.0-Linux-x86_64.tar.xz TOOLCHAIN_FILE = i386-elf-7.5.0-Linux-x86_64.tar.xz @@ -24,14 +29,21 @@ TOOLCHAIN_FILE = i386-elf-7.5.0-Linux-x86_64.tar.xz FONT_OBJ = $(OBJ_DIR)/fonts/UniCyr_8x16.o FONT_SRC = $(FONTS_DIR)/UniCyr_8x16.psf -all: $(OBJ_DIR) kernel.elf +all: $(OBJ_DIR) kernel.elf programs $(OBJ_DIR): mkdir -p $(OBJ_DIR) - mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/programs $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts - + mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/utils $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts $(OBJ_DIR)/programs + kernel.elf: $(OBJECTS) $(FONT_OBJ) - ld $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf + $(LD) $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf + +programs: $(PROGRAM_OBJECTS) + @mkdir -p $(SRC_DIR)/initrd + @for prog in $(PROGRAM_OBJECTS); do \ + base=$$(basename $$prog .o); \ + $(LD) -melf_i386 -T program.ld $$prog -o $(SRC_DIR)/initrd/$$base.bin; \ + done $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(CC) $(CFLAGS) $< -o $@ @@ -66,5 +78,5 @@ debug: ./debug.sh clean: - rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE) + rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE) $(SRC_DIR)/initrd/*.bin diff --git a/program.ld b/program.ld new file mode 100644 index 0000000..dc36352 --- /dev/null +++ b/program.ld @@ -0,0 +1,10 @@ +OUTPUT_FORMAT(binary) +ENTRY(main) + +SECTIONS +{ + . = 0x1000; + .text : { *(.text*) } + .data : { *(.data*) } + .bss : { *(.bss*) } +} diff --git a/src/kernel/initrd.c b/src/kernel/initrd.c index f1dcf96..9aa36bc 100644 --- a/src/kernel/initrd.c +++ b/src/kernel/initrd.c @@ -8,6 +8,7 @@ #include "../libc/string.h" #include "initrd.h" #include "system.h" +#include "kheap.h" static unsigned int octal_to_int(const char* str, size_t size) { @@ -31,6 +32,18 @@ uint32_t tar_parse_size(const char* in) return size; } +uint32_t tar_get_size(tar_header_t* header) +{ + uint32_t size = 0; + char* size_str = header->size; + + for (int i=0; i<11 && size_str[i] != '\0'; i++) + { + size = size*8 + (size_str[i]-'0'); + } + return size; +} + void tar_find_file(uint8_t *tar_start, const char* filename) { uint8_t *ptr = tar_start; @@ -186,3 +199,52 @@ uint32_t tar_get_file_size(uint8_t* initrd, const char* filename) } return -1; } + +tar_header_t* tar_find(uint8_t* initrd, const char* filename) +{ + tar_header_t* header = (tar_header_t*)initrd; + while (header->filename[0] != '\0') + { + if (strcmp(header->filename, filename) == 0) + { + return header; + } + + uint32_t file_size = tar_get_size(header); + uint32_t file_blocks = (file_size + 511)/512; + header = (tar_header_t*) ((uintptr_t)header+(file_blocks+1)*512); + } + + return NULL; +} + +void* tar_get_file_content(tar_header_t* header) +{ + return (void*) ((uintptr_t)header+512); +} + +void* load_file_from_initrd(uint8_t* initrd, const char* filename) +{ + tar_header_t* file = tar_find(initrd, filename); + if (file == NULL) + { + printf("'%s' not found\n", filename); + return NULL; + } + + uint32_t file_size = tar_get_size(file); + + void* file_data = malloc(file_size); + if (file_data == NULL) + { + printf("Malloc error for file '%s'\n", filename); + return NULL; + } + + void* file_content = tar_get_file_content(file); + memcpy(file_data, file_content, file_size); + + printf("[initrd] Loaded '%s' at 0x%x, size=%u\n", filename, (unsigned int)file_data, file_size); + + return file_data; +} diff --git a/src/kernel/initrd.h b/src/kernel/initrd.h index 714bf84..3772153 100644 --- a/src/kernel/initrd.h +++ b/src/kernel/initrd.h @@ -35,5 +35,6 @@ void ls_initrd(uint8_t* initrd, int verbose); void cat_initrd(uint8_t* initrd, const char* filename); int tar_file_to_buffer(uint8_t* initrd, const char* filename, char* buffer); uint32_t tar_get_file_size(uint8_t* initrd, const char* filename); +void* load_file_from_initrd(uint8_t* initrd, const char* filename); #endif diff --git a/src/kernel/irq.c b/src/kernel/irq.c index 05f6f6f..baa117a 100644 --- a/src/kernel/irq.c +++ b/src/kernel/irq.c @@ -25,6 +25,8 @@ extern void irq13(); extern void irq14(); extern void irq15(); +extern void syscall_common_stub(); + void *irq_routines[16] = { 0, 0, 0, 0, 0, 0, 0, 0, @@ -76,6 +78,8 @@ void irq_install() idt_set_gate(46, (unsigned)irq14, 0x08, 0x8E); idt_set_gate(47, (unsigned)irq15, 0x08, 0x8E); printf("[kernel] installed irq 0-15\n"); + + idt_set_gate(0x80, (unsigned long)syscall_common_stub, 0x08, 0x8E); } void irq_handler(struct regs *r) diff --git a/src/kernel/kheap.c b/src/kernel/kheap.c index d845103..888ed1d 100644 --- a/src/kernel/kheap.c +++ b/src/kernel/kheap.c @@ -6,6 +6,7 @@ #include "kheap.h" #include #include "system.h" +#include "../libc/stdio.h" // Free list allocator @@ -17,6 +18,7 @@ void init_alloc() free_list = (block_t*)heap; free_list->size = HEAP_SIZE-sizeof(block_t); free_list->next = NULL; + printf("[kernel] initialized heap and allocator, start=0x%x\n", heap); } void* malloc(size_t size) diff --git a/src/kernel/kheap.h b/src/kernel/kheap.h index 8aba820..f41fa37 100644 --- a/src/kernel/kheap.h +++ b/src/kernel/kheap.h @@ -17,7 +17,6 @@ typedef struct block #define HEAP_SIZE 1024*1024 // 1MB malloc-able - void init_alloc(); void* malloc(size_t size); void free(void* ptr); diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index 26b0367..45a1820 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -15,7 +15,7 @@ #include "multiboot2.h" #include "kheap.h" #include "initrd.h" -#include "../programs/programs.h" +#include "../utils/utils.h" #include "../libc/crypto.h" void kmain(multiboot2_info *mb_info) @@ -78,14 +78,14 @@ void kmain(multiboot2_info *mb_info) if (mmap->addr != 0) { - + /* serial_printf(3, "base addr=0x%x%x, length=0x%x%x, type=%u", (uint32_t) (mmap->addr >> 32), (uint32_t) (mmap->addr & 0xFFFFFFFF), (uint32_t) (mmap->len >> 32), (uint32_t) (mmap->len & 0xFFFFFFFF), mmap->type); - + */ } mmap = (struct multiboot_mmap_entry*) ((uint8_t*)mmap + mmap_tag->entry_size); @@ -118,6 +118,8 @@ void kmain(multiboot2_info *mb_info) printf("[debug] malloc test ptr1=0x%x, ptr2=0x%x\n", (unsigned int)ptr1, (unsigned int)ptr2); free(ptr1); free(ptr2); + // usually the place where i do testing + timer_install(); keyboard_install(); printf("[kernel] spawning shell...\n"); diff --git a/src/kernel/loader.s b/src/kernel/loader.s index 11d8aeb..1029284 100644 --- a/src/kernel/loader.s +++ b/src/kernel/loader.s @@ -210,8 +210,39 @@ irq_common_stub: add esp, 8 iret +; we'll be placing the syscall_common_stub here. +; push everything, then call syscall_handler (be sure to define it extern) +; then pop back everything and iret +extern syscall_handler + +global syscall_common_stub +syscall_common_stub: + pusha + push ds + push es + push fs + push gs + + mov eax, ds + push eax ; save ds + mov ax, 0x01 ; kernel segment YES I CHEATED I KNOW THIS SUCKS + mov ds, ax + mov es, ax + + call syscall_handler + + pop eax + mov ds, eax ; restore ds + + pop gs + pop fs + pop es + pop ds + popa + iret + section .bss align 4 -resb KERNEL_STACK_SIZE kernel_stack: + resb KERNEL_STACK_SIZE diff --git a/src/kernel/shell.c b/src/kernel/shell.c index 10ec05e..febd98c 100644 --- a/src/kernel/shell.c +++ b/src/kernel/shell.c @@ -6,7 +6,7 @@ #include "system.h" #include "../libc/stdio.h" #include "../libc/string.h" -#include "../programs/programs.h" +#include "../utils/utils.h" #include "../libc/crypto.h" #include #include "../drivers/rtc.h" @@ -146,6 +146,7 @@ void shell_install() register_command("lspci", program_lspci); register_command("naval", program_navalbattle); register_command("snake", program_snake); + register_command("exec", program_exec); for (;;) { diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c new file mode 100644 index 0000000..aac4650 --- /dev/null +++ b/src/kernel/syscalls.c @@ -0,0 +1,33 @@ +// System calls +// Author: xamidev +// Licensed under the Unlicense. See the repo below. +// https://github.com/xamidev/blankos + +#include "../libc/stdio.h" + +void handle_syscall(int syscall_number) +{ + switch(syscall_number) + { + case 1: + puts("Here's the syscall 1\n"); + break; + default: + printf("[error] Invalid syscall number '%d'!\n", syscall_number); + break; + } +} + +void syscall_handler() +{ + int syscall_number; + void* arg; + // mov eax, syscall_number + // mov ebx, arg + asm volatile("mov %%eax, %0" : "=r"(syscall_number)); + asm volatile("mov %%ebx, %0" : "=r"(arg)); + + printf("[syscall] syscall_number=%d, arg=%p\n", syscall_number, arg); + + handle_syscall(syscall_number); +} diff --git a/src/kernel/system.h b/src/kernel/system.h index 240f208..966d72b 100644 --- a/src/kernel/system.h +++ b/src/kernel/system.h @@ -39,5 +39,7 @@ extern volatile unsigned long global_ticks; extern unsigned int g_multiboot_info_address; +void syscall_handler(); + #endif diff --git a/src/programs/hello.c b/src/programs/hello.c new file mode 100644 index 0000000..af3a85f --- /dev/null +++ b/src/programs/hello.c @@ -0,0 +1,10 @@ +void user_syscall(int syscall_no) { + asm volatile ("mov %0, %%eax" : : "r"(syscall_no)); + asm volatile ("int $0x80"); +} + +void main() +{ + user_syscall(1); + return; +} diff --git a/src/programs/bf.c b/src/utils/bf.c similarity index 100% rename from src/programs/bf.c rename to src/utils/bf.c diff --git a/src/programs/bmp.c b/src/utils/bmp.c similarity index 100% rename from src/programs/bmp.c rename to src/utils/bmp.c diff --git a/src/programs/ciphers.c b/src/utils/ciphers.c similarity index 100% rename from src/programs/ciphers.c rename to src/utils/ciphers.c diff --git a/src/programs/ciphers.h b/src/utils/ciphers.h similarity index 100% rename from src/programs/ciphers.h rename to src/utils/ciphers.h diff --git a/src/programs/conway.c b/src/utils/conway.c similarity index 100% rename from src/programs/conway.c rename to src/utils/conway.c diff --git a/src/programs/conway.h b/src/utils/conway.h similarity index 100% rename from src/programs/conway.h rename to src/utils/conway.h diff --git a/src/programs/cowsay.c b/src/utils/cowsay.c similarity index 100% rename from src/programs/cowsay.c rename to src/utils/cowsay.c diff --git a/src/programs/fs.c b/src/utils/fs.c similarity index 100% rename from src/programs/fs.c rename to src/utils/fs.c diff --git a/src/programs/math.c b/src/utils/math.c similarity index 100% rename from src/programs/math.c rename to src/utils/math.c diff --git a/src/programs/misc.c b/src/utils/misc.c similarity index 83% rename from src/programs/misc.c rename to src/utils/misc.c index c8f364d..717ff31 100644 --- a/src/programs/misc.c +++ b/src/utils/misc.c @@ -11,6 +11,8 @@ #include "../drivers/rtc.h" #include "../kernel/io.h" #include "../drivers/pci.h" +#include "../kernel/initrd.h" +#include "../kernel/kmain.h" // Print a rainbow colorful text for testing @@ -74,7 +76,7 @@ void program_uptime() void program_help() { - printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\t lspci\t naval\nsnake\n"); + printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\t lspci\t naval\nsnake exec\n"); } // Panic @@ -133,7 +135,7 @@ void program_read(int argc, char* argv[]) } } -// Reboots the machine (might just shutdown) +// Reboots the machine (might just shutdown) (or do nothing if youre lucky) void program_reboot() { @@ -151,3 +153,24 @@ void program_lspci() { scan_pci_bus(); } + +// Executes binary file + +void program_exec(int argc, char* argv[]) +{ + if (argc < 2) + { + puts("Usage: exec \n"); + return; + } + void* binary_file = load_file_from_initrd((uint8_t*)initrd_addr, argv[1]); + + if (binary_file == NULL) + { + printf("[exec] Failed to load program '%s'.\n", argv[1]); + return; + } + + void (*program_entry)() = (void (*)())binary_file; + program_entry(); +} diff --git a/src/programs/navalbattle.c b/src/utils/navalbattle.c similarity index 100% rename from src/programs/navalbattle.c rename to src/utils/navalbattle.c diff --git a/src/programs/navalbattle.h b/src/utils/navalbattle.h similarity index 100% rename from src/programs/navalbattle.h rename to src/utils/navalbattle.h diff --git a/src/programs/pi.c b/src/utils/pi.c similarity index 100% rename from src/programs/pi.c rename to src/utils/pi.c diff --git a/src/programs/primes.c b/src/utils/primes.c similarity index 100% rename from src/programs/primes.c rename to src/utils/primes.c diff --git a/src/programs/snake.c b/src/utils/snake.c similarity index 100% rename from src/programs/snake.c rename to src/utils/snake.c diff --git a/src/programs/sysinfo.c b/src/utils/sysinfo.c similarity index 100% rename from src/programs/sysinfo.c rename to src/utils/sysinfo.c diff --git a/src/utils/uhex.c b/src/utils/uhex.c new file mode 100644 index 0000000..f47be49 --- /dev/null +++ b/src/utils/uhex.c @@ -0,0 +1,72 @@ +// uhex (microhex) port for BlankOS; read-only version +// Author: xamidev +// Licensed under the Unlicense. See the repo below. +// https://github.com/xamidev/blankos + +// This version is the port of a hex viewer which already was not great, +// and now by being here it is even worse because it is RO and will have +// hardcoded stuff in it (no ioctl, STDOUT, or other stuff here...) + +/* + +#define BYTES 1024 +#define round(x) (int)(x < 0 ? (x -0.5) : x + 0.5) + +// WIP: pushed but not done yet + +void print_hex(unsigned char* buf, int byteno, int pos, int BYTES_PER_LINE) +{ + for (int i=0; i\nInline commands:\n\tpX - print position X\n\teX - edit position X\n\tq - quit\n"); + return; + } + + int BYTES_PER_LINE = 20; + + + +} + +*/ diff --git a/src/programs/programs.h b/src/utils/utils.h similarity index 91% rename from src/programs/programs.h rename to src/utils/utils.h index 097900f..419974f 100644 --- a/src/programs/programs.h +++ b/src/utils/utils.h @@ -3,8 +3,8 @@ // Licensed under the Unlicense. See the repo below. // https://github.com/xamidev/blankos -#ifndef PROGRAMS_H -#define PROGRAMS_H +#ifndef UTILS_H +#define UTILS_H void program_words(); void program_primes(); @@ -45,4 +45,7 @@ void program_navalbattle(); void program_conway(); void program_snake(); +// Binaries loading and execution +void program_exec(); + #endif diff --git a/src/programs/words.c b/src/utils/words.c similarity index 100% rename from src/programs/words.c rename to src/utils/words.c