From 87bb1d96fd753e6f0649fe30e34a8ddacafdb24a Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Sat, 14 Sep 2024 20:31:35 +0200 Subject: [PATCH 1/9] Change: programs->utils --- makefile | 8 ++++---- src/kernel/kmain.c | 2 +- src/kernel/shell.c | 2 +- src/{programs => utils}/bf.c | 0 src/{programs => utils}/bmp.c | 0 src/{programs => utils}/ciphers.c | 0 src/{programs => utils}/ciphers.h | 0 src/{programs => utils}/conway.c | 0 src/{programs => utils}/conway.h | 0 src/{programs => utils}/cowsay.c | 0 src/{programs => utils}/fs.c | 0 src/{programs => utils}/math.c | 0 src/{programs => utils}/misc.c | 0 src/{programs => utils}/navalbattle.c | 0 src/{programs => utils}/navalbattle.h | 0 src/{programs => utils}/pi.c | 0 src/{programs => utils}/primes.c | 0 src/{programs => utils}/snake.c | 0 src/{programs => utils}/sysinfo.c | 0 src/{programs/programs.h => utils/utils.h} | 4 ++-- src/{programs => utils}/words.c | 0 21 files changed, 8 insertions(+), 8 deletions(-) rename src/{programs => utils}/bf.c (100%) rename src/{programs => utils}/bmp.c (100%) rename src/{programs => utils}/ciphers.c (100%) rename src/{programs => utils}/ciphers.h (100%) rename src/{programs => utils}/conway.c (100%) rename src/{programs => utils}/conway.h (100%) rename src/{programs => utils}/cowsay.c (100%) rename src/{programs => utils}/fs.c (100%) rename src/{programs => utils}/math.c (100%) rename src/{programs => utils}/misc.c (100%) rename src/{programs => utils}/navalbattle.c (100%) rename src/{programs => utils}/navalbattle.h (100%) rename src/{programs => utils}/pi.c (100%) rename src/{programs => utils}/primes.c (100%) rename src/{programs => utils}/snake.c (100%) rename src/{programs => utils}/sysinfo.c (100%) rename src/{programs/programs.h => utils/utils.h} (96%) rename src/{programs => utils}/words.c (100%) diff --git a/makefile b/makefile index c6eb216..0e216e4 100644 --- a/makefile +++ b/makefile @@ -7,14 +7,14 @@ ASFLAGS = -f elf 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 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) OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o)) @@ -28,7 +28,7 @@ all: $(OBJ_DIR) kernel.elf $(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 kernel.elf: $(OBJECTS) $(FONT_OBJ) ld $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index 26b0367..b506a74 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) diff --git a/src/kernel/shell.c b/src/kernel/shell.c index 10ec05e..c1e75be 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" 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 100% rename from src/programs/misc.c rename to src/utils/misc.c 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/programs/programs.h b/src/utils/utils.h similarity index 96% rename from src/programs/programs.h rename to src/utils/utils.h index 097900f..80e6e51 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(); 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 From 03b712ace0a090626c0f8564d25b9177bac5b6ce Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Sat, 14 Sep 2024 22:39:06 +0200 Subject: [PATCH 2/9] Program loading, build system for apps, and badly-made lib linking. --- .gitignore | 1 + hello.bin | Bin 0 -> 55760 bytes makefile | 23 +++++++++++++--- program.ld | 10 +++++++ src/kernel/initrd.c | 62 +++++++++++++++++++++++++++++++++++++++++++ src/kernel/initrd.h | 1 + src/kernel/kmain.c | 10 +++++++ src/programs/hello.c | 6 +++++ 8 files changed, 109 insertions(+), 4 deletions(-) create mode 100755 hello.bin create mode 100644 program.ld create mode 100644 src/programs/hello.c 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/hello.bin b/hello.bin new file mode 100755 index 0000000000000000000000000000000000000000..202136584a556965fef3dcfb0cb7e209251674ee GIT binary patch literal 55760 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 P;39s-EtI2CEtBaF--Tj~ literal 0 HcmV?d00001 diff --git a/makefile b/makefile index 0e216e4..ab2aa73 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/ +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 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 $(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,24 @@ 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) lib kernel.elf programs $(OBJ_DIR): mkdir -p $(OBJ_DIR) - mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/utils $(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 +lib: $(OBJECTS) $(FONT_OBJ) + $(AR) rcs $(OBJ_DIR)/lib.a $(OBJECTS) $(FONT_OBJ) + 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 $(OBJ_DIR)/lib.a -o $(SRC_DIR)/initrd/$$base.bin; \ + done $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(CC) $(CFLAGS) $< -o $@ @@ -66,5 +81,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 0742d4f..3183f20 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; @@ -174,3 +187,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("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/kmain.c b/src/kernel/kmain.c index b506a74..e64b0bb 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -118,6 +118,16 @@ 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 + + void* binary_file = load_file_from_initrd((uint8_t*)initrd_addr, "./hello.bin"); + if (binary_file == NULL) + { + printf("NOT LOADED...\n"); + } else { + printf("LOADED!\n"); + } + timer_install(); keyboard_install(); printf("[kernel] spawning shell...\n"); diff --git a/src/programs/hello.c b/src/programs/hello.c new file mode 100644 index 0000000..8cffe15 --- /dev/null +++ b/src/programs/hello.c @@ -0,0 +1,6 @@ +#include "../libc/stdio.h" + +void main() +{ + printf("Hello, world, from a PROGRAM!\n"); +} From c885e69be4de015586566a2ce3193e773cd4f3c9 Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Sat, 14 Sep 2024 22:55:02 +0200 Subject: [PATCH 3/9] Loaded program cannot do stuff. Answer=syscalls? --- src/kernel/kmain.c | 7 +++++-- src/programs/hello.c | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index e64b0bb..ebcaba4 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -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); @@ -128,6 +128,9 @@ void kmain(multiboot2_info *mb_info) printf("LOADED!\n"); } + void (*program_entry)() = (void (*)())binary_file; + program_entry(); + timer_install(); keyboard_install(); printf("[kernel] spawning shell...\n"); diff --git a/src/programs/hello.c b/src/programs/hello.c index 8cffe15..f4c73e9 100644 --- a/src/programs/hello.c +++ b/src/programs/hello.c @@ -1,6 +1,8 @@ #include "../libc/stdio.h" +#include "../drivers/serial.h" void main() { - printf("Hello, world, from a PROGRAM!\n"); + serial_printf(3, "Hello, world, from a PROGRAM!\n"); + return; } From e6f119236bf2e4492eafb255683f54b19a6c5272 Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Sun, 15 Sep 2024 11:30:56 +0200 Subject: [PATCH 4/9] Fix: kernel stack --- src/kernel/loader.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/loader.s b/src/kernel/loader.s index 11d8aeb..7ae9c0a 100644 --- a/src/kernel/loader.s +++ b/src/kernel/loader.s @@ -213,5 +213,5 @@ irq_common_stub: section .bss align 4 -resb KERNEL_STACK_SIZE kernel_stack: + resb KERNEL_STACK_SIZE From af716cb2ec3a8b564154c4726957d8a1394bd67c Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Mon, 16 Sep 2024 14:38:39 +0200 Subject: [PATCH 5/9] minor fixes --- hello.bin | Bin 55760 -> 0 bytes makefile | 2 +- src/kernel/initrd.c | 2 +- src/kernel/kheap.c | 2 ++ src/kernel/kheap.h | 1 - src/kernel/kmain.c | 4 ++-- src/kernel/syscall.c | 20 ++++++++++++++++++++ src/kernel/syscall.h | 8 ++++++++ src/programs/hello.c | 7 ++++--- 9 files changed, 38 insertions(+), 8 deletions(-) delete mode 100755 hello.bin create mode 100644 src/kernel/syscall.c create mode 100644 src/kernel/syscall.h diff --git a/hello.bin b/hello.bin deleted file mode 100755 index 202136584a556965fef3dcfb0cb7e209251674ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55760 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 P;39s-EtI2CEtBaF--Tj~ diff --git a/makefile b/makefile index ab2aa73..386b5c8 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ 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 diff --git a/src/kernel/initrd.c b/src/kernel/initrd.c index 3183f20..84cccc0 100644 --- a/src/kernel/initrd.c +++ b/src/kernel/initrd.c @@ -232,7 +232,7 @@ void* load_file_from_initrd(uint8_t* initrd, const char* filename) void* file_content = tar_get_file_content(file); memcpy(file_data, file_content, file_size); - printf("Loaded '%s' at 0x%x, size=%u\n", filename, (unsigned int)file_data, 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/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 ebcaba4..b1e60a8 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -123,9 +123,9 @@ void kmain(multiboot2_info *mb_info) void* binary_file = load_file_from_initrd((uint8_t*)initrd_addr, "./hello.bin"); if (binary_file == NULL) { - printf("NOT LOADED...\n"); + printf("[debug] Failed to load test program!\n"); } else { - printf("LOADED!\n"); + printf("[debug] Test program loaded!\n"); } void (*program_entry)() = (void (*)())binary_file; diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c new file mode 100644 index 0000000..a117fc7 --- /dev/null +++ b/src/kernel/syscall.c @@ -0,0 +1,20 @@ +#include +#include "../libc/stdio.h" +#include "syscall.h" + +syscall_t syscalls[] = { + (syscall_t)printf, +}; + +int syscall_handler(int syscall_num, ...) +{ + if ((unsigned)syscall_num < sizeof(syscalls)/sizeof(syscall_t)) + { + va_list args; + va_start(args, syscall_num); + syscalls[syscall_num](va_arg(args, const char*)); + va_end(args); + return 0; + } + return -1; +} diff --git a/src/kernel/syscall.h b/src/kernel/syscall.h new file mode 100644 index 0000000..4367ba6 --- /dev/null +++ b/src/kernel/syscall.h @@ -0,0 +1,8 @@ +#ifndef SYSCALL_H +#define SYSCALL_H + +#define SYSCALL_PRINTF 0 + +typedef void (*syscall_t)(); + +#endif diff --git a/src/programs/hello.c b/src/programs/hello.c index f4c73e9..09df5fa 100644 --- a/src/programs/hello.c +++ b/src/programs/hello.c @@ -1,8 +1,9 @@ -#include "../libc/stdio.h" -#include "../drivers/serial.h" +void user_printf(const char* format) { + asm volatile ("int $0x80" : : "a"(1), "b"(format)); +} void main() { - serial_printf(3, "Hello, world, from a PROGRAM!\n"); + user_printf("Hello, world, from a PROGRAM!\n"); return; } From d02b3d62cb73006c922c82a7fbe464cc1815162a Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Mon, 16 Sep 2024 16:43:59 +0200 Subject: [PATCH 6/9] err: invalid syscall no --- src/kernel/irq.c | 4 ++++ src/kernel/loader.s | 31 +++++++++++++++++++++++++++++++ src/kernel/syscall.c | 20 -------------------- src/kernel/syscall.h | 8 -------- src/kernel/syscalls.c | 33 +++++++++++++++++++++++++++++++++ src/kernel/system.h | 2 ++ src/programs/hello.c | 7 ++++--- 7 files changed, 74 insertions(+), 31 deletions(-) delete mode 100644 src/kernel/syscall.c delete mode 100644 src/kernel/syscall.h create mode 100644 src/kernel/syscalls.c 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/loader.s b/src/kernel/loader.s index 7ae9c0a..1011219 100644 --- a/src/kernel/loader.s +++ b/src/kernel/loader.s @@ -210,6 +210,37 @@ 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, 0x10 ; kernel segment + 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 diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c deleted file mode 100644 index a117fc7..0000000 --- a/src/kernel/syscall.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include "../libc/stdio.h" -#include "syscall.h" - -syscall_t syscalls[] = { - (syscall_t)printf, -}; - -int syscall_handler(int syscall_num, ...) -{ - if ((unsigned)syscall_num < sizeof(syscalls)/sizeof(syscall_t)) - { - va_list args; - va_start(args, syscall_num); - syscalls[syscall_num](va_arg(args, const char*)); - va_end(args); - return 0; - } - return -1; -} diff --git a/src/kernel/syscall.h b/src/kernel/syscall.h deleted file mode 100644 index 4367ba6..0000000 --- a/src/kernel/syscall.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef SYSCALL_H -#define SYSCALL_H - -#define SYSCALL_PRINTF 0 - -typedef void (*syscall_t)(); - -#endif diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c new file mode 100644 index 0000000..a2e20dd --- /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, void* arg) +{ + 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, arg); +} 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 index 09df5fa..af3a85f 100644 --- a/src/programs/hello.c +++ b/src/programs/hello.c @@ -1,9 +1,10 @@ -void user_printf(const char* format) { - asm volatile ("int $0x80" : : "a"(1), "b"(format)); +void user_syscall(int syscall_no) { + asm volatile ("mov %0, %%eax" : : "r"(syscall_no)); + asm volatile ("int $0x80"); } void main() { - user_printf("Hello, world, from a PROGRAM!\n"); + user_syscall(1); return; } From 5ad32d3ee1546b02cd895cb1bdb4c484d514e858 Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:40:39 +0200 Subject: [PATCH 7/9] remove: useless lib rule --- makefile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/makefile b/makefile index 386b5c8..a7d9edf 100644 --- a/makefile +++ b/makefile @@ -29,14 +29,11 @@ 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) lib kernel.elf programs +all: $(OBJ_DIR) kernel.elf programs $(OBJ_DIR): mkdir -p $(OBJ_DIR) mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/utils $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts $(OBJ_DIR)/programs - -lib: $(OBJECTS) $(FONT_OBJ) - $(AR) rcs $(OBJ_DIR)/lib.a $(OBJECTS) $(FONT_OBJ) kernel.elf: $(OBJECTS) $(FONT_OBJ) $(LD) $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf @@ -45,7 +42,7 @@ 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 $(OBJ_DIR)/lib.a -o $(SRC_DIR)/initrd/$$base.bin; \ + $(LD) -melf_i386 -T program.ld $$prog -o $(SRC_DIR)/initrd/$$base.bin; \ done $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c From 1fa4b5c70a3a23617ecd0f2effd85adf1eb829f7 Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:46:58 +0200 Subject: [PATCH 8/9] Add: exec feature for binaries --- docs/DEVELOPERS.md | 2 ++ docs/USERS.md | 4 ++++ src/kernel/kmain.c | 11 ----------- src/kernel/loader.s | 2 +- src/kernel/shell.c | 1 + src/kernel/syscalls.c | 4 ++-- src/utils/misc.c | 27 +++++++++++++++++++++++++-- src/utils/utils.h | 3 +++ 8 files changed, 38 insertions(+), 16 deletions(-) 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/src/kernel/kmain.c b/src/kernel/kmain.c index b1e60a8..45a1820 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -120,17 +120,6 @@ void kmain(multiboot2_info *mb_info) // usually the place where i do testing - void* binary_file = load_file_from_initrd((uint8_t*)initrd_addr, "./hello.bin"); - if (binary_file == NULL) - { - printf("[debug] Failed to load test program!\n"); - } else { - printf("[debug] Test program loaded!\n"); - } - - void (*program_entry)() = (void (*)())binary_file; - program_entry(); - timer_install(); keyboard_install(); printf("[kernel] spawning shell...\n"); diff --git a/src/kernel/loader.s b/src/kernel/loader.s index 1011219..1029284 100644 --- a/src/kernel/loader.s +++ b/src/kernel/loader.s @@ -225,7 +225,7 @@ syscall_common_stub: mov eax, ds push eax ; save ds - mov ax, 0x10 ; kernel segment + mov ax, 0x01 ; kernel segment YES I CHEATED I KNOW THIS SUCKS mov ds, ax mov es, ax diff --git a/src/kernel/shell.c b/src/kernel/shell.c index c1e75be..febd98c 100644 --- a/src/kernel/shell.c +++ b/src/kernel/shell.c @@ -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 index a2e20dd..aac4650 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -5,7 +5,7 @@ #include "../libc/stdio.h" -void handle_syscall(int syscall_number, void* arg) +void handle_syscall(int syscall_number) { switch(syscall_number) { @@ -29,5 +29,5 @@ void syscall_handler() printf("[syscall] syscall_number=%d, arg=%p\n", syscall_number, arg); - handle_syscall(syscall_number, arg); + handle_syscall(syscall_number); } diff --git a/src/utils/misc.c b/src/utils/misc.c index c8f364d..717ff31 100644 --- a/src/utils/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/utils/utils.h b/src/utils/utils.h index 80e6e51..419974f 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -45,4 +45,7 @@ void program_navalbattle(); void program_conway(); void program_snake(); +// Binaries loading and execution +void program_exec(); + #endif From c104657d523ed574ebf63cbd2b35ba4346ddc421 Mon Sep 17 00:00:00 2001 From: xamidev <121681048+xamidev@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:39:26 +0200 Subject: [PATCH 9/9] WIP: uhex RO port --- src/utils/uhex.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/utils/uhex.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; + + + +} + +*/