diff --git a/.gitmodules b/.gitmodules index d00defe..9af33af 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "boot/platform/uefi/libefi"] path = boot/platform/uefi/libefi - url = https://github.com/aurixos/efi + url = https://git.piraterna.org/Piraterna/libsefi diff --git a/Brewfile b/Brewfile index 993024a..afff3ac 100644 --- a/Brewfile +++ b/Brewfile @@ -10,6 +10,7 @@ brew "make" brew "gptfdisk" brew "xorriso" brew "qemu" +brew "ffmpeg" brew "llvm" brew "lld" brew "util-linux" if OS.mac? diff --git a/Makefile b/Makefile index eb93a78..2582f48 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ export BUILD_DIR ?= $(ROOT_DIR)/build export SYSROOT_DIR ?= $(ROOT_DIR)/sysroot export RELEASE_DIR ?= $(ROOT_DIR)/release -NOUEFI ?= n +export NOUEFI ?= n ## # Image generation and running @@ -43,7 +43,16 @@ LIVECD := $(RELEASE_DIR)/aurix-$(GITREV)-livecd_$(ARCH)-$(PLATFORM).iso LIVEHDD := $(RELEASE_DIR)/aurix-$(GITREV)-livehdd_$(ARCH)-$(PLATFORM).img LIVESD := $(RELEASE_DIR)/aurix-$(GITREV)-livesd_$(ARCH)-$(PLATFORM).img -QEMU_FLAGS := -m 2G -smp 4 -serial stdio +QEMU_FLAGS := -m 2G -smp 4 -rtc base=localtime -serial stdio + +# QEMU Audio support +#QEMU_FLAGS += -audiodev coreaudio,id=coreaudio0 -device ich9-intel-hda -device hda-output,audiodev=coreaudio0 + +# QEMU Mouse support +QEMU_FLAGS += -usb -device usb-mouse + +# x86_64 +QEMU_FLAGS += -machine q35 ## # General info @@ -75,16 +84,7 @@ all: boot kernel .PHONY: boot boot: @printf ">>> Building bootloader...\n" -ifneq (,$(filter $(ARCH),i686 x86_64)) - @$(MAKE) -C boot PLATFORM=pc-bios -else - @$(MAKE) -C boot -endif -ifneq (,$(filter $(ARCH),i686 x86_64 arm32 aarch64)) -ifeq ($(NOUEFI),n) - @$(MAKE) -C boot PLATFORM=uefi -endif -endif + @$(MAKE) -C boot all .PHONY: kernel kernel: @@ -142,6 +142,7 @@ run-uefi: livecd ovmf .PHONY: clean clean: + @$(MAKE) -C boot clean @rm -rf $(BUILD_DIR) $(SYSROOT_DIR) .PHONY: distclean diff --git a/boot/.gitignore b/boot/.gitignore new file mode 100644 index 0000000..64c59cb --- /dev/null +++ b/boot/.gitignore @@ -0,0 +1 @@ +include/sounds \ No newline at end of file diff --git a/boot/Makefile b/boot/Makefile index ea5ec46..e1fb122 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -40,13 +40,37 @@ CFLAGS += -O2 endif .PHONY: all -all: +all: sounds +ifneq (,$(filter $(ARCH),i686 x86_64)) + @$(MAKE) -C platform/pc-bios all +else @$(MAKE) -C platform/$(PLATFORM) all +endif +ifneq (,$(filter $(ARCH),i686 x86_64 arm32 aarch64)) +ifeq ($(NOUEFI),n) + @$(MAKE) -C platform/uefi all +# @$(MAKE) -C drivers all +endif +endif + +.PHONY: sounds +sounds: + @mkdir -p $(BUILD_DIR)/boot/sounds + @mkdir -p $(BOOT_ROOT)/include/sounds + @for f in $(BOOT_ROOT)/sound/*.mp3; do \ + file=$$(basename $$f ".$${f##*.}") ; \ + printf " GEN\t$$file.h\n" ; \ + ffmpeg -i "$$f" -acodec pcm_s16le -f s16le -ac 2 "$(BUILD_DIR)/boot/sounds/$$file.raw" -y 2>/dev/null ; \ + python3 $(ROOT_DIR)/utils/bin_to_header.py "$(BUILD_DIR)/boot/sounds/$$file.raw" "$(BOOT_ROOT)/include/sounds/$$file.h" $$file ; \ + done .PHONY: install install: @$(MAKE) -C platform/$(PLATFORM) install +# @$(MAKE) -C drivers install + @mkdir -p $(SYSROOT_DIR)/AxBoot + @cp -r base/* $(SYSROOT_DIR)/AxBoot .PHONY: clean clean: - @$(MAKE) -C platform/$(PLATFORM) clean + @rm -rf $(BOOT_ROOT)/include/sounds diff --git a/boot/arch/x86_64/common/uart/uart.c b/boot/arch/x86_64/common/uart/uart.c new file mode 100644 index 0000000..7403a78 --- /dev/null +++ b/boot/arch/x86_64/common/uart/uart.c @@ -0,0 +1,56 @@ +/*********************************************************************************/ +/* Module Name: uart.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include + +#include +#include + +#define COM1 0x3f8 + +void uart_init(uint32_t baud_rate) +{ + uint8_t divisor = 115200 / baud_rate; + + outb(COM1 + 1, 0x00); + outb(COM1 + 3, 0x80); + outb(COM1 + 0, divisor & 0xFF); + outb(COM1 + 1, (divisor >> 8) & 0xFF); + outb(COM1 + 3, 0x03); + outb(COM1 + 2, 0xC7); + outb(COM1 + 4, 0x0B); + outb(COM1 + 4, 0x0F); +} + +void uart_send(char c) +{ + while ((inb(COM1 + 5) & 0x20) == 0); + outb(COM1, c); +} + +void uart_sendstr(char *str) +{ + while (*str != '\0') { + if (*str == '\n') { + uart_send('\r'); + } + uart_send(*str); + str++; + } +} \ No newline at end of file diff --git a/boot/base/axboot.cfg b/boot/base/axboot.cfg index ccfec46..0de7fe4 100644 --- a/boot/base/axboot.cfg +++ b/boot/base/axboot.cfg @@ -1,12 +1,13 @@ -; This is a comment +;; please leave this here, the parser breaks without it -entry "AurixOS" { - PROTOCOL="aurix" - IMAGE_PATH="boot:///System/axkrnl.sys" -} +default = 0 +timeout = 30 +ui = text -;; UEFI only -entry "Windows" { - PROTOCOL="chainload" - IMAGE_PATH="boot:///EFI/Microsoft/bootmgfw.efi" -} +[AurixOS] +protocol = aurix +image = boot:///System/axkrnl.sys + +[Windows 10] +protocol = efi-chainload +image = boot:///EFI/Microsoft/bootmgfw.efi \ No newline at end of file diff --git a/boot/base/fonts/u_vga16/u_vga16.sfn b/boot/base/fonts/u_vga16/u_vga16.sfn new file mode 100644 index 0000000..5d5a4d0 Binary files /dev/null and b/boot/base/fonts/u_vga16/u_vga16.sfn differ diff --git a/boot/base/fonts/vera/Vera.sfn b/boot/base/fonts/vera/Vera.sfn new file mode 100644 index 0000000..4c4b0f3 Binary files /dev/null and b/boot/base/fonts/vera/Vera.sfn differ diff --git a/boot/common/config/config.c b/boot/common/config/config.c index 1fef728..c0d5a21 100644 --- a/boot/common/config/config.c +++ b/boot/common/config/config.c @@ -17,7 +17,10 @@ /* SOFTWARE. */ /*********************************************************************************/ +#include +#include #include +#include #include #include #include @@ -26,20 +29,51 @@ #include #include +#define DEFAULT_ENTRY 0 +// default timeout of 0 disables the UI entirely, which is essentialy what *should* happen now since the UI +// is... in a catastrophic state. Just remember to set this back to 30 once the UI is ready +#define DEFAULT_TIMEOUT 0 +// #define DEFAULT_TIMEOUT 30 + char *config_paths[] = { + "\\AxBoot\\axboot.cfg", "\\axboot.cfg", - "\\System\\axboot.cfg", "\\EFI\\axboot.cfg", "\\EFI\\BOOT\\axboot.cfg", }; +struct axboot_cfg cfg = { + .default_entry = DEFAULT_ENTRY, + .timeout = DEFAULT_TIMEOUT, + .ui_mode = UI_TEXT, + + //.entry_count = 0 + .entry_count = 2 +}; + +struct axboot_entry entries[2] = { + { + .name = "AurixOS", + .description = "Boot the Aurix Operating System", + .image_path = "\\System\\axkrnl", + .protocol = PROTO_AURIX + }, + { + .name = "Windows 10", + .description = "", + .image_path = "\\EFI\\Microsoft\\bootmgfw.efi", + .protocol = PROTO_CHAINLOAD + } +}; + + void config_init(void) { - char *config_buf; + char *config_buf = NULL; uint8_t open = 0; for (size_t i = 0; i < ARRAY_LENGTH(config_paths); i++) { - vfs_read("\\System\\axkrnl", &config_buf); + vfs_read(config_paths[i], &config_buf); if (config_buf != NULL) { open = 1; break; @@ -52,7 +86,30 @@ void config_init(void) while (1); } - // TODO: parse configuration file - mem_free(config_buf); +} + +int config_get_timeout() +{ + return cfg.timeout; +} + +int config_get_default() +{ + return cfg.default_entry; +} + +int config_get_entry_count() +{ + return cfg.entry_count; +} + +struct axboot_entry *config_get_entries() +{ + return entries; +} + +int config_get_ui_mode() +{ + return cfg.ui_mode; } \ No newline at end of file diff --git a/boot/common/data/list.c b/boot/common/data/list.c new file mode 100644 index 0000000..9fa15fd --- /dev/null +++ b/boot/common/data/list.c @@ -0,0 +1,130 @@ +/*********************************************************************************/ +/* Module Name: list.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include +#include +#include + +#include + +List *list_new() +{ + List *list = (List *)mem_alloc(sizeof(List)); + if (!list) { + debug("list_new(): Failed to allocate memory for new list!\n"); + return NULL; + } + + list->count = 0; + list->root = (ListNode *)0; + + return list; +} + +ListNode *listnode_new(void *data) +{ + ListNode *ln = (ListNode *)mem_alloc(sizeof(ListNode)); + if (!ln) { + debug("listnode_new(): Failed to allocate memory for new list node!\n"); + return NULL; + } + + ln->prev = (ListNode *)0; + ln->next = (ListNode *)0; + ln->data = data; + + return ln; +} + +int list_add(List *list, void *data) +{ + ListNode *node = listnode_new(data); + if (!node) { + return false; + } + + if (!list->root) { + list->root = node; + } else { + ListNode *cur = list->root; + + while (cur->next) { + cur = cur->next; + } + + cur->next = node; + node->prev = cur; + } + + list->count++; + return true; +} + +void *list_remove_at(List *list, uint32_t idx) +{ + void *data; + + if (!list || list->count == 0 || idx >= list->count) { + return NULL; + } + + ListNode *cur = list->root; + + for (uint32_t i = 0; (i < idx) && cur; i++) { + cur = cur->next; + } + + if (!cur) { + return NULL; + } + + data = cur->data; + + if (cur->prev) { + cur->prev->next = cur->next; + } + + if (cur->next) { + cur->next->prev = cur->prev; + } + + if (idx == 0) { + list->root = cur->next; + } + + mem_free(cur); + + list->count--; + return data; +} + +void *list_get_at(List *list, uint32_t idx) +{ + if (!list || list->count == 0 | idx >= list->count) { + return NULL; + } + + ListNode *cur = list->root; + + for (uint32_t i = 0; (i < idx) && cur; i++) { + cur = cur->next; + } + + return cur ? cur->data : NULL; +} \ No newline at end of file diff --git a/boot/common/i18n/cs_CZ.c b/boot/common/i18n/cs_CZ.c new file mode 100644 index 0000000..754544d --- /dev/null +++ b/boot/common/i18n/cs_CZ.c @@ -0,0 +1,29 @@ +/*********************************************************************************/ +/* Module Name: cs_CZ.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include + +struct language i18n_csCZ = { + .shutdown = "Vypnout", + .reboot = "Restartovat", + .reboot_to_firmware = "Přejít do nastavení firmwaru", + .resolution = "Rozlišení", + + .language = "Jazyk" +}; diff --git a/boot/common/i18n/en_US.c b/boot/common/i18n/en_US.c new file mode 100644 index 0000000..629e26b --- /dev/null +++ b/boot/common/i18n/en_US.c @@ -0,0 +1,29 @@ +/*********************************************************************************/ +/* Module Name: en_US.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include + +struct language i18n_enUS = { + .shutdown = "Shutdown", + .reboot = "Reboot", + .reboot_to_firmware = "Reboot to Firmware", + .resolution = "Resolution", + + .language = "Language" +}; diff --git a/boot/common/i18n/i18n.c b/boot/common/i18n/i18n.c new file mode 100644 index 0000000..c2860a1 --- /dev/null +++ b/boot/common/i18n/i18n.c @@ -0,0 +1,38 @@ +/*********************************************************************************/ +/* Module Name: i18n.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include + +extern struct language i18n_csCZ; +extern struct language i18n_enUS; + +struct language_selection i18n_languages[] = { + { + "Čeština", + "cs_CZ", + &i18n_csCZ + }, + { + "English", + "en_US", + &i18n_enUS + } +}; + +struct language_selection *i18n_curlang = &i18n_languages[1]; // english \ No newline at end of file diff --git a/boot/common/init.c b/boot/common/init.c index 6ef4552..00f337f 100644 --- a/boot/common/init.c +++ b/boot/common/init.c @@ -17,21 +17,50 @@ /* SOFTWARE. */ /*********************************************************************************/ -#include -#include -#include +#include +#include #include +#include +#include +#include +#include #include void axboot_init() { + uart_init(115200); + if (!vfs_init("\\")) { debug("axboot_init(): Failed to mount boot drive! Halting...\n"); // TODO: Halt while (1); } - aurix_load("\\System\\axkrnl"); +#ifdef AXBOOT_UEFI +#include + load_drivers(); +#endif - while (1); + //config_init(); + + // boot straight away + if (config_get_timeout() < 1) { + struct axboot_entry *entries = config_get_entries(); + loader_load(&(entries[config_get_default()])); + } + + ui_init(); + + debug("axboot_init(): Returned from main menu, something went wrong. Halting!"); + //UNREACHABLE(); + + // just boot aurixos for now + struct axboot_entry axos = { + .name = "AurixOS", + .description = "", + .image_path = "\\System\\axkrnl", + .protocol = PROTO_AURIX + }; + loader_load(&axos); + UNREACHABLE(); } \ No newline at end of file diff --git a/boot/common/lib/string.c b/boot/common/lib/string.c index 533806f..816bbe8 100644 --- a/boot/common/lib/string.c +++ b/boot/common/lib/string.c @@ -143,6 +143,38 @@ char *strcpy(char *dest, const char *src) return pdest; } +char *strncpy(char *dest, const char *src, size_t n) +{ + if (dest == NULL || src == NULL) { + return NULL; + } + + char *pdest = dest; + + while (*src != '\0' || n--) { + *pdest++ = *src++; + } + + *pdest = '\0'; + return dest; +} + +char *strncat(char *dest, const char *src, size_t n) +{ + if (dest == 0 || src == 0) { + return NULL; + } + + size_t i = strlen(dest); + size_t a = 0; + + while (a < n && src[a] != '\0') { + dest[i++] = src[a++]; + } + dest[i] = '\0'; + return dest; +} + // TODO: Get rid of this function char *strdup(const char *s) { diff --git a/boot/common/loader/loader.c b/boot/common/loader/loader.c new file mode 100644 index 0000000..4033534 --- /dev/null +++ b/boot/common/loader/loader.c @@ -0,0 +1,58 @@ +/*********************************************************************************/ +/* Module Name: loader.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include +#include +#include +#include +#include +#include + +int proto_str_to_int(char *proto) +{ + if (strcmp(proto, "aurix") == 0) { + return PROTO_AURIX; + } + +#ifdef AXBOOT_UEFI + if (strcmp(proto, "efi-chainload") == 0) { + return PROTO_CHAINLOAD; + } +#endif + + return PROTO_UNSUPPORTED; +} + +void loader_load(struct axboot_entry *entry) +{ + debug("loader_load(): Booting \"%s\"...\n", entry->name); + + switch (entry->protocol) { + case PROTO_AURIX: { + aurix_load(entry->image_path); + break; + } + default: { + debug("Entry doesn't have a supported protocol!\n"); + break; + } + } + + UNREACHABLE(); +} \ No newline at end of file diff --git a/boot/common/mm/mman.c b/boot/common/mm/mman.c index ea4490a..b76056b 100644 --- a/boot/common/mm/mman.c +++ b/boot/common/mm/mman.c @@ -113,6 +113,7 @@ void *mem_alloc(size_t n) add_alloc(alloc, n); + debug("mem_alloc(): Allocated %u bytes\n", n); return alloc; } @@ -122,7 +123,7 @@ int mem_allocat(void *addr, size_t npages) status = gBootServices->AllocatePages(AllocateAddress, EfiLoaderData, (EFI_UINTN)npages, addr); if (EFI_ERROR(status)) { - debug("mem_allocat(): Couldn't allocate %u bytes at 0x%lx: %s (%lx)\n", npages, addr, efi_status_to_str(status), status); + debug("mem_allocat(): Couldn't allocate %u pages at 0x%lx: %s (%lx)\n", npages, addr, efi_status_to_str(status), status); return 0; } @@ -137,9 +138,9 @@ void *mem_realloc(void *addr, size_t n) void *new = NULL; int i = find_alloc(addr); - if (i == -1) { - debug("mem_realloc(): Couldn't find allocation for 0x%lx.\n"); - return NULL; + if (i == -1 || addr == NULL) { + debug("mem_realloc(): Couldn't find allocation for 0x%lx, allocating new memory.\n"); + return mem_alloc(n); } old_size = allocation_list[i].size; @@ -169,6 +170,8 @@ void mem_free(void *addr) return; } + debug("mem_free(): Freed 0x%llx\n", addr); + remove_alloc(addr); } diff --git a/boot/common/print.c b/boot/common/print.c index 93553c7..758706a 100644 --- a/boot/common/print.c +++ b/boot/common/print.c @@ -19,13 +19,14 @@ #define NANOPRINTF_IMPLEMENTATION #define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1 -#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 0 +#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1 #define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1 #define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 0 #include +#include #include #include @@ -46,10 +47,7 @@ void log(const char *fmt, ...) npf_vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); -// TODO: Get rid of this -#ifdef AXBOOT_UEFI - printstr(buf); -#endif + uart_sendstr(buf); } void debug(const char *fmt, ...) @@ -61,15 +59,19 @@ void debug(const char *fmt, ...) npf_vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); -#ifdef AXBOOT_UEFI - printstr(buf); -#endif + uart_sendstr(buf); } void snprintf(char *buf, size_t size, const char *fmt, ...) { va_list args; + va_start(args, fmt); npf_vsnprintf(buf, size, fmt, args); va_end(args); -} \ No newline at end of file +} + +void vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + npf_vsnprintf(buf, size, fmt, args); +} diff --git a/boot/common/proto/aurix.c b/boot/common/proto/aurix.c index 5c79856..c45d740 100644 --- a/boot/common/proto/aurix.c +++ b/boot/common/proto/aurix.c @@ -44,12 +44,13 @@ void aurix_load(char *kernel_path) // TODO: Halt while (1); } - + axboot_memmap *memmap = get_memmap(pm); + (void)memmap; map_pages(pm, (uintptr_t)pm, (uintptr_t)pm, PAGE_SIZE, VMM_WRITABLE); map_pages(pm, (uintptr_t)_aurix_handoff_start, (uintptr_t)_aurix_handoff_start, (uint64_t)_aurix_handoff_end - (uint64_t)_aurix_handoff_start, 0); - + void *stack = mem_alloc(16*1024); // 16 KiB stack should be well more than enough if (!stack) { debug("aurix_load(): Failed to allocate stack! Halting...\n"); @@ -61,11 +62,12 @@ void aurix_load(char *kernel_path) void *kernel_entry = (void *)elf_load(kbuf, pm); if (!kernel_entry) { debug("aurix_load(): Failed to load '%s'! Halting...\n", kernel_path); - mem_free(kbuf); while (1); } + // mem_free(kbuf); void *parameters = NULL; + (void)parameters; debug("aurix_load(): Handoff state: pm=0x%llx, stack=0x%llx, kernel_entry=0x%llx\n", pm, stack, kernel_entry); @@ -76,6 +78,6 @@ void aurix_load(char *kernel_path) __asm__ volatile("movq %[pml4], %%cr3\n" "movq %[stack], %%rsp\n" "callq *%[entry]\n" - :: [pml4]"r"(pm), [stack]"r"(stack), [entry]"r"(kernel_entry) : "memory"); + :: [pml4]"r"(pm), [stack]"r"(stack + (16 * 1024)), [entry]"r"(kernel_entry) : "memory"); __builtin_unreachable(); } diff --git a/boot/common/ui/font.c b/boot/common/ui/font.c new file mode 100644 index 0000000..e184f75 --- /dev/null +++ b/boot/common/ui/font.c @@ -0,0 +1,91 @@ +/*********************************************************************************/ +/* Module Name: font.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include +#include +#include +#include +#define FONT_IMPLEMENTATION +#include +#include +#include +#include +#include +#include + +bool font_init(struct ui_context *ctx, char *font_path, int size) +{ + vfs_read(font_path, &(ctx->font_file)); + if (!ctx->font_file) { + return false; + } + + int ssfn_status; + + ssfn_status = ssfn_load(&(ctx->font), (void *)(ctx->font_file)); + if (ssfn_status != SSFN_OK) { + debug("font_init(): SSFN failed to load font: %s!\n", ssfn_error(ssfn_status)); + goto error; + } + + ssfn_status = ssfn_select(&(ctx->font), SSFN_FAMILY_ANY, NULL, SSFN_STYLE_REGULAR, size); + if (ssfn_status != SSFN_OK) { + debug("font_init(): SSFN failed to select font: %s!\n", ssfn_error(ssfn_status)); + goto error; + } + + // initialize terminal + ctx->terminal.font_size = size; + ctx->terminal.cx = 0; + ctx->terminal.cy = size; + + return true; + +error: + mem_free(ctx->font_file); + return false; +} + +void font_write(struct ui_context *ctx, char *s, uint32_t cx, uint32_t cy) +{ + ctx->font_buf.x = cx; + ctx->font_buf.y = cy; + ssfn_render(&(ctx->font), &(ctx->font_buf), s); +} + +void font_free(struct ui_context *ctx) +{ + ssfn_free(&(ctx->font)); + mem_free(ctx->font_file); +} + +/* +void font_ttf_init(char *font_path, int initial_size) +{ + vfs_read(font_path, (char **)&font_buf); + if (!font_buf) { + debug("Font not loaded, returning...\n"); + return; + } +} + +void font_psf2_init() +{ +} +*/ \ No newline at end of file diff --git a/boot/common/ui/terminal.c b/boot/common/ui/terminal.c new file mode 100644 index 0000000..f65e3c3 --- /dev/null +++ b/boot/common/ui/terminal.c @@ -0,0 +1,86 @@ +/*********************************************************************************/ +/* Module Name: terminal.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include +#include +#include +#include + +#include + +#define HORIZONTAL_TAB_WIDTH 8 + +void terminal_print(struct ui_context *ctx, char *fmt, ...) +{ + va_list args; + char buf[4096] = {0}; + char *s = (char *)&buf; + + va_start(args, fmt); + vsnprintf((char *)&buf, sizeof(buf), fmt, args); + va_end(args); + + while (*s) { + switch (*s) { + case '\t': { + // horizontal tab - 4 spaces + int w, h; + ssfn_bbox(&(ctx->font), " ", &w, &h, NULL, NULL); + if (ctx->terminal.cx >= ctx->fb_modes[ctx->current_mode].width - (w * HORIZONTAL_TAB_WIDTH)) { + for (int i = 1; i <= HORIZONTAL_TAB_WIDTH; i++) { + if (ctx->terminal.cx >= ctx->fb_modes[ctx->current_mode].width - (w * i)) { + ctx->terminal.cx = ((HORIZONTAL_TAB_WIDTH * (w + 1)) - (w * i)); + ctx->terminal.cy += h; + break; + } + } + } else { + ctx->terminal.cx += w * HORIZONTAL_TAB_WIDTH; + } + break; + } + case '\n': { + // newline + ctx->terminal.cx = 0; + ctx->terminal.cy += ctx->terminal.font_size; + break; + } + default: { + // printable character + const char str[2] = {*s, 0}; + int w, h; + ssfn_bbox(&(ctx->font), (char *)&str, &w, &h, NULL, NULL); + if (ctx->terminal.cx + w >= ctx->fb_modes[ctx->current_mode].width) { + ctx->terminal.cx = 0; + ctx->terminal.cy += h; + } + font_write(ctx, (char *)&str, ctx->terminal.cx, ctx->terminal.cy); + ctx->terminal.cx += w; + break; + } + } + s++; + } +} + +void terminal_setcur(struct ui_context *ui, uint32_t x, uint32_t y) +{ + ui->terminal.cx = x; + ui->terminal.cy = y; +} diff --git a/boot/common/ui/ui.c b/boot/common/ui/ui.c new file mode 100644 index 0000000..80c5239 --- /dev/null +++ b/boot/common/ui/ui.c @@ -0,0 +1,290 @@ +/*********************************************************************************/ +/* Module Name: ui.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include