diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index e962eb71..3fd6d465 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -124,9 +124,7 @@ jobs: sudo apt update sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo make --quiet -C tools do_limine - make --quiet -C Drivers prepare - make --quiet -C Userspace prepare - make --quiet -C Kernel prepare + make --quiet prepare - name: Cache cross id: cache-cross @@ -187,9 +185,7 @@ jobs: sudo apt update sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 make --quiet -C tools do_limine - make --quiet -C Drivers prepare - make --quiet -C Userspace prepare - make --quiet -C Kernel prepare + make --quiet prepare - name: Cache cross Folder id: cache-cross @@ -236,9 +232,7 @@ jobs: sudo apt update sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 make --quiet -C tools do_limine - make --quiet -C Drivers prepare - make --quiet -C Userspace prepare - make --quiet -C Kernel prepare + make --quiet prepare - name: Cache cross Folder id: cache-cross @@ -285,9 +279,7 @@ jobs: sudo apt update sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 make --quiet -C tools do_limine - make --quiet -C Drivers prepare - make --quiet -C Userspace prepare - make --quiet -C Kernel prepare + make --quiet prepare - name: Cache cross Folder id: cache-cross @@ -334,9 +326,7 @@ jobs: sudo apt update sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 make --quiet -C tools do_limine - make --quiet -C Drivers prepare - make --quiet -C Userspace prepare - make --quiet -C Kernel prepare + make --quiet prepare - name: Cache cross Folder id: cache-cross diff --git a/.vscode/launch.json b/.vscode/launch.json index 543f2222..144cec6c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -132,4 +132,4 @@ "preLaunchTask": "launch-qemu" }, ] -} \ No newline at end of file +} diff --git a/Bootloader/.editorconfig b/Bootloader/.editorconfig new file mode 100644 index 00000000..784b867b --- /dev/null +++ b/Bootloader/.editorconfig @@ -0,0 +1,13 @@ +# EditorConfig is awesome: https://editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = tab +indent_size = 4 + +[Makefile] +indent_style = tab diff --git a/Bootloader/.gitignore b/Bootloader/.gitignore new file mode 100644 index 00000000..f12553ad --- /dev/null +++ b/Bootloader/.gitignore @@ -0,0 +1,10 @@ +gnu-efi +include/* +!include/stdbool.h +!include/types.h +*.o +*.su +*.EFI +*.map +*.bin +*.elf diff --git a/Bootloader/.vscode/c_boilerplates.code-snippets b/Bootloader/.vscode/c_boilerplates.code-snippets new file mode 100644 index 00000000..8197764f --- /dev/null +++ b/Bootloader/.vscode/c_boilerplates.code-snippets @@ -0,0 +1,96 @@ +{ + "Lynx Bootloader C++ Header": { + "isFileTemplate": true, + "scope": "c,cpp", + "prefix": [ + "head", + ], + "body": [ + "/*", + "\tThis file is part of Lynx Bootloader.", + "", + "\tLynx Bootloader is free software: you can redistribute it and/or", + "\tmodify it under the terms of the GNU General Public License as", + "\tpublished by the Free Software Foundation, either version 3 of", + "\tthe License, or (at your option) any later version.", + "", + "\tLynx Bootloader is distributed in the hope that it will be useful,", + "\tbut WITHOUT ANY WARRANTY; without even the implied warranty of", + "\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", + "\tGNU General Public License for more details.", + "", + "\tYou should have received a copy of the GNU General Public License", + "\talong with Lynx Bootloader. If not, see .", + "*/", + "", + "#pragma once", + "", + "$0", + "", + "$1", + "" + ], + "description": "Create kernel header." + }, + "Lynx Bootloader C Header": { + "isFileTemplate": true, + "scope": "c,cpp", + "prefix": [ + "headc", + ], + "body": [ + "/*", + "\tThis file is part of Lynx Bootloader.", + "", + "\tLynx Bootloader is free software: you can redistribute it and/or", + "\tmodify it under the terms of the GNU General Public License as", + "\tpublished by the Free Software Foundation, either version 3 of", + "\tthe License, or (at your option) any later version.", + "", + "\tLynx Bootloader is distributed in the hope that it will be useful,", + "\tbut WITHOUT ANY WARRANTY; without even the implied warranty of", + "\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", + "\tGNU General Public License for more details.", + "", + "\tYou should have received a copy of the GNU General Public License", + "\talong with Lynx Bootloader. If not, see .", + "*/", + "", + "#ifndef __LYNX_BOOTLOADER_${1:header}_H__", + "#define __LYNX_BOOTLOADER_${1:header}_H__", + "", + "#include ", + "", + "$0", + "", + "#endif // !__LYNX_BOOTLOADER_${1:header}_H__", + "" + ], + "description": "Create kernel header." + }, + "License": { + "isFileTemplate": true, + "prefix": [ + "license", + ], + "body": [ + "/*", + "\tThis file is part of Lynx Bootloader.", + "", + "\tLynx Bootloader is free software: you can redistribute it and/or", + "\tmodify it under the terms of the GNU General Public License as", + "\tpublished by the Free Software Foundation, either version 3 of", + "\tthe License, or (at your option) any later version.", + "", + "\tLynx Bootloader is distributed in the hope that it will be useful,", + "\tbut WITHOUT ANY WARRANTY; without even the implied warranty of", + "\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", + "\tGNU General Public License for more details.", + "", + "\tYou should have received a copy of the GNU General Public License", + "\talong with Lynx Bootloader. If not, see .", + "*/" + ], + "description": "Create kernel license." + } +} \ No newline at end of file diff --git a/Bootloader/.vscode/c_cpp_properties.json b/Bootloader/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..8996a08d --- /dev/null +++ b/Bootloader/.vscode/c_cpp_properties.json @@ -0,0 +1,184 @@ +{ + "configurations": [ + { + "name": "Fennix x64 (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/include/**" + ], + "defines": [ + "DEBUG=\"1\"" + ], + "forcedInclude": [ + "${workspaceFolder}/.vscode/preinclude.h" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "gcc-x64", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + // Compiler flags + "-fno-pic", + "-fno-pie", + "-mno-red-zone", + "-march=core2", + "-pipe", + "-mcmodel=kernel", + "-fno-builtin", + "-m64", + "-fcoroutines", + // Warnings + "-Wall", + "-Wextra", + "-Wfloat-equal", + "-Wpointer-arith", + "-Wcast-align", + "-Wredundant-decls", + "-Winit-self", + "-Wswitch-default", + "-Wstrict-overflow=5", + "-Wconversion", + // C++ flags + "-fno-rtti", + "-fno-exceptions", + // Linker flags + "-T${workspaceFolder}/arch/amd64/linker.ld", + "-Wl,-static,--no-dynamic-linker,-ztext", + "-nostdlib", + "-nodefaultlibs", + "-nolibc", + "-zmax-page-size=0x1000", + "-shared", + // Debug flags + "-ggdb3", + "-O0", + "-fdiagnostics-color=always", + "-fverbose-asm", + "-fstack-usage", + "-fstack-check", + "-fsanitize=undefined", + // VSCode flags + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + }, + { + "name": "Fennix x32 (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/include/**" + ], + "forcedInclude": [ + "${workspaceFolder}/.vscode/preinclude.h" + ], + "defines": [ + "DEBUG=\"1\"" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "gcc-x86", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + // Compiler flags + "-fno-pic", + "-fno-pie", + "-mno-80387", + "-mno-mmx", + "-mno-3dnow", + "-mno-red-zone", + "-march=pentium", + "-pipe", + "-msoft-float", + "-fno-builtin", + "-m32", + "-fcoroutines", + // Warnings + "-Wall", + "-Wextra", + "-Wfloat-equal", + "-Wpointer-arith", + "-Wcast-align", + "-Wredundant-decls", + "-Winit-self", + "-Wswitch-default", + "-Wstrict-overflow=5", + "-Wconversion", + // C++ flags + "-fno-rtti", + "-fno-exceptions", + // Linker flags + "-T${workspaceFolder}/arch/i386/linker.ld", + "-Wl,-static,--no-dynamic-linker,-ztext", + "-nostdlib", + "-nodefaultlibs", + "-nolibc", + "-zmax-page-size=0x1000", + "-shared", + // Debug flags + "-ggdb3", + "-O0", + "-fdiagnostics-color=always", + "-fverbose-asm", + "-fstack-usage", + "-fstack-check", + "-fsanitize=undefined", + // VSCode flags + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + }, + { + "name": "Fennix Arm (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/include/**" + ], + "forcedInclude": [ + "${workspaceFolder}/.vscode/preinclude.h" + ], + "defines": [ + "DEBUG=\"1\"" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "linux-gcc-arm", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + // VSCode flags + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + }, + { + "name": "Fennix Aarch64 (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/include/**" + ], + "forcedInclude": [ + "${workspaceFolder}/.vscode/preinclude.h" + ], + "defines": [ + "DEBUG=\"1\"" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "linux-gcc-arm64", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + // VSCode flags + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + } + ], + "version": 4 +} diff --git a/Bootloader/.vscode/launch.json b/Bootloader/.vscode/launch.json new file mode 120000 index 00000000..e4eab602 --- /dev/null +++ b/Bootloader/.vscode/launch.json @@ -0,0 +1 @@ +../../.vscode/launch.json \ No newline at end of file diff --git a/Bootloader/.vscode/preinclude.h b/Bootloader/.vscode/preinclude.h new file mode 100644 index 00000000..9ef3ec36 --- /dev/null +++ b/Bootloader/.vscode/preinclude.h @@ -0,0 +1,11 @@ +#undef __linux__ +#undef __WIN32__ +#undef __WIN64__ +#undef _WIN32 +#undef _WIN64 +#undef __APPLE__ +#undef __clang__ +#define __vscode__ 1 +#define __kernel__ 1 +#define GIT_COMMIT "0000000000000000000000000000000000000000" +#define GIT_COMMIT_SHORT "0000000" diff --git a/Bootloader/.vscode/settings.json b/Bootloader/.vscode/settings.json new file mode 100644 index 00000000..f1b22965 --- /dev/null +++ b/Bootloader/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "C_Cpp.errorSquiggles": "enabled", + "C_Cpp.autocompleteAddParentheses": true, + "C_Cpp.codeAnalysis.clangTidy.enabled": true, + "C_Cpp.clang_format_style": "Visual Studio", + "C_Cpp.default.intelliSenseMode": "gcc-x64", + "C_Cpp.default.cStandard": "c17", + "C_Cpp.default.cppStandard": "c++20", + "C_Cpp.intelliSenseMemoryLimit": 16384, + "editor.smoothScrolling": true, + "editor.cursorSmoothCaretAnimation": "on", + "C_Cpp.codeAnalysis.clangTidy.checks.disabled": [ + "clang-analyzer-security.insecureAPI.strcpy", + "clang-diagnostic-unknown-warning-option", + "clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling", + "clang-diagnostic-implicit-exception-spec-mismatch", + "clang-diagnostic-unknown-attributes", + "clang-diagnostic-user-defined-literals", + "clang-diagnostic-non-pod-varargs", + "clang-diagnostic-non-pod-varargs", + "clang-diagnostic-non-pod-varargs" + ] +} \ No newline at end of file diff --git a/Bootloader/.vscode/tasks.json b/Bootloader/.vscode/tasks.json new file mode 120000 index 00000000..5edb3db9 --- /dev/null +++ b/Bootloader/.vscode/tasks.json @@ -0,0 +1 @@ +../../.vscode/tasks.json \ No newline at end of file diff --git a/Bootloader/Makefile b/Bootloader/Makefile new file mode 100644 index 00000000..f2710c69 --- /dev/null +++ b/Bootloader/Makefile @@ -0,0 +1,56 @@ +GNUEFI_RELEASE_VERSION=3.0.18 + +GIT_COMMIT = $(shell git rev-parse HEAD) +GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD) + +export CC := $(__CONF_CC) +export CXX := $(__CONF_CXX) +export LD := $(__CONF_LD) +export AS := $(__CONF_AS) +export AR := $(__CONF_AR) +export NM := $(__CONF_NM) +export OBJCOPY := $(__CONF_OBJCOPY) +export OBJDUMP := $(__CONF_OBJDUMP) +export GDB := $(__CONF_GDB) + +default: + $(error Do not run this Makefile directly!) + +prepare: +ifeq ("$(wildcard ./gnu-efi)", "") + wget https://freefr.dl.sourceforge.net/project/gnu-efi/gnu-efi-$(GNUEFI_RELEASE_VERSION).tar.bz2 + tar -xf gnu-efi-$(GNUEFI_RELEASE_VERSION).tar.bz2 + rm gnu-efi-$(GNUEFI_RELEASE_VERSION).tar.bz2 + mv ./gnu-efi-$(GNUEFI_RELEASE_VERSION) ./gnu-efi + cp -a ./gnu-efi/inc/. ./include +endif + echo "PREPARE > Compiling gnu-efi for x86_64" + make -C gnu-efi all ARCH=x86_64 \ + AR=$(TOOLCHAIN_AMD64_PREFIX)ar \ + AS=$(TOOLCHAIN_AMD64_PREFIX)as \ + CC=$(TOOLCHAIN_AMD64_PREFIX)gcc \ + LD=$(TOOLCHAIN_AMD64_PREFIX)ld +# echo "PREPARE > Compiling gnu-efi for arm" +# make -C gnu-efi all ARCH=arm \ +# AR=$(TOOLCHAIN_ARM_PREFIX)ar \ +# AS=$(TOOLCHAIN_ARM_PREFIX)as \ +# CC=$(TOOLCHAIN_ARM_PREFIX)gcc \ +# LD=$(TOOLCHAIN_ARM_PREFIX)ld \ +# CFLAGS="-I$(CURDIR)/gnu-efi/inc" +# echo "PREPARE > Compiling gnu-efi for aarch64" +# make -C gnu-efi all ARCH=aarch64 \ +# AR=$(TOOLCHAIN_AARCH64_PREFIX)ar \ +# AS=$(TOOLCHAIN_AARCH64_PREFIX)as \ +# CC=$(TOOLCHAIN_AARCH64_PREFIX)gcc \ +# LD=$(TOOLCHAIN_AARCH64_PREFIX)ld + +build: + $(MAKE) -C common build + $(MAKE) -C firmware build +# $(MAKE) -C uefi build + +clean: + $(MAKE) -C common clean + $(MAKE) -C firmware clean +# $(MAKE) -C uefi clean + rm -f boot.bin diff --git a/Bootloader/README.md b/Bootloader/README.md new file mode 100644 index 00000000..8e47fbbc --- /dev/null +++ b/Bootloader/README.md @@ -0,0 +1,13 @@ +# Lynx Bootloader + +> [!CAUTION] +> The project is in early stages of development and is not yet ready for production use. +> +> Use at your own risk. + + +## Introduction + +### [bios](bios) + +### [uefi](uefi) diff --git a/Bootloader/common/Makefile b/Bootloader/common/Makefile new file mode 100644 index 00000000..dd364aa4 --- /dev/null +++ b/Bootloader/common/Makefile @@ -0,0 +1,19 @@ +define find-sources + $(shell find ./ -type f -name '$1' -print0 | xargs -0) +endef + +BMP_SOURCES := $(call find-sources,*.bmp) +PSF_SOURCES := $(call find-sources,*.psf) +S_SOURCES := $(call find-sources,*.S) +s_SOURCES := $(call find-sources,*.s) +C_SOURCES := $(call find-sources,*.c) +CXX_SOURCES := $(call find-sources,*.cpp) + +OBJ = $(BMP_SOURCES:.bmp=.o) $(PSF_SOURCES:.psf=.o) $(s_SOURCES:.s=.o) $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) + +default: + $(error Do not run this Makefile directly!) + +build: + +clean: diff --git a/Bootloader/common/main.c b/Bootloader/common/main.c new file mode 100644 index 00000000..31963615 --- /dev/null +++ b/Bootloader/common/main.c @@ -0,0 +1,21 @@ +/* + This file is part of Lynx Bootloader. + + Lynx Bootloader is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Lynx Bootloader is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Lynx Bootloader. If not, see . +*/ + +int main() +{ + return 0; +} diff --git a/Bootloader/firmware/Makefile b/Bootloader/firmware/Makefile new file mode 100644 index 00000000..0a2a52dc --- /dev/null +++ b/Bootloader/firmware/Makefile @@ -0,0 +1,8 @@ +default: + $(error Do not run this Makefile directly!) + +build: + $(MAKE) -C $(OSARCH) build + +clean: + $(MAKE) -C $(OSARCH) clean diff --git a/Bootloader/firmware/aarch64/Makefile b/Bootloader/firmware/aarch64/Makefile new file mode 100644 index 00000000..48a36b24 --- /dev/null +++ b/Bootloader/firmware/aarch64/Makefile @@ -0,0 +1,64 @@ +define find-sources + $(shell find ./ -type f -name '$1' $(shell echo $(foreach board,$(filter-out $(BOARD_TYPE),$(AVAILABLE_BOARDS)), -not -path \"./$(board)/*\")) -print0 | xargs -0) +endef + +S_SOURCES := $(call find-sources,*.S) +s_SOURCES := $(call find-sources,*.s) +C_SOURCES := $(call find-sources,*.c) + +define find-common-sources + $(shell find ../../common -type f -name '$1' -print0 | xargs -0) +endef + +C_COMMON_SOURCES := $(call find-common-sources,*.c) + +OBJ = $(s_SOURCES:.s=.o) $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(C_COMMON_SOURCES:.c=.o) + +LDFLAGS = -static -nostdlib -nodefaultlibs -nolibc \ + -Wl,-static,--no-dynamic-linker,-ztext \ + -zmax-page-size=0x1000 \ + -Wl,-Map boot.map -fno-pic -fno-pie + +CFLAGS := \ + $(INCLUDE_DIR) \ + -D__kernel__='1' \ + -DGIT_COMMIT='"$(GIT_COMMIT)"' \ + -DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' \ + -fno-pic -fno-pie -fno-builtin -I../../include + +CFLAGS += -mcmodel=large +LDFLAGS += -T$(BOARD_TYPE)/linker.ld + +ifeq ($(DEBUG), 1) + CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always +# CFLAGS += -fsanitize=undefined + CFLAGS += -fstack-check -fverbose-asm + LDFLAGS += -ggdb3 -O0 + ASFLAGS += -g --gstabs+ --gdwarf-5 -D +endif # DEBUG + +default: + $(error Do not run this Makefile directly!) + +build: boot.bin + +boot.bin: $(OBJ) + $(info Linking $@) + $(CC) $(LDFLAGS) $(OBJ) -o tmp.elf + $(OBJCOPY) tmp.elf -O binary ../../boot.bin +# rm tmp.elf + +%.o: %.c $(HEADERS) + $(info Compiling $<) + $(CC) $(CFLAGS) -fstack-protector-all -std=c17 -c $< -o $@ + +%.o: %.S + $(info Compiling $<) + $(AS) $(ASFLAGS) -c $< -o $@ + +%.o: %.s + $(info Compiling $<) + $(AS) $(ASFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJ) boot.map diff --git a/Bootloader/firmware/aarch64/raspi3 b/Bootloader/firmware/aarch64/raspi3 new file mode 120000 index 00000000..89b5460b --- /dev/null +++ b/Bootloader/firmware/aarch64/raspi3 @@ -0,0 +1 @@ +./raspi4 \ No newline at end of file diff --git a/Bootloader/firmware/aarch64/raspi4/boot.S b/Bootloader/firmware/aarch64/raspi4/boot.S new file mode 100644 index 00000000..251651e6 --- /dev/null +++ b/Bootloader/firmware/aarch64/raspi4/boot.S @@ -0,0 +1,49 @@ +/* + This file is part of Lynx Bootloader. + + Lynx Bootloader is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Lynx Bootloader is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Lynx Bootloader. If not, see . +*/ + +.section ".text.boot" + +.extern __bss_start +.extern __bss_end +.extern __bss_size + +.global _start +_start: + /* Keep only the main core */ + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, 2f + + /* Halt */ +1: wfe + b 1b + + /* Initialize the stack */ +2: ldr x1, =_start + mov sp, x1 + + /* Clear the BSS */ + ldr x1, =__bss_start + ldr w2, =__bss_size +3: cbz w2, 4f + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, 3b + + /* Start the kernel */ +4: bl _aarch64_start + b 1b diff --git a/Bootloader/firmware/aarch64/raspi4/init.c b/Bootloader/firmware/aarch64/raspi4/init.c new file mode 100644 index 00000000..18b171fd --- /dev/null +++ b/Bootloader/firmware/aarch64/raspi4/init.c @@ -0,0 +1,32 @@ +/* + This file is part of Lynx Bootloader. + + Lynx Bootloader is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Lynx Bootloader is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Lynx Bootloader. If not, see . +*/ + +#include + +uintptr_t __stack_chk_guard = 0; + +__noreturn __no_stack_protector void __stack_chk_fail(void) +{ + while (1) + ; +} + +int main(); +__attribute__((section(".bootstrap.text"))) void _aarch64_start(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3) +{ + main(); +} diff --git a/Bootloader/firmware/aarch64/raspi4/linker.ld b/Bootloader/firmware/aarch64/raspi4/linker.ld new file mode 100644 index 00000000..18594248 --- /dev/null +++ b/Bootloader/firmware/aarch64/raspi4/linker.ld @@ -0,0 +1,70 @@ +/* + This file is part of Lynx Bootloader. + + Lynx Bootloader is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Lynx Bootloader is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Lynx Bootloader. If not, see . +*/ + +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) + +ENTRY(_start) + +SECTIONS +{ + . = 0x80000; + __start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + . = ALIGN(4096); + __text_end = .; + + __rodata_start = .; + .rodata : + { + *(.rodata) + } + . = ALIGN(4096); + __rodata_end = .; + + __data_start = .; + .data : + { + *(.data) + } + . = ALIGN(4096); + __data_end = .; + + __bss_start = .; + .bss : + { + bss = .; + *(.bss) + } + . = ALIGN(4096); + __bss_end = .; + __bss_size = __bss_end - __bss_start; /* SIZEOF(.bss); */ + __end = .; + + /DISCARD/ : + { + *(.comment*) + *(.gnu*) + *(.note*) + *(.eh_frame*) + } +} diff --git a/Bootloader/firmware/amd64/.gitkeep b/Bootloader/firmware/amd64/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Bootloader/firmware/arm/.gitkeep b/Bootloader/firmware/arm/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Bootloader/firmware/i386/.gitkeep b/Bootloader/firmware/i386/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Bootloader/include/stdbool.h b/Bootloader/include/stdbool.h new file mode 100644 index 00000000..b96d4a39 --- /dev/null +++ b/Bootloader/include/stdbool.h @@ -0,0 +1,26 @@ +/* + This file is part of Lynx Bootloader. + + Lynx Bootloader is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Lynx Bootloader is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Lynx Bootloader. If not, see . +*/ + +#ifndef __STDBOOL_H__ +#define __STDBOOL_H__ + + +typedef int bool; +#define true 1 +#define false 0 + +#endif /* __STDBOOL_H__ */ diff --git a/Bootloader/include/types.h b/Bootloader/include/types.h new file mode 100644 index 00000000..e5a29fb2 --- /dev/null +++ b/Bootloader/include/types.h @@ -0,0 +1,496 @@ +/* + This file is part of Lynx Bootloader. + + Lynx Bootloader is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Lynx Bootloader is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Lynx Bootloader. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_TYPES_H__ +#define __FENNIX_KERNEL_TYPES_H__ + +#include + +/** + * It doesn't do anything. + * + * Used to specify a function that is dependent on the architecture. + * It's architecture specific variant is defined in arch//... + */ +#define arch + +#ifdef __cplusplus +#define EXTERNC extern "C" +#define START_EXTERNC \ + EXTERNC \ + { +#define END_EXTERNC \ + } +#else // __cplusplus +#define EXTERNC +#define START_EXTERNC +#define END_EXTERNC +#endif // __cplusplus + +#ifdef __cplusplus +#define NULL 0 +#else // __cplusplus +#define NULL ((void *)0) +#endif // __cplusplus + +#define asm __asm__ +#define asmv __asm__ volatile + +#define inf_loop while (1) +#define ilp inf_loop; /* Used for debugging */ + +#ifdef __cplusplus +#define foreach for +#define in : + +#define forItr(itr, container) \ + for (auto itr = container.begin(); \ + itr != container.end(); ++itr) + +#define r_cst(t, v) reinterpret_cast(v) +#define c_cst(t, v) const_cast(v) +#define s_cst(t, v) static_cast(v) +#define d_cst(t, v) dynamic_cast(v) +#endif // __cplusplus + +#define UNUSED(x) (void)(x) +#define CONCAT(x, y) x##y + +#ifndef __va_list__ +typedef __builtin_va_list va_list; +#endif + +#define va_start(v, l) __builtin_va_start(v, l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v, l) __builtin_va_arg(v, l) + +#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align) - 1)) & (~((align) - 1)))) +#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align) - 1)))) + +#define offsetof(type, member) __builtin_offsetof(type, member) + +#define RGB_TO_HEX(r, g, b) ((r << 16) | (g << 8) | (b)) + +#define MAX(a, b) \ + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) + +#define MIN(a, b) \ + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) + +#define ROUND_UP(x, y) (((x) + (y) - 1) & ~((y) - 1)) +#define ROUND_DOWN(x, y) ((x) & ~((y) - 1)) + +#define VPOKE(type, address) (*((volatile type *)(address))) +#define POKE(type, address) (*((type *)(address))) + +#ifndef __SIG_ATOMIC_TYPE__ +#define __SIG_ATOMIC_TYPE__ int +#endif + +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; +typedef __INT64_TYPE__ int64_t; + +typedef __UINT8_TYPE__ uint8_t; +typedef __UINT16_TYPE__ uint16_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; + +typedef __INT_LEAST8_TYPE__ int_least8_t; +typedef __INT_LEAST16_TYPE__ int_least16_t; +typedef __INT_LEAST32_TYPE__ int_least32_t; +typedef __INT_LEAST64_TYPE__ int_least64_t; + +typedef __UINT_LEAST8_TYPE__ uint_least8_t; +typedef __UINT_LEAST16_TYPE__ uint_least16_t; +typedef __UINT_LEAST32_TYPE__ uint_least32_t; +typedef __UINT_LEAST64_TYPE__ uint_least64_t; + +typedef __INT_FAST8_TYPE__ int_fast8_t; +typedef __INT_FAST16_TYPE__ int_fast16_t; +typedef __INT_FAST32_TYPE__ int_fast32_t; +typedef __INT_FAST64_TYPE__ int_fast64_t; + +typedef __UINT_FAST8_TYPE__ uint_fast8_t; +typedef __UINT_FAST16_TYPE__ uint_fast16_t; +typedef __UINT_FAST32_TYPE__ uint_fast32_t; +typedef __UINT_FAST64_TYPE__ uint_fast64_t; + +typedef __INTPTR_TYPE__ intptr_t; +typedef __UINTPTR_TYPE__ uintptr_t; + +typedef __INTMAX_TYPE__ intmax_t; +typedef __UINTMAX_TYPE__ uintmax_t; + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; +#ifndef __cplusplus +typedef __WCHAR_TYPE__ wchar_t; +#endif +typedef __WINT_TYPE__ wint_t; +typedef __SIG_ATOMIC_TYPE__ sig_atomic_t; +// TODO: ssize_t +typedef intptr_t ssize_t; + +#if defined(__amd64__) || defined(__aarch64__) +typedef int64_t off_t; +typedef int64_t off64_t; +typedef uint32_t mode_t; +typedef uint64_t dev_t; +typedef uint64_t ino64_t; +typedef uint64_t ino_t; +typedef uint32_t nlink_t; +typedef int64_t blksize_t; +typedef int64_t blkcnt_t; +typedef int64_t blkcnt64_t; +typedef int64_t time_t; +typedef uint32_t uid_t; +typedef uint32_t gid_t; +typedef int64_t clock_t; +typedef int32_t pid_t; +#elif defined(__i386__) || defined(__arm__) +typedef int32_t off_t; +typedef long long off64_t; +typedef uint32_t mode_t; +typedef int32_t dev_t; +typedef int32_t ino64_t; +typedef int32_t ino_t; +typedef uint32_t nlink_t; +typedef int blksize_t; +typedef int32_t blkcnt_t; +typedef int32_t blkcnt64_t; +typedef int32_t time_t; +typedef uint32_t uid_t; +typedef uint32_t gid_t; +typedef long clock_t; +typedef int pid_t; +#endif + +#ifdef __cplusplus +template +class ptr_t +{ + T ptr; + +public: + ptr_t() : ptr(nullptr) {} + ptr_t(T p) : ptr(p) {} + ptr_t(int p) : ptr((T)(uintptr_t)p) {} + ptr_t(const ptr_t &other) : ptr(other.ptr) {} + + operator T() { return ptr; } + operator uintptr_t() { return (uintptr_t)ptr; } + + operator bool() { return (void *)(uintptr_t)ptr != nullptr; } + + ptr_t &operator=(const ptr_t &other) + { + ptr = other.ptr; + return *this; + } + + ptr_t &operator+=(uintptr_t offset) + { + ptr = (T)((uintptr_t)ptr + offset); + return *this; + } + + ptr_t &operator-=(uintptr_t offset) + { + ptr = (T)((uintptr_t)ptr - offset); + return *this; + } + + bool operator==(const ptr_t &other) const { return ptr == other.ptr; } + bool operator==(auto other) const { return (uintptr_t)ptr == (uintptr_t)other; } + + bool operator!=(const ptr_t &other) const { return ptr != other.ptr; } + bool operator!=(auto other) const { return (uintptr_t)ptr != (uintptr_t)other; } + + bool operator>(const ptr_t &other) const { return ptr > other.ptr; } + bool operator>(auto other) const { return (uintptr_t)ptr > (uintptr_t)other; } + + bool operator<(const ptr_t &other) const { return ptr < other.ptr; } + bool operator<(auto other) const { return (uintptr_t)ptr < (uintptr_t)other; } + + bool operator>=(const ptr_t &other) const { return ptr >= other.ptr; } + bool operator>=(auto other) const { return (uintptr_t)ptr >= (uintptr_t)other; } + + bool operator<=(const ptr_t &other) const { return ptr <= other.ptr; } + bool operator<=(auto other) const { return (uintptr_t)ptr <= (uintptr_t)other; } + + ptr_t operator+(auto offset) const { return ptr_t((void *)((uintptr_t)ptr + offset)); } + ptr_t operator-(auto offset) const { return ptr_t((void *)((uintptr_t)ptr - offset)); } + + T operator->() { return ptr; } + T operator*() { return *ptr; } +}; +#endif // __cplusplus + +#define INT8_MAX __INT8_MAX__ +#define INT8_MIN (-INT8_MAX - 1) +#define UINT8_MAX __UINT8_MAX__ +#define INT16_MAX __INT16_MAX__ +#define INT16_MIN (-INT16_MAX - 1) +#define UINT16_MAX __UINT16_MAX__ +#define INT32_MAX __INT32_MAX__ +#define INT32_MIN (-INT32_MAX - 1) +#define UINT32_MAX __UINT32_MAX__ +#define INT64_MAX __INT64_MAX__ +#define INT64_MIN (-INT64_MAX - 1) +#define UINT64_MAX __UINT64_MAX__ + +#define INT_LEAST8_MAX __INT_LEAST8_MAX__ +#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1) +#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__ +#define INT_LEAST16_MAX __INT_LEAST16_MAX__ +#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1) +#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__ +#define INT_LEAST32_MAX __INT_LEAST32_MAX__ +#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1) +#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__ +#define INT_LEAST64_MAX __INT_LEAST64_MAX__ +#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1) +#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__ + +#define INT_FAST8_MAX __INT_FAST8_MAX__ +#define INT_FAST8_MIN (-INT_FAST8_MAX - 1) +#define UINT_FAST8_MAX __UINT_FAST8_MAX__ +#define INT_FAST16_MAX __INT_FAST16_MAX__ +#define INT_FAST16_MIN (-INT_FAST16_MAX - 1) +#define UINT_FAST16_MAX __UINT_FAST16_MAX__ +#define INT_FAST32_MAX __INT_FAST32_MAX__ +#define INT_FAST32_MIN (-INT_FAST32_MAX - 1) +#define UINT_FAST32_MAX __UINT_FAST32_MAX__ +#define INT_FAST64_MAX __INT_FAST64_MAX__ +#define INT_FAST64_MIN (-INT_FAST64_MAX - 1) +#define UINT_FAST64_MAX __UINT_FAST64_MAX__ + +#define INTPTR_MAX __INTPTR_MAX__ +#define INTPTR_MIN (-INTPTR_MAX - 1) +#define UINTPTR_MAX __UINTPTR_MAX__ + +#define INTMAX_MAX __INTMAX_MAX__ +#define INTMAX_MIN (-INTMAX_MAX - 1) +#define UINTMAX_MAX __UINTMAX_MAX__ + +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#define PTRDIFF_MIN (-PTRDIFF_MAX - 1) + +#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ +#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__ + +#define SIZE_MAX __SIZE_MAX__ + +#define WCHAR_MAX __WCHAR_MAX__ +#define WCHAR_MIN __WCHAR_MIN__ + +#define WINT_MAX __WINT_MAX__ +#define WINT_MIN __WINT_MIN__ + +#if defined(__amd64__) +#define BREAK __asm__ __volatile__("int $0x3" \ + : \ + : \ + : "memory"); +#elif defined(__i386__) +#define BREAK __asm__ __volatile__("int $0x3" \ + : \ + : \ + : "memory"); +#elif defined(__aarch64__) +#define BREAK __asm__ __volatile__("brk #0" \ + : \ + : \ + : "memory"); +#endif + +#ifdef __INT48_TYPE__ +typedef __INT48_TYPE__ int48_t; +typedef __UINT48_TYPE__ uint48_t; +typedef int48_t int_least48_t; +typedef uint48_t uint_least48_t; +typedef int48_t int_fast48_t; +typedef uint48_t uint_fast48_t; +#else // __INT48_TYPE__ +typedef __INT64_TYPE__ int48_t; +typedef __UINT64_TYPE__ uint48_t; +typedef int48_t int_least48_t; +typedef uint48_t uint_least48_t; +typedef int48_t int_fast48_t; +typedef uint48_t uint_fast48_t; +#endif // __INT48_TYPE__ + +#define b4(x) ((x & 0x0F) << 4 | (x & 0xF0) >> 4) +#define b8(x) ((x) & 0xFF) +#define b16(x) __builtin_bswap16(x) +#define b32(x) __builtin_bswap32(x) +#define b48(x) (((((x) & 0x0000000000ff) << 40) | \ + (((x) & 0x00000000ff00) << 24) | \ + (((x) & 0x000000ff0000) << 8) | \ + (((x) & 0x0000ff000000) >> 8) | \ + (((x) & 0x00ff00000000) >> 24) | \ + (((x) & 0xff0000000000) >> 40))) +#define b64(x) __builtin_bswap64(x) + +/* https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html */ + +/** No optimization (the default); generates + * unoptimized code but has the fastest compilation time. + */ +#define O0 __attribute__((optimize("O0"))) + +/** Moderate optimization; + * optimizes reasonably well but does not degrade + * compilation time significantly. */ +#define O1 __attribute__((optimize("O1"))) + +/** Full optimization; generates highly + * optimized code and has the slowest compilation time. + */ +#define O2 __attribute__((optimize("O2"))) + +/** Full optimization as in -O2; + * also uses more aggressive automatic inlining of + * subprograms within a unit (Inlining of Subprograms) + * and attempts to vectorize loops. */ +#define O3 __attribute__((optimize("O3"))) + +/** Optimize space usage (code and data) + * of resulting program. + */ +#define Os __attribute__((optimize("Os"))) + +/** Disregard strict standards compliance. + * -Ofast enables all -O3 optimizations. + * It also enables optimizations that are not valid for + * all standard-compliant programs. + */ +#define Ofast __attribute__((optimize("Ofast"))) + +/** Optimize for size. + * -Oz enables all -Os optimizations that do not typically + * increase code size. + */ +#define Oz __attribute__((optimize("Oz"))) + +/** Optimize for debugging. + * -Og enables optimizations that do not interfere with + * debugging. + */ +#define Og __attribute__((optimize("Og"))) + +#define __unused __attribute__((unused)) +#define __packed __attribute__((packed)) +#define __naked __attribute__((naked)) +#define __aligned(x) __attribute__((aligned(x))) +#define __section(x) __attribute__((section(x))) +#define __noreturn __attribute__((noreturn)) +#define __weak __attribute__((weak)) +#define __alias(x) __attribute__((alias(x))) +#define __always_inline __attribute__((always_inline)) +#define __noinline __attribute__((noinline)) +#define __pure __attribute__((pure)) +#define __const __attribute__((const)) +#define __malloc __attribute__((malloc)) +#define __returns_twice __attribute__((returns_twice)) +#define __used __attribute__((used)) +#define __deprecated __attribute__((deprecated)) +#define __deprecated_msg(x) __attribute__((deprecated(x))) +#define __weakref(x) __attribute__((weakref(x))) +#define __weakrefalias(x) __attribute__((weakref(#x))) +#define __visibility(x) __attribute__((visibility(x))) +#define __constructor __attribute__((constructor)) +#define __destructor __attribute__((destructor)) +#define __cleanup(x) __attribute__((cleanup(x))) +#define __fallthrough __attribute__((fallthrough)) +#define __nonnull(x) __attribute__((nonnull x)) +#define __nonnull_all __attribute__((nonnull)) +#define __returns_nonnull __attribute__((returns_nonnull)) +#define __sentinel __attribute__((sentinel)) +#define __sentinel_all __attribute__((sentinel(0))) +#define __format(x, y, z) __attribute__((format(x, y, z))) +#define __format_arg(x) __attribute__((format_arg(x))) +#define __nonnull_params(x) __attribute__((nonnull x)) +#define __nonnull_all __attribute__((nonnull)) +#define __warn_unused_result __attribute__((warn_unused_result)) +#define __no_stack_protector __attribute__((no_stack_protector)) +#define __no_instrument_function __attribute__((no_instrument_function)) +#define __no_debug __attribute__((no_debug)) +#define __target(x) __attribute__((target(x))) +#define __min_vector_width(x) __attribute__((min_vector_width(x))) + +// sanitizer +#define __no_sanitize(x) __attribute__((no_sanitize(x))) +#define __no_sanitize_address __attribute__((no_sanitize_address)) +#define __no_sanitize_thread __attribute__((no_sanitize_thread)) +#define __no_sanitize_undefined __attribute__((no_sanitize_undefined)) +#define __no_sanitize_coverage __attribute__((no_sanitize_coverage)) + +#define __synchronize __sync_synchronize() +#define __sync __synchronize + +#define __unreachable __builtin_unreachable() + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_sanitize_thread +#define nsa NoSecurityAnalysis + +#define NIF __no_instrument_function + +#define int3 \ + __asm__ __volatile__("int3" \ + : \ + : \ + : "memory") + +#define StackPush(stack, type, value) \ + *((type *)--stack) = value + +#define StackPop(stack, type) \ + *((type *)stack++) + +#define ReturnLogError(ret, format, ...) \ + { \ + trace(format, ##__VA_ARGS__); \ + return ret; \ + } \ + while (0) \ + __builtin_unreachable() + +#define AssertReturnError(condition, ret) \ + do \ + { \ + if (__builtin_expect(!!(!(condition)), 0)) \ + { \ + error("\"%s\" failed!", #condition); \ + return ret; \ + } \ + } while (0) + +#endif // !__FENNIX_KERNEL_TYPES_H__ diff --git a/Bootloader/uefi/Makefile b/Bootloader/uefi/Makefile new file mode 100644 index 00000000..137616ac --- /dev/null +++ b/Bootloader/uefi/Makefile @@ -0,0 +1,137 @@ +BOOT_FILENAME = BOOTX64.EFI + +GNUEFI_RELEASE_VERSION=3.0.18 + +GIT_COMMIT = $(shell git rev-parse HEAD) +GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD) + +HEADERS := $(sort $(dir $(wildcard ../include/*))) +INCLUDE_DIR = -I../include + +define find-sources + $(shell find ./ -type f -name '$1' -print0 | xargs -0) +endef + +BMP_SOURCES := $(call find-sources,*.bmp) +PSF_SOURCES := $(call find-sources,*.psf) +S_SOURCES := $(call find-sources,*.S) +s_SOURCES := $(call find-sources,*.s) +C_SOURCES := $(call find-sources,*.c) +CXX_SOURCES := $(call find-sources,*.cpp) + +OBJ = $(BMP_SOURCES:.bmp=.o) $(PSF_SOURCES:.psf=.o) $(s_SOURCES:.s=.o) $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) + +LDFLAGS = -static -nostdlib -nodefaultlibs -nolibc \ + -Wl,-static,--no-dynamic-linker,-ztext \ + -zmax-page-size=0x1000 \ + -Wl,-Map kernel.map -fno-pic -fno-pie + +# Disable all warnings by adding "-w" in WARNCFLAG and if you want to treat the warnings as errors, add "-Werror" +# -Wconversion this may be re-added later +WARNCFLAG = -Wall -Wextra \ + -Wfloat-equal -Wpointer-arith -Wcast-align \ + -Wredundant-decls -Winit-self -Wswitch-default \ + -Wstrict-overflow=5 -Wno-error=cpp -Werror \ + -Wno-unused-parameter -Wno-error=format + +CFLAG_STACK_PROTECTOR := -fstack-protector-all + +# https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html +CFLAGS := \ + $(INCLUDE_DIR) \ + -D__kernel__='1' \ + -DKERNEL_NAME='"$(OSNAME)"' \ + -DKERNEL_ARCH='"$(OSARCH)"' \ + -DKERNEL_VERSION='"$(KERNEL_VERSION)"' \ + -DGIT_COMMIT='"$(GIT_COMMIT)"' \ + -DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' \ + -fno-pic -fno-pie -fno-builtin + +ifeq ($(OSARCH), amd64) +CFLAGS += -march=core2 -mcmodel=kernel -m64 -mno-red-zone +LDFLAGS += -T../linker.ld +else ifeq ($(OSARCH), i386) +CFLAGS += -march=pentium -m32 -mno-red-zone +LDFLAGS += -T../linker.ld +else ifeq ($(OSARCH), arm) +CFLAGS += -march=armv7-a -mfloat-abi=softfp -ggdb3 +LDFLAGS += -T../linker.ld +WARNCFLAG += -w +else ifeq ($(OSARCH), aarch64) +CFLAGS += -march=armv9.4-a -mtune=cortex-a72 -mlittle-endian -mcmodel=large +LDFLAGS += -T../linker.ld +endif # OSARCH + +# -finstrument-functions for __cyg_profile_func_enter & __cyg_profile_func_exit. Used for profiling and debugging. +ifeq ($(DEBUG), 1) +# CFLAGS += --coverage +# CFLAGS += -pg +# CFLAGS += -finstrument-functions + CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage -fsanitize=undefined +ifeq ($(OSARCH), amd64) + CFLAGS += -fverbose-asm +endif # amd64 +ifeq ($(OSARCH), arm) + CFLAGS += -fstack-check -fverbose-asm +endif # arm +ifeq ($(OSARCH), aarch64) + CFLAGS += -fstack-check -fverbose-asm +endif # aarch64 + LDFLAGS += -ggdb3 -O0 + ASFLAGS += -g --gstabs+ --gdwarf-5 -D + WARNCFLAG += -Wno-unused-function -Wno-maybe-uninitialized -Wno-builtin-declaration-mismatch -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-variable +endif # DEBUG + +default: + $(error Do not run this Makefile directly!) + +build: $(BOOT_FILENAME) + +$(BOOT_FILENAME): $(OBJ) + $(info Linking $@) + $(LD) -shared -Bsymbolic -L../gnu-efi/x86_64/lib -L../gnu-efi/x86_64/gnuefi -T../gnu-efi/gnuefi/elf_x86_64_efi.lds ../gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o $(OBJ) -o tmp.so -lgnuefi -lefi + objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 tmp.so BOOTX64.EFI + rm tmp.so + +%.o: %.c $(HEADERS) + $(info Compiling $<) + $(CC) -I../include -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -c $< -o $@ + +%.o: %.cpp $(HEADERS) + $(info Compiling $<) + $(CC) -I../include -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -c $< -o $@ + +%.o: %.S + $(info Compiling $<) + $(AS) $(ASFLAGS) -c $< -o $@ + +%.o: %.s + $(info Compiling $<) + $(AS) $(ASFLAGS) -c $< -o $@ + +%.o: %.psf +ifeq ($(OSARCH), amd64) + $(OBJCOPY) -O elf64-x86-64 -I binary $< $@ +else ifeq ($(OSARCH), i386) + $(OBJCOPY) -O elf32-i386 -I binary $< $@ +else ifeq ($(OSARCH), arm) + $(OBJCOPY) -O elf32-littlearm -I binary $< $@ +else ifeq ($(OSARCH), aarch64) + $(OBJCOPY) -O elf64-littleaarch64 -I binary $< $@ +endif + $(NM) $@ + +%.o: %.bmp +ifeq ($(OSARCH), amd64) + $(OBJCOPY) -O elf64-x86-64 -I binary $< $@ +else ifeq ($(OSARCH), i386) + $(OBJCOPY) -O elf32-i386 -I binary $< $@ +else ifeq ($(OSARCH), arm) + $(OBJCOPY) -O elf32-littlearm -I binary $< $@ +else ifeq ($(OSARCH), aarch64) + $(OBJCOPY) -O elf64-littlearch64 -I binary $< $@ +endif + $(NM) $@ + +clean: + rm -f kernel.map kernel_dump.map kernel_dump_intel.map $(OBJ) $(STACK_USAGE_OBJ) $(GCNO_OBJ) $(BOOT_FILENAME) diff --git a/Bootloader/uefi/main.c b/Bootloader/uefi/main.c new file mode 100644 index 00000000..fa30344a --- /dev/null +++ b/Bootloader/uefi/main.c @@ -0,0 +1,27 @@ +/* + This file is part of Lynx Bootloader. + + Lynx Bootloader is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Lynx Bootloader is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Lynx Bootloader. If not, see . +*/ + +#include +#include + +EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + InitializeLib(ImageHandle, SystemTable); + SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL); + Print(L"Lynx Bootloader © EnderIce2 2025\n"); + return EFI_SUCCESS; +} diff --git a/Fennix Bootloader.code-workspace b/Fennix Bootloader.code-workspace new file mode 100644 index 00000000..999739b3 --- /dev/null +++ b/Fennix Bootloader.code-workspace @@ -0,0 +1,15 @@ +{ + "folders": [ + { + "path": "./Bootloader" + } + ], + "settings": { + "terminal.integrated.cwd": "../", + "debug.allowBreakpointsEverywhere": true, + "git.alwaysSignOff": true, + "git.defaultBranchName": "master", + "git.openRepositoryInParentFolders": "always", + "C_Cpp.autoAddFileAssociations": false + } +} \ No newline at end of file diff --git a/Makefile b/Makefile index 1fc99bc9..69b52ab8 100644 --- a/Makefile +++ b/Makefile @@ -101,13 +101,17 @@ endif tools: make --quiet -C tools all -setup: +prepare: make --quiet -C Kernel prepare + make --quiet -C Bootloader prepare make --quiet -C Drivers prepare make --quiet -C Userspace prepare + +setup: + $(MAKE) prepare $(MAKE) tools -build: build_kernel build_userspace build_drivers build_image +build: build_kernel build_bootloader build_userspace build_drivers build_image dump: make --quiet -C Kernel dump @@ -123,9 +127,9 @@ ifeq ($(BUILD_KERNEL), 1) make -j$(shell nproc) $(MAKE_QUIET_FLAG) -C Kernel build endif -build_userspace: -ifeq ($(BUILD_USERSPACE), 1) - make $(MAKE_QUIET_FLAG) -C Userspace build +build_bootloader: +ifeq ($(BUILD_BOOTLOADER), 1) + make $(MAKE_QUIET_FLAG) -C Bootloader build endif build_drivers: @@ -133,6 +137,11 @@ ifeq ($(BUILD_DRIVERS), 1) make $(MAKE_QUIET_FLAG) -C Drivers build endif +build_userspace: +ifeq ($(BUILD_USERSPACE), 1) + make $(MAKE_QUIET_FLAG) -C Userspace build +endif + build_image: mkdir -p iso_tmp_data mkdir -p initrd_tmp_data @@ -171,6 +180,7 @@ ifeq ($(BOOTLOADER), grub) endif ifneq ($(filter aarch64 arm,$(OSARCH)),) $(__CONF_OBJCOPY) Kernel/fennix.elf -O binary $(OSNAME).img +# cp Bootloader/boot.bin $(OSNAME).img endif ifeq ($(OSARCH), amd64) diff --git a/config.mk b/config.mk index 07374589..38f252d5 100644 --- a/config.mk +++ b/config.mk @@ -8,16 +8,26 @@ OSNAME = Fennix # OS architecture, check AVAILABLE_ARCHS for available options. OSARCH = amd64 +# This variable specifies the board type. +# It is crucial because the ARM booting process differs significantly from x86. +# +# ! This variable is ignored on x86 ! +# +# Available options are in AVAILABLE_BOARDS. +BOARD_TYPE := raspi4 + # Kernel version. KERNEL_VERSION = dev # Which bootloader to use. # Available bootloaders: +# - builtin - Built-in # - grub - GRUB # - limine - Limine BOOTLOADER = grub BUILD_KERNEL = 1 +BUILD_BOOTLOADER = 1 BUILD_USERSPACE = 1 BUILD_DRIVERS = 1 @@ -35,10 +45,6 @@ COMPILER_PATH := $(CURDIR)/tools/cross # Default: $(CURDIR)/tools/cross __CONF_QEMU_PATH := $(CURDIR)/tools/cross -# Set libc to use. Available options: -# - internal - Use the internal libc -USE_LIBC = internal - @@ -56,10 +62,24 @@ USE_LIBC = internal # Available architectures. Do not change export AVAILABLE_ARCHS := amd64 i386 arm aarch64 +# Available board types. Do not change +export AVAILABLE_BOARDS := \ + raspi0 \ + raspi1 \ + raspi2 \ + raspi3 \ + raspi4 + ifneq ($(filter $(OSARCH),$(AVAILABLE_ARCHS)),$(OSARCH)) $(error OSARCH=$(OSARCH) is not a supported architecture. Choose one of: $(AVAILABLE_ARCHS)) endif +ifeq ($(filter amd64 i386,$(OSARCH)),) +ifneq ($(filter $(BOARD_TYPE),$(AVAILABLE_BOARDS)),$(BOARD_TYPE)) +$(error BOARD_TYPE=$(BOARD_TYPE) is not a supported board type. Choose one of: $(AVAILABLE_BOARDS)) +endif +endif + ARCH_MAP := amd64=x86_64 i386=i386 arm=arm aarch64=aarch64 COMPILER_ARCH := $(patsubst $(OSARCH)=%,%,$(filter $(OSARCH)=%,$(ARCH_MAP))) __CONF_QEMU_PATH := $(__CONF_QEMU_PATH)/bin/qemu-system-$(COMPILER_ARCH) @@ -78,4 +98,10 @@ export __CONF_GDB := $(TOOLCHAIN_PREFIX)gdb export DEBUG export OSNAME export OSARCH +export BOARD_TYPE export KERNEL_VERSION + +export TOOLCHAIN_AMD64_PREFIX := $(COMPILER_PATH)/bin/x86_64-fennix- +export TOOLCHAIN_I386_PREFIX := $(COMPILER_PATH)/bin/i386-fennix- +export TOOLCHAIN_ARM_PREFIX := $(COMPILER_PATH)/bin/arm-fennix- +export TOOLCHAIN_AARCH64_PREFIX := $(COMPILER_PATH)/bin/aarch64-fennix-