diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/src/userland/hlib/list.c b/src/userland/hlib/list.c deleted file mode 100644 index ffc0ed6..0000000 --- a/src/userland/hlib/list.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -void _listAdd(AllocationData allocationData, ListElement **list, void *data) { - ListElement *element = malloc(sizeof(ListElement)); - element->data = data; - element->next = NULL; - if (!*list) { - *list = element; - return; - } - ListElement *current = *list; - while (current->next) { - current = current->next; - } - current->next = element; -} - -void *listPopFirst(ListElement **list) { - if (!*list) { - return NULL; - } - ListElement *resultElement = *list; - void *result = resultElement->data; - *list = (*list)->next; - free(resultElement); - return result; -} - -uint32_t listCount(ListElement *list) { - uint32_t i = 0; - foreach (list, void *, element, { i++; }) - ; - return i; -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -bool listRemoveValue(ListElement **list, void *value) { - if (!*list) { - return false; - } - ListElement *element = *list, *previous = NULL; - while (element) { - if (element->data == value) { - if (previous) { - previous->next = element->next; - } else { - *list = element->next; - } - free(element); - return true; - } - previous = element; - element = element->next; - } - return false; -} - -void listClear(ListElement **list, bool freeData) { - ListElement *current = *list; - if (!current) { - return; - } - while (current->next) { - if (freeData) { - free(current->data); - } - ListElement *next = current->next; - free(current); - current = next; - } - *list = NULL; -} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/src/userland/hlib/list.c b/src/userland/hlib/list.c deleted file mode 100644 index ffc0ed6..0000000 --- a/src/userland/hlib/list.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -void _listAdd(AllocationData allocationData, ListElement **list, void *data) { - ListElement *element = malloc(sizeof(ListElement)); - element->data = data; - element->next = NULL; - if (!*list) { - *list = element; - return; - } - ListElement *current = *list; - while (current->next) { - current = current->next; - } - current->next = element; -} - -void *listPopFirst(ListElement **list) { - if (!*list) { - return NULL; - } - ListElement *resultElement = *list; - void *result = resultElement->data; - *list = (*list)->next; - free(resultElement); - return result; -} - -uint32_t listCount(ListElement *list) { - uint32_t i = 0; - foreach (list, void *, element, { i++; }) - ; - return i; -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -bool listRemoveValue(ListElement **list, void *value) { - if (!*list) { - return false; - } - ListElement *element = *list, *previous = NULL; - while (element) { - if (element->data == value) { - if (previous) { - previous->next = element->next; - } else { - *list = element->next; - } - free(element); - return true; - } - previous = element; - element = element->next; - } - return false; -} - -void listClear(ListElement **list, bool freeData) { - ListElement *current = *list; - if (!current) { - return; - } - while (current->next) { - if (freeData) { - free(current->data); - } - ListElement *next = current->next; - free(current); - current = next; - } - *list = NULL; -} diff --git a/src/userland/hlib/main.c b/src/userland/hlib/main.c deleted file mode 100644 index 43ac97d..0000000 --- a/src/userland/hlib/main.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "include/syscalls.h" -#include -#include - -uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, - uint32_t parameter2, uint32_t parameter3) { - uint32_t esp; - asm("push %%eax" ::"a"(&&end)); // end: return address - asm("mov %%esp, %%eax" : "=a"(esp)); - asm("sysenter\n" - : - : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), - "S"(parameter3), "D"(esp)); -// eax is set by the kernel as the return value -end: - // the 0x1C comes from the number of parameters / local variables do handle - // this function with care or it will break everything - asm("add $0x1C, %%esp\n" - "pop %%ebp\n" - "ret" ::); - // don't go here! ret returns with the correct value - return 0; -} - -uint32_t loadFromInitrd(char *name) { - uintptr_t id = insertString(name); - uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); - if (!service) { - return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); - } - return service; -} - -uint32_t loadFromInitrdUninitialized(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); -} - -void requestName(char *service, char *provider, uintptr_t data1, - uintptr_t data2) { - uint32_t serviceId = getService(service); - uint32_t providerId = getFunction(serviceId, provider); - request(serviceId, providerId, data1, data2); -} - -void *requestMemory(uint32_t pageCount, void *targetAddress, - void *physicalAddress) { - return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), - U32(physicalAddress), 0)); -} - -void *getPage() { return requestMemory(1, NULL, NULL); } - -void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } - -void freePage(void *location) {} - -void memset(void *_target, uint8_t byte, uint32_t size) { - uint8_t *target = _target; - for (uint32_t i = 0; i < size; i++) { - *target = byte; - target++; - } -} - -bool stackContains(uint32_t serviceId) { - return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); -} - -#define REQUEST1(returnType, functionName, service, function) \ - returnType functionName(uint32_t data) { \ - static uint32_t serviceId = 0; \ - if (!serviceId) { \ - serviceId = getService(service); \ - serviceId = getService(service); \ - } \ - static uint32_t functionId = 0; \ - if (!functionId) { \ - functionId = getFunction(serviceId, function); \ - } \ - return (returnType)request(serviceId, functionId, data, 0); \ - } - -REQUEST1(void, sleep, "pit", "sleep") diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/src/userland/hlib/list.c b/src/userland/hlib/list.c deleted file mode 100644 index ffc0ed6..0000000 --- a/src/userland/hlib/list.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -void _listAdd(AllocationData allocationData, ListElement **list, void *data) { - ListElement *element = malloc(sizeof(ListElement)); - element->data = data; - element->next = NULL; - if (!*list) { - *list = element; - return; - } - ListElement *current = *list; - while (current->next) { - current = current->next; - } - current->next = element; -} - -void *listPopFirst(ListElement **list) { - if (!*list) { - return NULL; - } - ListElement *resultElement = *list; - void *result = resultElement->data; - *list = (*list)->next; - free(resultElement); - return result; -} - -uint32_t listCount(ListElement *list) { - uint32_t i = 0; - foreach (list, void *, element, { i++; }) - ; - return i; -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -bool listRemoveValue(ListElement **list, void *value) { - if (!*list) { - return false; - } - ListElement *element = *list, *previous = NULL; - while (element) { - if (element->data == value) { - if (previous) { - previous->next = element->next; - } else { - *list = element->next; - } - free(element); - return true; - } - previous = element; - element = element->next; - } - return false; -} - -void listClear(ListElement **list, bool freeData) { - ListElement *current = *list; - if (!current) { - return; - } - while (current->next) { - if (freeData) { - free(current->data); - } - ListElement *next = current->next; - free(current); - current = next; - } - *list = NULL; -} diff --git a/src/userland/hlib/main.c b/src/userland/hlib/main.c deleted file mode 100644 index 43ac97d..0000000 --- a/src/userland/hlib/main.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "include/syscalls.h" -#include -#include - -uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, - uint32_t parameter2, uint32_t parameter3) { - uint32_t esp; - asm("push %%eax" ::"a"(&&end)); // end: return address - asm("mov %%esp, %%eax" : "=a"(esp)); - asm("sysenter\n" - : - : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), - "S"(parameter3), "D"(esp)); -// eax is set by the kernel as the return value -end: - // the 0x1C comes from the number of parameters / local variables do handle - // this function with care or it will break everything - asm("add $0x1C, %%esp\n" - "pop %%ebp\n" - "ret" ::); - // don't go here! ret returns with the correct value - return 0; -} - -uint32_t loadFromInitrd(char *name) { - uintptr_t id = insertString(name); - uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); - if (!service) { - return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); - } - return service; -} - -uint32_t loadFromInitrdUninitialized(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); -} - -void requestName(char *service, char *provider, uintptr_t data1, - uintptr_t data2) { - uint32_t serviceId = getService(service); - uint32_t providerId = getFunction(serviceId, provider); - request(serviceId, providerId, data1, data2); -} - -void *requestMemory(uint32_t pageCount, void *targetAddress, - void *physicalAddress) { - return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), - U32(physicalAddress), 0)); -} - -void *getPage() { return requestMemory(1, NULL, NULL); } - -void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } - -void freePage(void *location) {} - -void memset(void *_target, uint8_t byte, uint32_t size) { - uint8_t *target = _target; - for (uint32_t i = 0; i < size; i++) { - *target = byte; - target++; - } -} - -bool stackContains(uint32_t serviceId) { - return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); -} - -#define REQUEST1(returnType, functionName, service, function) \ - returnType functionName(uint32_t data) { \ - static uint32_t serviceId = 0; \ - if (!serviceId) { \ - serviceId = getService(service); \ - serviceId = getService(service); \ - } \ - static uint32_t functionId = 0; \ - if (!functionId) { \ - functionId = getFunction(serviceId, function); \ - } \ - return (returnType)request(serviceId, functionId, data, 0); \ - } - -REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/userland/hlib/malloc.c b/src/userland/hlib/malloc.c deleted file mode 120000 index 022d82b..0000000 --- a/src/userland/hlib/malloc.c +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.c \ No newline at end of file diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/src/userland/hlib/list.c b/src/userland/hlib/list.c deleted file mode 100644 index ffc0ed6..0000000 --- a/src/userland/hlib/list.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -void _listAdd(AllocationData allocationData, ListElement **list, void *data) { - ListElement *element = malloc(sizeof(ListElement)); - element->data = data; - element->next = NULL; - if (!*list) { - *list = element; - return; - } - ListElement *current = *list; - while (current->next) { - current = current->next; - } - current->next = element; -} - -void *listPopFirst(ListElement **list) { - if (!*list) { - return NULL; - } - ListElement *resultElement = *list; - void *result = resultElement->data; - *list = (*list)->next; - free(resultElement); - return result; -} - -uint32_t listCount(ListElement *list) { - uint32_t i = 0; - foreach (list, void *, element, { i++; }) - ; - return i; -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -bool listRemoveValue(ListElement **list, void *value) { - if (!*list) { - return false; - } - ListElement *element = *list, *previous = NULL; - while (element) { - if (element->data == value) { - if (previous) { - previous->next = element->next; - } else { - *list = element->next; - } - free(element); - return true; - } - previous = element; - element = element->next; - } - return false; -} - -void listClear(ListElement **list, bool freeData) { - ListElement *current = *list; - if (!current) { - return; - } - while (current->next) { - if (freeData) { - free(current->data); - } - ListElement *next = current->next; - free(current); - current = next; - } - *list = NULL; -} diff --git a/src/userland/hlib/main.c b/src/userland/hlib/main.c deleted file mode 100644 index 43ac97d..0000000 --- a/src/userland/hlib/main.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "include/syscalls.h" -#include -#include - -uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, - uint32_t parameter2, uint32_t parameter3) { - uint32_t esp; - asm("push %%eax" ::"a"(&&end)); // end: return address - asm("mov %%esp, %%eax" : "=a"(esp)); - asm("sysenter\n" - : - : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), - "S"(parameter3), "D"(esp)); -// eax is set by the kernel as the return value -end: - // the 0x1C comes from the number of parameters / local variables do handle - // this function with care or it will break everything - asm("add $0x1C, %%esp\n" - "pop %%ebp\n" - "ret" ::); - // don't go here! ret returns with the correct value - return 0; -} - -uint32_t loadFromInitrd(char *name) { - uintptr_t id = insertString(name); - uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); - if (!service) { - return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); - } - return service; -} - -uint32_t loadFromInitrdUninitialized(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); -} - -void requestName(char *service, char *provider, uintptr_t data1, - uintptr_t data2) { - uint32_t serviceId = getService(service); - uint32_t providerId = getFunction(serviceId, provider); - request(serviceId, providerId, data1, data2); -} - -void *requestMemory(uint32_t pageCount, void *targetAddress, - void *physicalAddress) { - return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), - U32(physicalAddress), 0)); -} - -void *getPage() { return requestMemory(1, NULL, NULL); } - -void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } - -void freePage(void *location) {} - -void memset(void *_target, uint8_t byte, uint32_t size) { - uint8_t *target = _target; - for (uint32_t i = 0; i < size; i++) { - *target = byte; - target++; - } -} - -bool stackContains(uint32_t serviceId) { - return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); -} - -#define REQUEST1(returnType, functionName, service, function) \ - returnType functionName(uint32_t data) { \ - static uint32_t serviceId = 0; \ - if (!serviceId) { \ - serviceId = getService(service); \ - serviceId = getService(service); \ - } \ - static uint32_t functionId = 0; \ - if (!functionId) { \ - functionId = getFunction(serviceId, function); \ - } \ - return (returnType)request(serviceId, functionId, data, 0); \ - } - -REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/userland/hlib/malloc.c b/src/userland/hlib/malloc.c deleted file mode 120000 index 022d82b..0000000 --- a/src/userland/hlib/malloc.c +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/userland/hlib/malloc.h b/src/userland/hlib/malloc.h deleted file mode 120000 index 8a56b0a..0000000 --- a/src/userland/hlib/malloc.h +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.h \ No newline at end of file diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/src/userland/hlib/list.c b/src/userland/hlib/list.c deleted file mode 100644 index ffc0ed6..0000000 --- a/src/userland/hlib/list.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -void _listAdd(AllocationData allocationData, ListElement **list, void *data) { - ListElement *element = malloc(sizeof(ListElement)); - element->data = data; - element->next = NULL; - if (!*list) { - *list = element; - return; - } - ListElement *current = *list; - while (current->next) { - current = current->next; - } - current->next = element; -} - -void *listPopFirst(ListElement **list) { - if (!*list) { - return NULL; - } - ListElement *resultElement = *list; - void *result = resultElement->data; - *list = (*list)->next; - free(resultElement); - return result; -} - -uint32_t listCount(ListElement *list) { - uint32_t i = 0; - foreach (list, void *, element, { i++; }) - ; - return i; -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -bool listRemoveValue(ListElement **list, void *value) { - if (!*list) { - return false; - } - ListElement *element = *list, *previous = NULL; - while (element) { - if (element->data == value) { - if (previous) { - previous->next = element->next; - } else { - *list = element->next; - } - free(element); - return true; - } - previous = element; - element = element->next; - } - return false; -} - -void listClear(ListElement **list, bool freeData) { - ListElement *current = *list; - if (!current) { - return; - } - while (current->next) { - if (freeData) { - free(current->data); - } - ListElement *next = current->next; - free(current); - current = next; - } - *list = NULL; -} diff --git a/src/userland/hlib/main.c b/src/userland/hlib/main.c deleted file mode 100644 index 43ac97d..0000000 --- a/src/userland/hlib/main.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "include/syscalls.h" -#include -#include - -uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, - uint32_t parameter2, uint32_t parameter3) { - uint32_t esp; - asm("push %%eax" ::"a"(&&end)); // end: return address - asm("mov %%esp, %%eax" : "=a"(esp)); - asm("sysenter\n" - : - : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), - "S"(parameter3), "D"(esp)); -// eax is set by the kernel as the return value -end: - // the 0x1C comes from the number of parameters / local variables do handle - // this function with care or it will break everything - asm("add $0x1C, %%esp\n" - "pop %%ebp\n" - "ret" ::); - // don't go here! ret returns with the correct value - return 0; -} - -uint32_t loadFromInitrd(char *name) { - uintptr_t id = insertString(name); - uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); - if (!service) { - return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); - } - return service; -} - -uint32_t loadFromInitrdUninitialized(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); -} - -void requestName(char *service, char *provider, uintptr_t data1, - uintptr_t data2) { - uint32_t serviceId = getService(service); - uint32_t providerId = getFunction(serviceId, provider); - request(serviceId, providerId, data1, data2); -} - -void *requestMemory(uint32_t pageCount, void *targetAddress, - void *physicalAddress) { - return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), - U32(physicalAddress), 0)); -} - -void *getPage() { return requestMemory(1, NULL, NULL); } - -void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } - -void freePage(void *location) {} - -void memset(void *_target, uint8_t byte, uint32_t size) { - uint8_t *target = _target; - for (uint32_t i = 0; i < size; i++) { - *target = byte; - target++; - } -} - -bool stackContains(uint32_t serviceId) { - return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); -} - -#define REQUEST1(returnType, functionName, service, function) \ - returnType functionName(uint32_t data) { \ - static uint32_t serviceId = 0; \ - if (!serviceId) { \ - serviceId = getService(service); \ - serviceId = getService(service); \ - } \ - static uint32_t functionId = 0; \ - if (!functionId) { \ - functionId = getFunction(serviceId, function); \ - } \ - return (returnType)request(serviceId, functionId, data, 0); \ - } - -REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/userland/hlib/malloc.c b/src/userland/hlib/malloc.c deleted file mode 120000 index 022d82b..0000000 --- a/src/userland/hlib/malloc.c +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/userland/hlib/malloc.h b/src/userland/hlib/malloc.h deleted file mode 120000 index 8a56b0a..0000000 --- a/src/userland/hlib/malloc.h +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/userland/hlib/service/events.c b/src/userland/hlib/service/events.c deleted file mode 100644 index 9429c44..0000000 --- a/src/userland/hlib/service/events.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -uint32_t createEvent(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); -} - -uintptr_t hashString(char *string) { - uintptr_t hash = 0; - for (uintptr_t i = 0; string[i]; i++) { - hash = 257 * hash + string[i]; - } - return hash; -} - -uint32_t getEvent(uint32_t service, char *name) { - uintptr_t id = hashString(name); - return syscall(SYS_GET_EVENT, service, id, 0, 0); -} - -void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { - syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); -} - -void fireEvent(uint32_t eventNumber, uint32_t data) { - fireEventCode(eventNumber, data, 0); -} - -void subscribeEvent(uint32_t service, uint32_t event, - void(handler)(void *, uint32_t)) { - syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); -} - -uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { - return syscall(SYS_AWAIT, service, event, code, 0); -} - -uint32_t await(uint32_t service, uint32_t event) { - return awaitCode(service, event, 0); -} - -uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { - return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); -} - -uint32_t createDirectEvent(uint32_t id) { - return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); -} - -uint32_t createDirectEventSave(uint32_t id) { - uint32_t existingEvent = getDirectEvent(getServiceId(), id); - if (existingEvent) { - return existingEvent; - } - return createDirectEvent(id); -} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/src/userland/hlib/list.c b/src/userland/hlib/list.c deleted file mode 100644 index ffc0ed6..0000000 --- a/src/userland/hlib/list.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -void _listAdd(AllocationData allocationData, ListElement **list, void *data) { - ListElement *element = malloc(sizeof(ListElement)); - element->data = data; - element->next = NULL; - if (!*list) { - *list = element; - return; - } - ListElement *current = *list; - while (current->next) { - current = current->next; - } - current->next = element; -} - -void *listPopFirst(ListElement **list) { - if (!*list) { - return NULL; - } - ListElement *resultElement = *list; - void *result = resultElement->data; - *list = (*list)->next; - free(resultElement); - return result; -} - -uint32_t listCount(ListElement *list) { - uint32_t i = 0; - foreach (list, void *, element, { i++; }) - ; - return i; -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -bool listRemoveValue(ListElement **list, void *value) { - if (!*list) { - return false; - } - ListElement *element = *list, *previous = NULL; - while (element) { - if (element->data == value) { - if (previous) { - previous->next = element->next; - } else { - *list = element->next; - } - free(element); - return true; - } - previous = element; - element = element->next; - } - return false; -} - -void listClear(ListElement **list, bool freeData) { - ListElement *current = *list; - if (!current) { - return; - } - while (current->next) { - if (freeData) { - free(current->data); - } - ListElement *next = current->next; - free(current); - current = next; - } - *list = NULL; -} diff --git a/src/userland/hlib/main.c b/src/userland/hlib/main.c deleted file mode 100644 index 43ac97d..0000000 --- a/src/userland/hlib/main.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "include/syscalls.h" -#include -#include - -uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, - uint32_t parameter2, uint32_t parameter3) { - uint32_t esp; - asm("push %%eax" ::"a"(&&end)); // end: return address - asm("mov %%esp, %%eax" : "=a"(esp)); - asm("sysenter\n" - : - : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), - "S"(parameter3), "D"(esp)); -// eax is set by the kernel as the return value -end: - // the 0x1C comes from the number of parameters / local variables do handle - // this function with care or it will break everything - asm("add $0x1C, %%esp\n" - "pop %%ebp\n" - "ret" ::); - // don't go here! ret returns with the correct value - return 0; -} - -uint32_t loadFromInitrd(char *name) { - uintptr_t id = insertString(name); - uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); - if (!service) { - return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); - } - return service; -} - -uint32_t loadFromInitrdUninitialized(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); -} - -void requestName(char *service, char *provider, uintptr_t data1, - uintptr_t data2) { - uint32_t serviceId = getService(service); - uint32_t providerId = getFunction(serviceId, provider); - request(serviceId, providerId, data1, data2); -} - -void *requestMemory(uint32_t pageCount, void *targetAddress, - void *physicalAddress) { - return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), - U32(physicalAddress), 0)); -} - -void *getPage() { return requestMemory(1, NULL, NULL); } - -void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } - -void freePage(void *location) {} - -void memset(void *_target, uint8_t byte, uint32_t size) { - uint8_t *target = _target; - for (uint32_t i = 0; i < size; i++) { - *target = byte; - target++; - } -} - -bool stackContains(uint32_t serviceId) { - return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); -} - -#define REQUEST1(returnType, functionName, service, function) \ - returnType functionName(uint32_t data) { \ - static uint32_t serviceId = 0; \ - if (!serviceId) { \ - serviceId = getService(service); \ - serviceId = getService(service); \ - } \ - static uint32_t functionId = 0; \ - if (!functionId) { \ - functionId = getFunction(serviceId, function); \ - } \ - return (returnType)request(serviceId, functionId, data, 0); \ - } - -REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/userland/hlib/malloc.c b/src/userland/hlib/malloc.c deleted file mode 120000 index 022d82b..0000000 --- a/src/userland/hlib/malloc.c +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/userland/hlib/malloc.h b/src/userland/hlib/malloc.h deleted file mode 120000 index 8a56b0a..0000000 --- a/src/userland/hlib/malloc.h +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/userland/hlib/service/events.c b/src/userland/hlib/service/events.c deleted file mode 100644 index 9429c44..0000000 --- a/src/userland/hlib/service/events.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -uint32_t createEvent(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); -} - -uintptr_t hashString(char *string) { - uintptr_t hash = 0; - for (uintptr_t i = 0; string[i]; i++) { - hash = 257 * hash + string[i]; - } - return hash; -} - -uint32_t getEvent(uint32_t service, char *name) { - uintptr_t id = hashString(name); - return syscall(SYS_GET_EVENT, service, id, 0, 0); -} - -void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { - syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); -} - -void fireEvent(uint32_t eventNumber, uint32_t data) { - fireEventCode(eventNumber, data, 0); -} - -void subscribeEvent(uint32_t service, uint32_t event, - void(handler)(void *, uint32_t)) { - syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); -} - -uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { - return syscall(SYS_AWAIT, service, event, code, 0); -} - -uint32_t await(uint32_t service, uint32_t event) { - return awaitCode(service, event, 0); -} - -uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { - return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); -} - -uint32_t createDirectEvent(uint32_t id) { - return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); -} - -uint32_t createDirectEventSave(uint32_t id) { - uint32_t existingEvent = getDirectEvent(getServiceId(), id); - if (existingEvent) { - return existingEvent; - } - return createDirectEvent(id); -} diff --git a/src/userland/hlib/service/service.c b/src/userland/hlib/service/service.c deleted file mode 100644 index 1669154..0000000 --- a/src/userland/hlib/service/service.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include - -uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, - uintptr_t data2) { - return syscall(SYS_REQUEST, service, function, data1, data2); -} - -uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { - uintptr_t id = insertString(name); - return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); -} - -uint32_t getService(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_GET_SERVICE, id, 0, 0, 0); -} - -uint32_t getFunction(uint32_t module, char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_GET_FUNCTION, module, id, 0, 0); -} - -uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } - -uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { - return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); -} - -void *getPhysicalAddress(void *source) { - return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | - (U32(source) & 0xFFF)); -} - -uint32_t fork(void (f)(), void *a, void *b, void *c) { - return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); -} - diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/src/userland/hlib/list.c b/src/userland/hlib/list.c deleted file mode 100644 index ffc0ed6..0000000 --- a/src/userland/hlib/list.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -void _listAdd(AllocationData allocationData, ListElement **list, void *data) { - ListElement *element = malloc(sizeof(ListElement)); - element->data = data; - element->next = NULL; - if (!*list) { - *list = element; - return; - } - ListElement *current = *list; - while (current->next) { - current = current->next; - } - current->next = element; -} - -void *listPopFirst(ListElement **list) { - if (!*list) { - return NULL; - } - ListElement *resultElement = *list; - void *result = resultElement->data; - *list = (*list)->next; - free(resultElement); - return result; -} - -uint32_t listCount(ListElement *list) { - uint32_t i = 0; - foreach (list, void *, element, { i++; }) - ; - return i; -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -bool listRemoveValue(ListElement **list, void *value) { - if (!*list) { - return false; - } - ListElement *element = *list, *previous = NULL; - while (element) { - if (element->data == value) { - if (previous) { - previous->next = element->next; - } else { - *list = element->next; - } - free(element); - return true; - } - previous = element; - element = element->next; - } - return false; -} - -void listClear(ListElement **list, bool freeData) { - ListElement *current = *list; - if (!current) { - return; - } - while (current->next) { - if (freeData) { - free(current->data); - } - ListElement *next = current->next; - free(current); - current = next; - } - *list = NULL; -} diff --git a/src/userland/hlib/main.c b/src/userland/hlib/main.c deleted file mode 100644 index 43ac97d..0000000 --- a/src/userland/hlib/main.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "include/syscalls.h" -#include -#include - -uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, - uint32_t parameter2, uint32_t parameter3) { - uint32_t esp; - asm("push %%eax" ::"a"(&&end)); // end: return address - asm("mov %%esp, %%eax" : "=a"(esp)); - asm("sysenter\n" - : - : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), - "S"(parameter3), "D"(esp)); -// eax is set by the kernel as the return value -end: - // the 0x1C comes from the number of parameters / local variables do handle - // this function with care or it will break everything - asm("add $0x1C, %%esp\n" - "pop %%ebp\n" - "ret" ::); - // don't go here! ret returns with the correct value - return 0; -} - -uint32_t loadFromInitrd(char *name) { - uintptr_t id = insertString(name); - uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); - if (!service) { - return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); - } - return service; -} - -uint32_t loadFromInitrdUninitialized(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); -} - -void requestName(char *service, char *provider, uintptr_t data1, - uintptr_t data2) { - uint32_t serviceId = getService(service); - uint32_t providerId = getFunction(serviceId, provider); - request(serviceId, providerId, data1, data2); -} - -void *requestMemory(uint32_t pageCount, void *targetAddress, - void *physicalAddress) { - return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), - U32(physicalAddress), 0)); -} - -void *getPage() { return requestMemory(1, NULL, NULL); } - -void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } - -void freePage(void *location) {} - -void memset(void *_target, uint8_t byte, uint32_t size) { - uint8_t *target = _target; - for (uint32_t i = 0; i < size; i++) { - *target = byte; - target++; - } -} - -bool stackContains(uint32_t serviceId) { - return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); -} - -#define REQUEST1(returnType, functionName, service, function) \ - returnType functionName(uint32_t data) { \ - static uint32_t serviceId = 0; \ - if (!serviceId) { \ - serviceId = getService(service); \ - serviceId = getService(service); \ - } \ - static uint32_t functionId = 0; \ - if (!functionId) { \ - functionId = getFunction(serviceId, function); \ - } \ - return (returnType)request(serviceId, functionId, data, 0); \ - } - -REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/userland/hlib/malloc.c b/src/userland/hlib/malloc.c deleted file mode 120000 index 022d82b..0000000 --- a/src/userland/hlib/malloc.c +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/userland/hlib/malloc.h b/src/userland/hlib/malloc.h deleted file mode 120000 index 8a56b0a..0000000 --- a/src/userland/hlib/malloc.h +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/userland/hlib/service/events.c b/src/userland/hlib/service/events.c deleted file mode 100644 index 9429c44..0000000 --- a/src/userland/hlib/service/events.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -uint32_t createEvent(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); -} - -uintptr_t hashString(char *string) { - uintptr_t hash = 0; - for (uintptr_t i = 0; string[i]; i++) { - hash = 257 * hash + string[i]; - } - return hash; -} - -uint32_t getEvent(uint32_t service, char *name) { - uintptr_t id = hashString(name); - return syscall(SYS_GET_EVENT, service, id, 0, 0); -} - -void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { - syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); -} - -void fireEvent(uint32_t eventNumber, uint32_t data) { - fireEventCode(eventNumber, data, 0); -} - -void subscribeEvent(uint32_t service, uint32_t event, - void(handler)(void *, uint32_t)) { - syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); -} - -uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { - return syscall(SYS_AWAIT, service, event, code, 0); -} - -uint32_t await(uint32_t service, uint32_t event) { - return awaitCode(service, event, 0); -} - -uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { - return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); -} - -uint32_t createDirectEvent(uint32_t id) { - return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); -} - -uint32_t createDirectEventSave(uint32_t id) { - uint32_t existingEvent = getDirectEvent(getServiceId(), id); - if (existingEvent) { - return existingEvent; - } - return createDirectEvent(id); -} diff --git a/src/userland/hlib/service/service.c b/src/userland/hlib/service/service.c deleted file mode 100644 index 1669154..0000000 --- a/src/userland/hlib/service/service.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include - -uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, - uintptr_t data2) { - return syscall(SYS_REQUEST, service, function, data1, data2); -} - -uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { - uintptr_t id = insertString(name); - return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); -} - -uint32_t getService(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_GET_SERVICE, id, 0, 0, 0); -} - -uint32_t getFunction(uint32_t module, char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_GET_FUNCTION, module, id, 0, 0); -} - -uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } - -uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { - return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); -} - -void *getPhysicalAddress(void *source) { - return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | - (U32(source) & 0xFFF)); -} - -uint32_t fork(void (f)(), void *a, void *b, void *c) { - return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); -} - diff --git a/src/userland/hlib/stdio.c b/src/userland/hlib/stdio.c deleted file mode 100644 index e717154..0000000 --- a/src/userland/hlib/stdio.c +++ /dev/null @@ -1,207 +0,0 @@ -#include -#include -#include -#include - -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char **write, uintptr_t x) { - if (x == 0) { - **write = HEX_CHARS[x]; - (*write)++; - **write = HEX_CHARS[x]; - (*write)++; - return; - } - bool alreadyWriting = false; - for (int position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00 && !alreadyWriting) { - alreadyWriting = true; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte >> 4]; - (*write)++; - **write = HEX_CHARS[byte & 0x0F]; - (*write)++; - } - } -} - -uint8_t hexLength(uintptr_t x) { - bool alreadyWriting = false; - uint8_t size = 0; - for (int position = sizeof(uintptr_t); position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00 && !alreadyWriting) { - alreadyWriting = true; - } - if (alreadyWriting) { - size += 2; - } - } - return MAX(size, 2); -} - -uint32_t power(uintptr_t x, uintptr_t y) { - uintptr_t result = 1; - for (uintptr_t i = 0; i < y; i++) { - result *= x; - } - return result; -} - -uint32_t intLength(intptr_t x) { - if (x == 0) { - return 1; - } - for (intptr_t i = 10; i >= 0; i--) { - if (x / power(10, i) > 0) { - return i + 1; - } - } - return 1; -} - -void addChar(char **write, char c) { - **write = c; - (*write)++; -} - -void putInt(char **write, intptr_t x) { - if (x == 0) { - addChar(write, '0'); - return; - } - if (x < 0) { - addChar(write, '-'); - x *= -1; - } - for (intptr_t i = 10; i >= 0; i--) { - uintptr_t n = x / power(10, i); - if (n) { - addChar(write, HEX_CHARS[n % 10]); - } - } -} - -void putPadding(char **write, uintptr_t x) { - x = MIN(x, 10); // max 10 wide padding - for (intptr_t i = 0; i < x; i++) { - addChar(write, ' '); - } -} - -uint32_t getInsertLength(char insertType, intptr_t x) { - switch (insertType) { - case 's': - return strlen((char *)x); - case 'x': - return hexLength(x); - case 'c': - return 1; - case 'i': - return intLength(x) + (x < 0); - case 'p': - return x; - } - return 0; -} - -void stringInsert(char **write, uintptr_t x) { - char *string = (char *)x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - (*write)++; - } -} - -void handleInsert(char **write, char insertType, uintptr_t x) { - switch (insertType) { - case 's': - stringInsert(write, x); - return; - case 'x': - putHex(write, x); - return; - case 'c': - **write = x; - (*write)++; - return; - case 'i': - putInt(write, x); - return; - case 'p': - putPadding(write, x); - return; - } -} -uint32_t ioManager, logFunction; - -uint32_t printfSize(const char *format, va_list *valist) { - uint32_t size = 0; - for (; format[size] != 0; size++) { - if (format[size] == '%') { - char insertType = format[++size]; - size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); - continue; - } - } - return size; -} - -void _sprintf(char *data, const char *format, va_list *valist) { - char *write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); - continue; - } - *write = format[i]; - write++; - } -} - -void sprintf(char *data, const char *format, ...) { - va_list valist; - va_start(valist, format); - _sprintf(data, format, &valist); - va_end(valist); -} - -char *_asprintf(AllocationData allocationData, const char *format, ...) { - va_list valist; - va_start(valist, format); - uint32_t size = printfSize(format, &valist); - char *data = malloc(size); - va_start(valist, format); - _sprintf(data, format, &valist); - va_end(valist); - return data; -} - -void _printf(AllocationData allocationData, const char *format, ...) { - // I have absolutely no idea why this line fixes an issue where the first - // printf operation consistently doesn't correctly insert its string - free(malloc(1)); - va_list valist; - va_start(valist, format); - char *data = malloc(printfSize(format, &valist)); - va_start(valist, format); - _sprintf(data, format, &valist); - va_end(valist); - uintptr_t id = insertString(data); - request(ioManager, logFunction, id, 0); - discardString(id); - free(data); -} - -void gets(char *buffer) { - static uint32_t function = 0; - if (!function) { - function = getFunction(ioManager, "gets"); - } - uint32_t stringId = request(ioManager, function, 0, 0); - readString(stringId, buffer); -} diff --git a/Makefile b/Makefile index fdd033b..6a72399 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ USER_PROGRAM_NAMES := $(USER_PROGRAMS:%=user/%) USER_PROGRAM_FILES := $(USER_PROGRAMS:%=initrd/%) -run: build initrd user/hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) +run: build initrd hlib $(USER_PROGRAM_NAMES) $(IMAGE_FILE) @echo "starting qemu" @$(EMU) $(EMUFLAGS) @@ -71,6 +71,10 @@ @echo "compiling userspace program $<" @make -C $< +hlib: + @echo "compiling userspace honey-os library" + @make -C src/hlib + clean: @echo "clearing build folder" @rm -r $(BUILD_FOLDER) initrd src/userland/*/build diff --git a/src/hlib/Makefile b/src/hlib/Makefile new file mode 100644 index 0000000..2eb5937 --- /dev/null +++ b/src/hlib/Makefile @@ -0,0 +1,30 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../initrd/hlib: $(OBJS) + @echo "linking the honey OS c libary" + @$(LD) $(LD_FLAGS) -o ../../build/hlib.o $(OBJS) -T link.ld -r + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/hlib/compile_flags.txt b/src/hlib/compile_flags.txt new file mode 100644 index 0000000..a432e7b --- /dev/null +++ b/src/hlib/compile_flags.txt @@ -0,0 +1,6 @@ +-I./include +-I../../include +clang +-fms-extensions +-Wno-microsoft-anon-tag +-Wno-incompatible-library-redeclaration diff --git a/src/hlib/include/syscalls.h b/src/hlib/include/syscalls.h new file mode 100644 index 0000000..2025b24 --- /dev/null +++ b/src/hlib/include/syscalls.h @@ -0,0 +1,36 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include + +typedef enum { + SYS_RUN = 0, + SYS_CREATE_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_FUNCTION = 7, + SYS_SUBSCRIBE_INTERRUPT = 8, + SYS_CREATE_EVENT = 9, + SYS_GET_EVENT = 10, + SYS_FIRE_EVENT = 11, + SYS_SUBSCRIBE_EVENT = 12, + SYS_GET_SERVICE_ID = 13, + SYS_INSERT_STRING = 14, + SYS_GET_STRING_LENGTH = 15, + SYS_READ_STRING = 16, + SYS_DISCARD_STRING = 17, + SYS_REQUEST_MEMORY = 18, + SYS_LOOKUP_SYMBOL = 19, + SYS_STACK_CONTAINS = 20, + SYS_AWAIT = 21, + SYS_GET_PHYSICAL = 22, + SYS_FORK = 23, +} SyscallIds; + +extern uint32_t getFunction(uint32_t module, char *name); + +#endif diff --git a/src/hlib/io.c b/src/hlib/io.c new file mode 100644 index 0000000..5a6c3f3 --- /dev/null +++ b/src/hlib/io.c @@ -0,0 +1,14 @@ +#include +#include + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} diff --git a/src/hlib/link.ld b/src/hlib/link.ld new file mode 100644 index 0000000..e38b0df --- /dev/null +++ b/src/hlib/link.ld @@ -0,0 +1,12 @@ +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0xFF000000; + + .hlib : { + *(.text) + *(.rodata) + *(.data) + *(.bss) + } +} diff --git a/src/hlib/list.c b/src/hlib/list.c new file mode 100644 index 0000000..ffc0ed6 --- /dev/null +++ b/src/hlib/list.c @@ -0,0 +1,78 @@ +#include + +void _listAdd(AllocationData allocationData, ListElement **list, void *data) { + ListElement *element = malloc(sizeof(ListElement)); + element->data = data; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + ListElement *resultElement = *list; + void *result = resultElement->data; + *list = (*list)->next; + free(resultElement); + return result; +} + +uint32_t listCount(ListElement *list) { + uint32_t i = 0; + foreach (list, void *, element, { i++; }) + ; + return i; +} + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +bool listRemoveValue(ListElement **list, void *value) { + if (!*list) { + return false; + } + ListElement *element = *list, *previous = NULL; + while (element) { + if (element->data == value) { + if (previous) { + previous->next = element->next; + } else { + *list = element->next; + } + free(element); + return true; + } + previous = element; + element = element->next; + } + return false; +} + +void listClear(ListElement **list, bool freeData) { + ListElement *current = *list; + if (!current) { + return; + } + while (current->next) { + if (freeData) { + free(current->data); + } + ListElement *next = current->next; + free(current); + current = next; + } + *list = NULL; +} diff --git a/src/hlib/main.c b/src/hlib/main.c new file mode 100644 index 0000000..43ac97d --- /dev/null +++ b/src/hlib/main.c @@ -0,0 +1,84 @@ +#include "include/syscalls.h" +#include +#include + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); // end: return address + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +uint32_t loadFromInitrd(char *name) { + uintptr_t id = insertString(name); + uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); + if (!service) { + return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); + } + return service; +} + +uint32_t loadFromInitrdUninitialized(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); +} + +void requestName(char *service, char *provider, uintptr_t data1, + uintptr_t data2) { + uint32_t serviceId = getService(service); + uint32_t providerId = getFunction(serviceId, provider); + request(serviceId, providerId, data1, data2); +} + +void *requestMemory(uint32_t pageCount, void *targetAddress, + void *physicalAddress) { + return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), + U32(physicalAddress), 0)); +} + +void *getPage() { return requestMemory(1, NULL, NULL); } + +void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } + +void freePage(void *location) {} + +void memset(void *_target, uint8_t byte, uint32_t size) { + uint8_t *target = _target; + for (uint32_t i = 0; i < size; i++) { + *target = byte; + target++; + } +} + +bool stackContains(uint32_t serviceId) { + return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); +} + +#define REQUEST1(returnType, functionName, service, function) \ + returnType functionName(uint32_t data) { \ + static uint32_t serviceId = 0; \ + if (!serviceId) { \ + serviceId = getService(service); \ + serviceId = getService(service); \ + } \ + static uint32_t functionId = 0; \ + if (!functionId) { \ + functionId = getFunction(serviceId, function); \ + } \ + return (returnType)request(serviceId, functionId, data, 0); \ + } + +REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/hlib/malloc.c b/src/hlib/malloc.c new file mode 120000 index 0000000..3eec597 --- /dev/null +++ b/src/hlib/malloc.c @@ -0,0 +1 @@ +../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/hlib/malloc.h b/src/hlib/malloc.h new file mode 120000 index 0000000..26dc6d5 --- /dev/null +++ b/src/hlib/malloc.h @@ -0,0 +1 @@ +../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/hlib/service/events.c b/src/hlib/service/events.c new file mode 100644 index 0000000..9429c44 --- /dev/null +++ b/src/hlib/service/events.c @@ -0,0 +1,58 @@ +#include +#include +#include + +uint32_t createEvent(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uintptr_t hashString(char *string) { + uintptr_t hash = 0; + for (uintptr_t i = 0; string[i]; i++) { + hash = 257 * hash + string[i]; + } + return hash; +} + +uint32_t getEvent(uint32_t service, char *name) { + uintptr_t id = hashString(name); + return syscall(SYS_GET_EVENT, service, id, 0, 0); +} + +void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { + syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); +} + +void fireEvent(uint32_t eventNumber, uint32_t data) { + fireEventCode(eventNumber, data, 0); +} + +void subscribeEvent(uint32_t service, uint32_t event, + void(handler)(void *, uint32_t)) { + syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); +} + +uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { + return syscall(SYS_AWAIT, service, event, code, 0); +} + +uint32_t await(uint32_t service, uint32_t event) { + return awaitCode(service, event, 0); +} + +uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { + return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); +} + +uint32_t createDirectEvent(uint32_t id) { + return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); +} + +uint32_t createDirectEventSave(uint32_t id) { + uint32_t existingEvent = getDirectEvent(getServiceId(), id); + if (existingEvent) { + return existingEvent; + } + return createDirectEvent(id); +} diff --git a/src/hlib/service/service.c b/src/hlib/service/service.c new file mode 100644 index 0000000..1669154 --- /dev/null +++ b/src/hlib/service/service.c @@ -0,0 +1,39 @@ +#include +#include +#include + +uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, + uintptr_t data2) { + return syscall(SYS_REQUEST, service, function, data1, data2); +} + +uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { + uintptr_t id = insertString(name); + return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); +} + +uint32_t getService(char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_SERVICE, id, 0, 0, 0); +} + +uint32_t getFunction(uint32_t module, char *name) { + uintptr_t id = insertString(name); + return syscall(SYS_GET_FUNCTION, module, id, 0, 0); +} + +uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } + +uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { + return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); +} + +void *getPhysicalAddress(void *source) { + return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | + (U32(source) & 0xFFF)); +} + +uint32_t fork(void (f)(), void *a, void *b, void *c) { + return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); +} + diff --git a/src/hlib/stdio.c b/src/hlib/stdio.c new file mode 100644 index 0000000..e717154 --- /dev/null +++ b/src/hlib/stdio.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char **write, uintptr_t x) { + if (x == 0) { + **write = HEX_CHARS[x]; + (*write)++; + **write = HEX_CHARS[x]; + (*write)++; + return; + } + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte >> 4]; + (*write)++; + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + } + } +} + +uint8_t hexLength(uintptr_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = sizeof(uintptr_t); position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00 && !alreadyWriting) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return MAX(size, 2); +} + +uint32_t power(uintptr_t x, uintptr_t y) { + uintptr_t result = 1; + for (uintptr_t i = 0; i < y; i++) { + result *= x; + } + return result; +} + +uint32_t intLength(intptr_t x) { + if (x == 0) { + return 1; + } + for (intptr_t i = 10; i >= 0; i--) { + if (x / power(10, i) > 0) { + return i + 1; + } + } + return 1; +} + +void addChar(char **write, char c) { + **write = c; + (*write)++; +} + +void putInt(char **write, intptr_t x) { + if (x == 0) { + addChar(write, '0'); + return; + } + if (x < 0) { + addChar(write, '-'); + x *= -1; + } + for (intptr_t i = 10; i >= 0; i--) { + uintptr_t n = x / power(10, i); + if (n) { + addChar(write, HEX_CHARS[n % 10]); + } + } +} + +void putPadding(char **write, uintptr_t x) { + x = MIN(x, 10); // max 10 wide padding + for (intptr_t i = 0; i < x; i++) { + addChar(write, ' '); + } +} + +uint32_t getInsertLength(char insertType, intptr_t x) { + switch (insertType) { + case 's': + return strlen((char *)x); + case 'x': + return hexLength(x); + case 'c': + return 1; + case 'i': + return intLength(x) + (x < 0); + case 'p': + return x; + } + return 0; +} + +void stringInsert(char **write, uintptr_t x) { + char *string = (char *)x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char **write, char insertType, uintptr_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + case 'c': + **write = x; + (*write)++; + return; + case 'i': + putInt(write, x); + return; + case 'p': + putPadding(write, x); + return; + } +} +uint32_t ioManager, logFunction; + +uint32_t printfSize(const char *format, va_list *valist) { + uint32_t size = 0; + for (; format[size] != 0; size++) { + if (format[size] == '%') { + char insertType = format[++size]; + size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); + continue; + } + } + return size; +} + +void _sprintf(char *data, const char *format, va_list *valist) { + char *write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); + continue; + } + *write = format[i]; + write++; + } +} + +void sprintf(char *data, const char *format, ...) { + va_list valist; + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); +} + +char *_asprintf(AllocationData allocationData, const char *format, ...) { + va_list valist; + va_start(valist, format); + uint32_t size = printfSize(format, &valist); + char *data = malloc(size); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + return data; +} + +void _printf(AllocationData allocationData, const char *format, ...) { + // I have absolutely no idea why this line fixes an issue where the first + // printf operation consistently doesn't correctly insert its string + free(malloc(1)); + va_list valist; + va_start(valist, format); + char *data = malloc(printfSize(format, &valist)); + va_start(valist, format); + _sprintf(data, format, &valist); + va_end(valist); + uintptr_t id = insertString(data); + request(ioManager, logFunction, id, 0); + discardString(id); + free(data); +} + +void gets(char *buffer) { + static uint32_t function = 0; + if (!function) { + function = getFunction(ioManager, "gets"); + } + uint32_t stringId = request(ioManager, function, 0, 0); + readString(stringId, buffer); +} diff --git a/src/hlib/strings.c b/src/hlib/strings.c new file mode 100644 index 0000000..78fff55 --- /dev/null +++ b/src/hlib/strings.c @@ -0,0 +1,38 @@ +#include +#include +#include + +uint32_t strlen(char *string) { + if (!string) { + return 0; + } + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + +uintptr_t insertString(char *string) { + return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); +} + +uintptr_t getStringLength(uintptr_t stringId) { + return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); +} + +void readString(uintptr_t stringId, void *buffer) { + syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); +} + +void discardString(uintptr_t stringId) { + syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); +} diff --git a/src/include/hlib.h b/src/include/hlib.h index a8da877..ed26b16 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -9,7 +9,7 @@ void *data; } ListElement; -#include "../userland/hlib/malloc.h" +#include "../hlib/malloc.h" #define PTR(x) ((void *)(uintptr_t)(x)) #define U32(x) ((uint32_t)(uintptr_t)(x)) diff --git a/src/userland/hlib/Makefile b/src/userland/hlib/Makefile deleted file mode 100644 index 4870f51..0000000 --- a/src/userland/hlib/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 -LD = i686-elf-ld -LD_FLAGS = -z max-page-size=0x1000 -AS = nasm -ASFlAGS = -felf32 - -BUILD_FOLDER = build - -SOURCE_FILES := $(shell find . -name "*.c" -or -name "*.asm") -OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) - -../../../initrd/hlib: $(OBJS) - @echo "linking the honey OS c libary" - @$(LD) $(LD_FLAGS) -o ../../../build/hlib.o $(OBJS) -T link.ld -r - @$(LD) $(LD_FLAGS) -o $@ $(OBJS) -T link.ld - -$(BUILD_FOLDER)/%.asm.o: %.asm - @echo "asembling $<" - @mkdir -p $(dir $@) - @$(AS) $(ASFlAGS) $< -o $@ - -$(BUILD_FOLDER)/%.c.o: %.c - @echo "compiling $<" - @mkdir -p $(dir $@) - @$(CC) $(CCFLAGS) -r $< -o $@ - -clean: - @echo "clearing build folder" - @rm -r $(BUILD_FOLDER) diff --git a/src/userland/hlib/compile_flags.txt b/src/userland/hlib/compile_flags.txt deleted file mode 100644 index a432e7b..0000000 --- a/src/userland/hlib/compile_flags.txt +++ /dev/null @@ -1,6 +0,0 @@ --I./include --I../../include -clang --fms-extensions --Wno-microsoft-anon-tag --Wno-incompatible-library-redeclaration diff --git a/src/userland/hlib/include/syscalls.h b/src/userland/hlib/include/syscalls.h deleted file mode 100644 index 2025b24..0000000 --- a/src/userland/hlib/include/syscalls.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SYSCALLS_H -#define SYSCALLS_H - -#include -#include - -typedef enum { - SYS_RUN = 0, - SYS_CREATE_FUNCTION = 1, - SYS_REQUEST = 2, - SYS_IO_IN = 3, - SYS_IO_OUT = 4, - SYS_LOAD_INITRD = 5, - SYS_GET_SERVICE = 6, - SYS_GET_FUNCTION = 7, - SYS_SUBSCRIBE_INTERRUPT = 8, - SYS_CREATE_EVENT = 9, - SYS_GET_EVENT = 10, - SYS_FIRE_EVENT = 11, - SYS_SUBSCRIBE_EVENT = 12, - SYS_GET_SERVICE_ID = 13, - SYS_INSERT_STRING = 14, - SYS_GET_STRING_LENGTH = 15, - SYS_READ_STRING = 16, - SYS_DISCARD_STRING = 17, - SYS_REQUEST_MEMORY = 18, - SYS_LOOKUP_SYMBOL = 19, - SYS_STACK_CONTAINS = 20, - SYS_AWAIT = 21, - SYS_GET_PHYSICAL = 22, - SYS_FORK = 23, -} SyscallIds; - -extern uint32_t getFunction(uint32_t module, char *name); - -#endif diff --git a/src/userland/hlib/io.c b/src/userland/hlib/io.c deleted file mode 100644 index 5a6c3f3..0000000 --- a/src/userland/hlib/io.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -uint32_t ioIn(uint16_t port, uint8_t size) { - return syscall(SYS_IO_IN, size, port, 0, 0); -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - syscall(SYS_IO_OUT, size, port, value, 0); -} - -void subscribeInterrupt(uint32_t intNo, void *handler) { - syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); -} diff --git a/src/userland/hlib/link.ld b/src/userland/hlib/link.ld deleted file mode 100644 index e38b0df..0000000 --- a/src/userland/hlib/link.ld +++ /dev/null @@ -1,12 +0,0 @@ -OUTPUT_ARCH(i386) - -SECTIONS { - . = 0xFF000000; - - .hlib : { - *(.text) - *(.rodata) - *(.data) - *(.bss) - } -} diff --git a/src/userland/hlib/list.c b/src/userland/hlib/list.c deleted file mode 100644 index ffc0ed6..0000000 --- a/src/userland/hlib/list.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -void _listAdd(AllocationData allocationData, ListElement **list, void *data) { - ListElement *element = malloc(sizeof(ListElement)); - element->data = data; - element->next = NULL; - if (!*list) { - *list = element; - return; - } - ListElement *current = *list; - while (current->next) { - current = current->next; - } - current->next = element; -} - -void *listPopFirst(ListElement **list) { - if (!*list) { - return NULL; - } - ListElement *resultElement = *list; - void *result = resultElement->data; - *list = (*list)->next; - free(resultElement); - return result; -} - -uint32_t listCount(ListElement *list) { - uint32_t i = 0; - foreach (list, void *, element, { i++; }) - ; - return i; -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -bool listRemoveValue(ListElement **list, void *value) { - if (!*list) { - return false; - } - ListElement *element = *list, *previous = NULL; - while (element) { - if (element->data == value) { - if (previous) { - previous->next = element->next; - } else { - *list = element->next; - } - free(element); - return true; - } - previous = element; - element = element->next; - } - return false; -} - -void listClear(ListElement **list, bool freeData) { - ListElement *current = *list; - if (!current) { - return; - } - while (current->next) { - if (freeData) { - free(current->data); - } - ListElement *next = current->next; - free(current); - current = next; - } - *list = NULL; -} diff --git a/src/userland/hlib/main.c b/src/userland/hlib/main.c deleted file mode 100644 index 43ac97d..0000000 --- a/src/userland/hlib/main.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "include/syscalls.h" -#include -#include - -uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, - uint32_t parameter2, uint32_t parameter3) { - uint32_t esp; - asm("push %%eax" ::"a"(&&end)); // end: return address - asm("mov %%esp, %%eax" : "=a"(esp)); - asm("sysenter\n" - : - : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), - "S"(parameter3), "D"(esp)); -// eax is set by the kernel as the return value -end: - // the 0x1C comes from the number of parameters / local variables do handle - // this function with care or it will break everything - asm("add $0x1C, %%esp\n" - "pop %%ebp\n" - "ret" ::); - // don't go here! ret returns with the correct value - return 0; -} - -uint32_t loadFromInitrd(char *name) { - uintptr_t id = insertString(name); - uint32_t service = syscall(SYS_GET_SERVICE, id, 0, 0, 0); - if (!service) { - return syscall(SYS_LOAD_INITRD, id, 1, 0, 0); - } - return service; -} - -uint32_t loadFromInitrdUninitialized(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_LOAD_INITRD, id, 0, 0, 0); -} - -void requestName(char *service, char *provider, uintptr_t data1, - uintptr_t data2) { - uint32_t serviceId = getService(service); - uint32_t providerId = getFunction(serviceId, provider); - request(serviceId, providerId, data1, data2); -} - -void *requestMemory(uint32_t pageCount, void *targetAddress, - void *physicalAddress) { - return PTR(syscall(SYS_REQUEST_MEMORY, pageCount, U32(targetAddress), - U32(physicalAddress), 0)); -} - -void *getPage() { return requestMemory(1, NULL, NULL); } - -void *getPagesCount(uint32_t count) { return requestMemory(count, NULL, NULL); } - -void freePage(void *location) {} - -void memset(void *_target, uint8_t byte, uint32_t size) { - uint8_t *target = _target; - for (uint32_t i = 0; i < size; i++) { - *target = byte; - target++; - } -} - -bool stackContains(uint32_t serviceId) { - return syscall(SYS_STACK_CONTAINS, serviceId, 0, 0, 0); -} - -#define REQUEST1(returnType, functionName, service, function) \ - returnType functionName(uint32_t data) { \ - static uint32_t serviceId = 0; \ - if (!serviceId) { \ - serviceId = getService(service); \ - serviceId = getService(service); \ - } \ - static uint32_t functionId = 0; \ - if (!functionId) { \ - functionId = getFunction(serviceId, function); \ - } \ - return (returnType)request(serviceId, functionId, data, 0); \ - } - -REQUEST1(void, sleep, "pit", "sleep") diff --git a/src/userland/hlib/malloc.c b/src/userland/hlib/malloc.c deleted file mode 120000 index 022d82b..0000000 --- a/src/userland/hlib/malloc.c +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.c \ No newline at end of file diff --git a/src/userland/hlib/malloc.h b/src/userland/hlib/malloc.h deleted file mode 120000 index 8a56b0a..0000000 --- a/src/userland/hlib/malloc.h +++ /dev/null @@ -1 +0,0 @@ -../../kernel/memory/malloc.h \ No newline at end of file diff --git a/src/userland/hlib/service/events.c b/src/userland/hlib/service/events.c deleted file mode 100644 index 9429c44..0000000 --- a/src/userland/hlib/service/events.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -uint32_t createEvent(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); -} - -uintptr_t hashString(char *string) { - uintptr_t hash = 0; - for (uintptr_t i = 0; string[i]; i++) { - hash = 257 * hash + string[i]; - } - return hash; -} - -uint32_t getEvent(uint32_t service, char *name) { - uintptr_t id = hashString(name); - return syscall(SYS_GET_EVENT, service, id, 0, 0); -} - -void fireEventCode(uint32_t eventNumber, uint32_t data, uint32_t code) { - syscall(SYS_FIRE_EVENT, eventNumber, data, code, 0); -} - -void fireEvent(uint32_t eventNumber, uint32_t data) { - fireEventCode(eventNumber, data, 0); -} - -void subscribeEvent(uint32_t service, uint32_t event, - void(handler)(void *, uint32_t)) { - syscall(SYS_SUBSCRIBE_EVENT, service, event, U32(handler), 0); -} - -uint32_t awaitCode(uint32_t service, uint32_t event, uint32_t code) { - return syscall(SYS_AWAIT, service, event, code, 0); -} - -uint32_t await(uint32_t service, uint32_t event) { - return awaitCode(service, event, 0); -} - -uint32_t getDirectEvent(uint32_t serviceId, uint32_t id) { - return syscall(SYS_GET_EVENT, serviceId, id, 0, 0); -} - -uint32_t createDirectEvent(uint32_t id) { - return syscall(SYS_CREATE_EVENT, id, 0, 0, 0); -} - -uint32_t createDirectEventSave(uint32_t id) { - uint32_t existingEvent = getDirectEvent(getServiceId(), id); - if (existingEvent) { - return existingEvent; - } - return createDirectEvent(id); -} diff --git a/src/userland/hlib/service/service.c b/src/userland/hlib/service/service.c deleted file mode 100644 index 1669154..0000000 --- a/src/userland/hlib/service/service.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include - -uint32_t request(uint32_t service, uint32_t function, uintptr_t data1, - uintptr_t data2) { - return syscall(SYS_REQUEST, service, function, data1, data2); -} - -uint32_t createFunction(char *name, int32_t(handler)(void *, uint32_t)) { - uintptr_t id = insertString(name); - return syscall(SYS_CREATE_FUNCTION, id, U32(handler), 0, 0); -} - -uint32_t getService(char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_GET_SERVICE, id, 0, 0, 0); -} - -uint32_t getFunction(uint32_t module, char *name) { - uintptr_t id = insertString(name); - return syscall(SYS_GET_FUNCTION, module, id, 0, 0); -} - -uint32_t getServiceId() { return syscall(SYS_GET_SERVICE_ID, 0, 0, 0, 0); } - -uint32_t lookupSymbol(uint32_t serviceId, uint32_t address) { - return syscall(SYS_LOOKUP_SYMBOL, serviceId, address, 0, 0); -} - -void *getPhysicalAddress(void *source) { - return PTR(syscall(SYS_GET_PHYSICAL, U32(source) & ~0xFFF, 0, 0, 0) | - (U32(source) & 0xFFF)); -} - -uint32_t fork(void (f)(), void *a, void *b, void *c) { - return syscall(SYS_FORK, U32(f), U32(a), U32(b), U32(c)); -} - diff --git a/src/userland/hlib/stdio.c b/src/userland/hlib/stdio.c deleted file mode 100644 index e717154..0000000 --- a/src/userland/hlib/stdio.c +++ /dev/null @@ -1,207 +0,0 @@ -#include -#include -#include -#include - -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char **write, uintptr_t x) { - if (x == 0) { - **write = HEX_CHARS[x]; - (*write)++; - **write = HEX_CHARS[x]; - (*write)++; - return; - } - bool alreadyWriting = false; - for (int position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00 && !alreadyWriting) { - alreadyWriting = true; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte >> 4]; - (*write)++; - **write = HEX_CHARS[byte & 0x0F]; - (*write)++; - } - } -} - -uint8_t hexLength(uintptr_t x) { - bool alreadyWriting = false; - uint8_t size = 0; - for (int position = sizeof(uintptr_t); position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00 && !alreadyWriting) { - alreadyWriting = true; - } - if (alreadyWriting) { - size += 2; - } - } - return MAX(size, 2); -} - -uint32_t power(uintptr_t x, uintptr_t y) { - uintptr_t result = 1; - for (uintptr_t i = 0; i < y; i++) { - result *= x; - } - return result; -} - -uint32_t intLength(intptr_t x) { - if (x == 0) { - return 1; - } - for (intptr_t i = 10; i >= 0; i--) { - if (x / power(10, i) > 0) { - return i + 1; - } - } - return 1; -} - -void addChar(char **write, char c) { - **write = c; - (*write)++; -} - -void putInt(char **write, intptr_t x) { - if (x == 0) { - addChar(write, '0'); - return; - } - if (x < 0) { - addChar(write, '-'); - x *= -1; - } - for (intptr_t i = 10; i >= 0; i--) { - uintptr_t n = x / power(10, i); - if (n) { - addChar(write, HEX_CHARS[n % 10]); - } - } -} - -void putPadding(char **write, uintptr_t x) { - x = MIN(x, 10); // max 10 wide padding - for (intptr_t i = 0; i < x; i++) { - addChar(write, ' '); - } -} - -uint32_t getInsertLength(char insertType, intptr_t x) { - switch (insertType) { - case 's': - return strlen((char *)x); - case 'x': - return hexLength(x); - case 'c': - return 1; - case 'i': - return intLength(x) + (x < 0); - case 'p': - return x; - } - return 0; -} - -void stringInsert(char **write, uintptr_t x) { - char *string = (char *)x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - (*write)++; - } -} - -void handleInsert(char **write, char insertType, uintptr_t x) { - switch (insertType) { - case 's': - stringInsert(write, x); - return; - case 'x': - putHex(write, x); - return; - case 'c': - **write = x; - (*write)++; - return; - case 'i': - putInt(write, x); - return; - case 'p': - putPadding(write, x); - return; - } -} -uint32_t ioManager, logFunction; - -uint32_t printfSize(const char *format, va_list *valist) { - uint32_t size = 0; - for (; format[size] != 0; size++) { - if (format[size] == '%') { - char insertType = format[++size]; - size += getInsertLength(insertType, va_arg(*valist, uintptr_t)); - continue; - } - } - return size; -} - -void _sprintf(char *data, const char *format, va_list *valist) { - char *write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(*valist, uintptr_t)); - continue; - } - *write = format[i]; - write++; - } -} - -void sprintf(char *data, const char *format, ...) { - va_list valist; - va_start(valist, format); - _sprintf(data, format, &valist); - va_end(valist); -} - -char *_asprintf(AllocationData allocationData, const char *format, ...) { - va_list valist; - va_start(valist, format); - uint32_t size = printfSize(format, &valist); - char *data = malloc(size); - va_start(valist, format); - _sprintf(data, format, &valist); - va_end(valist); - return data; -} - -void _printf(AllocationData allocationData, const char *format, ...) { - // I have absolutely no idea why this line fixes an issue where the first - // printf operation consistently doesn't correctly insert its string - free(malloc(1)); - va_list valist; - va_start(valist, format); - char *data = malloc(printfSize(format, &valist)); - va_start(valist, format); - _sprintf(data, format, &valist); - va_end(valist); - uintptr_t id = insertString(data); - request(ioManager, logFunction, id, 0); - discardString(id); - free(data); -} - -void gets(char *buffer) { - static uint32_t function = 0; - if (!function) { - function = getFunction(ioManager, "gets"); - } - uint32_t stringId = request(ioManager, function, 0, 0); - readString(stringId, buffer); -} diff --git a/src/userland/hlib/strings.c b/src/userland/hlib/strings.c deleted file mode 100644 index 78fff55..0000000 --- a/src/userland/hlib/strings.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include - -uint32_t strlen(char *string) { - if (!string) { - return 0; - } - uint32_t size = 0; - while (*string) { - string++; - size++; - } - return size; -} - -void memcpy(void *from, void *to, uint32_t size) { - uint8_t *a = from, *b = to; - for (uint32_t i = 0; i < size; i++) { - b[i] = a[i]; - } -} - -uintptr_t insertString(char *string) { - return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); -} - -uintptr_t getStringLength(uintptr_t stringId) { - return syscall(SYS_GET_STRING_LENGTH, stringId, 0, 0, 0); -} - -void readString(uintptr_t stringId, void *buffer) { - syscall(SYS_READ_STRING, stringId, U32(buffer), 0, 0); -} - -void discardString(uintptr_t stringId) { - syscall(SYS_DISCARD_STRING, stringId, 0, 0, 0); -}