From 67d281d6be26d0cff1eb01eae427e5e2e4d357f5 Mon Sep 17 00:00:00 2001 From: ImagineHaxing Date: Thu, 27 Aug 2026 14:03:06 +0300 Subject: [PATCH] Change to limine bootloader --- .clangd.template | 6 ++-- nob.c | 71 +++++++++++++++++++++++++++++++++++++++--------- shell.nix | 7 +++-- src/boot.s | 3 +- src/kernel.c | 24 ++++++++++++++-- src/limine.conf | 3 ++ 6 files changed, 92 insertions(+), 22 deletions(-) create mode 100644 src/limine.conf diff --git a/.clangd.template b/.clangd.template index f1c6c4c..3ccae2d 100644 --- a/.clangd.template +++ b/.clangd.template @@ -1,9 +1,9 @@ CompileFlags: - Compiler: i686-elf-gcc + Compiler: x86_64-elf-gcc Add: - "-target" - - "i686-elf" + - "x86_64-elf" - "-ffreestanding" - "-nostdlibinc" - "-isystem" - - "${env:I686_ELF_GCC_INCLUDE}" \ No newline at end of file + - "${env:X86_64_ELF_GCC_INCLUDE}" \ No newline at end of file diff --git a/nob.c b/nob.c index bcf319f..db00725 100644 --- a/nob.c +++ b/nob.c @@ -11,14 +11,14 @@ bool render_clangd_config(void) { return false; nob_sb_append_null(&tmpl); - const char *include_path = getenv("I686_ELF_GCC_INCLUDE"); + const char *include_path = getenv("x86_64_ELF_GCC_INCLUDE"); if (include_path == NULL) { - nob_log(NOB_ERROR, "I686_ELF_GCC_INCLUDE not set"); + nob_log(NOB_ERROR, "x86_64_ELF_GCC_INCLUDE not set"); nob_sb_free(tmpl); return false; } - const char *needle = "${env:I686_ELF_GCC_INCLUDE}"; + const char *needle = "${env:X86_64_ELF_GCC_INCLUDE}"; Nob_String_Builder out = {0}; const char *cursor = tmpl.items; @@ -45,7 +45,7 @@ bool build_assembly(Nob_Cmd *cmd) { if (!rebuild) return true; - nob_cmd_append(cmd, "i686-elf-as", "-o", BUILD_FOLDER "boot.o", SRC_FOLDER "boot.s"); + nob_cmd_append(cmd, "x86_64-elf-as", "-o", BUILD_FOLDER "boot.o", SRC_FOLDER "boot.s"); if (!nob_cmd_run(cmd)) return false; @@ -61,9 +61,14 @@ bool build_c(Nob_Cmd *cmd) { return true; nob_cmd_append(cmd, - "i686-elf-gcc", + "x86_64-elf-gcc", "-std=gnu99", "-ffreestanding", + "-mcmodel=large", + "-mno-red-zone", + "-mno-mmx", + "-mno-sse", + "-mno-sse2", "-Wall", "-Wextra", "-O2", @@ -86,7 +91,7 @@ bool link_everything(Nob_Cmd *cmd) { const char *objectFiles[] = {BUILD_FOLDER "kernel.o", BUILD_FOLDER "boot.o"}; nob_cmd_append(cmd, - "i686-elf-gcc", + "x86_64-elf-gcc", "-T", SRC_FOLDER "linker.ld", "-o", BUILD_FOLDER "kernel", "-ffreestanding", @@ -137,10 +142,10 @@ bool clean_dir(const char *dir_path) { } bool build_bootable_image(Nob_Cmd *cmd) { + // NOTE: this does not rebuild on change of limine bins const char *output = BUILD_FOLDER "kernel.iso"; - const char *input[] = {BUILD_FOLDER "kernel", SRC_FOLDER "grub.cfg"}; + const char *input[] = {BUILD_FOLDER "kernel", SRC_FOLDER "limine.conf"}; int rebuild = nob_needs_rebuild(output, input, NOB_ARRAY_LEN(input)); - if (!rebuild) return true; @@ -148,18 +153,58 @@ bool build_bootable_image(Nob_Cmd *cmd) { return false; if (!nob_mkdir_if_not_exists(BUILD_FOLDER "isodir/boot")) return false; - if (!nob_mkdir_if_not_exists(BUILD_FOLDER "isodir/boot/grub")) + if (!nob_mkdir_if_not_exists(BUILD_FOLDER "isodir/boot/limine")) + return false; + if (!nob_mkdir_if_not_exists(BUILD_FOLDER "isodir/EFI")) + return false; + if (!nob_mkdir_if_not_exists(BUILD_FOLDER "isodir/EFI/BOOT")) + return false; + if (!nob_mkdir_if_not_exists(BUILD_FOLDER "limine")) return false; - nob_cmd_append(cmd, "cp", BUILD_FOLDER "kernel", BUILD_FOLDER "isodir/boot/kernel"); + if (!nob_file_exists(BUILD_FOLDER "limine")) { + nob_cmd_append(cmd, "git", "clone", "https://github.com/limine-bootloader/limine.git", "--branch=v11.x-binary", "--depth=1", BUILD_FOLDER "limine"); + if (!nob_cmd_run(cmd)) + return false; + } + + nob_cmd_append(cmd, "make", "-C", BUILD_FOLDER "limine"); if (!nob_cmd_run(cmd)) return false; - nob_cmd_append(cmd, "cp", SRC_FOLDER "grub.cfg", BUILD_FOLDER "isodir/boot/grub/grub.cfg"); + nob_cmd_append(cmd, "cp", + BUILD_FOLDER "limine/limine-bios.sys", + BUILD_FOLDER "limine/limine-bios-cd.bin", + BUILD_FOLDER "limine/limine-uefi-cd.bin", + BUILD_FOLDER "isodir/boot/limine/"); if (!nob_cmd_run(cmd)) return false; - nob_cmd_append(cmd, "grub-mkrescue", "-o", BUILD_FOLDER "kernel.iso", BUILD_FOLDER "isodir"); + nob_cmd_append(cmd, "cp", + BUILD_FOLDER "limine/BOOTIA32.EFI", + BUILD_FOLDER "limine/BOOTX64.EFI", + BUILD_FOLDER "isodir/EFI/BOOT/"); + if (!nob_cmd_run(cmd)) + return false; + + nob_cmd_append(cmd, "cp", SRC_FOLDER "limine.conf", BUILD_FOLDER "isodir/boot/limine/limine.conf"); + if (!nob_cmd_run(cmd)) + return false; + + nob_cmd_append(cmd, "cp", BUILD_FOLDER "kernel", BUILD_FOLDER "isodir/boot/"); + if (!nob_cmd_run(cmd)) + return false; + + nob_cmd_append(cmd, "xorriso", "-as", "mkisofs", + "-b", "boot/limine/limine-bios-cd.bin", + "-no-emul-boot", "-boot-load-size", "4", "-boot-info-table", + "--efi-boot", "boot/limine/limine-uefi-cd.bin", + "-efi-boot-part", "--efi-boot-image", "--protective-msdos-label", + BUILD_FOLDER "isodir", "-o", BUILD_FOLDER "kernel.iso"); + if (!nob_cmd_run(cmd)) + return false; + + nob_cmd_append(cmd, BUILD_FOLDER "limine/limine", "bios-install", BUILD_FOLDER "kernel.iso"); if (!nob_cmd_run(cmd)) return false; @@ -167,7 +212,7 @@ bool build_bootable_image(Nob_Cmd *cmd) { } bool runQemu(Nob_Cmd *cmd) { - nob_cmd_append(cmd, "qemu-system-i386", "-cdrom", BUILD_FOLDER "kernel.iso", "-serial", "stdio"); + nob_cmd_append(cmd, "qemu-system-x86_64", "-cdrom", BUILD_FOLDER "kernel.iso", "-serial", "stdio"); if (!nob_cmd_run(cmd)) return false; return true; diff --git a/shell.nix b/shell.nix index bce4969..1cd4637 100644 --- a/shell.nix +++ b/shell.nix @@ -3,15 +3,16 @@ pkgs.mkShell { nativeBuildInputs = with pkgs; [ - pkgsCross.i686-embedded.buildPackages.gcc - pkgsCross.i686-embedded.buildPackages.binutils + pkgsCross.x86_64-embedded.buildPackages.gcc + pkgsCross.x86_64-embedded.buildPackages.binutils gdb grub2 xorriso qemu + limine ]; shellHook = '' - export I686_ELF_GCC_INCLUDE="${pkgs.pkgsCross.i686-embedded.buildPackages.gcc.cc}/lib/gcc/i686-elf/${pkgs.pkgsCross.i686-embedded.buildPackages.gcc.version}/include" + export x86_64_ELF_GCC_INCLUDE="${pkgs.pkgsCross.x86_64-embedded.buildPackages.gcc.cc}/lib/gcc/x86_64-elf/${pkgs.pkgsCross.x86_64-embedded.buildPackages.gcc.version}/include" ''; } diff --git a/src/boot.s b/src/boot.s index 3ee4cf0..a04be91 100644 --- a/src/boot.s +++ b/src/boot.s @@ -20,8 +20,9 @@ stack_top: .section .text .global _start .type _start, @function + _start: - mov $stack_top, %esp + mov $stack_top, %rsp /* Initialize processor state here */ diff --git a/src/kernel.c b/src/kernel.c index 0570b92..8ecada6 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -6,10 +6,24 @@ #if defined(__linux__) #error "Not using cross compiler" #endif -#if !defined(__i386__) -#error "Not using a ix86-elf compiler" +#if !defined(__x86_64__) +#error "Not using a x86_64-elf compiler" #endif +static inline uint64_t read_msr(uint32_t msr) { + uint32_t lo, hi; + __asm__ volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); + return ((uint64_t)hi << 32) | lo; +} + +#define IA32_EFER 0xC0000080 +#define EFER_LMA (1 << 10) + +int is_long_mode_active(void) { + uint64_t efer = read_msr(IA32_EFER); + return (efer & EFER_LMA) != 0; +} + void kernel_main(void) { init_serial(); if (!test_serial()) { @@ -17,4 +31,10 @@ void kernel_main(void) { return; } serial_log(S_LOG, "Init serial succesfully."); + + if (!is_long_mode_active()) { + serial_log(S_ERR, "Kernel is not in long mode!"); + return; + } + serial_log(S_LOG, "Kernel is in long mode."); } diff --git a/src/limine.conf b/src/limine.conf new file mode 100644 index 0000000..59226da --- /dev/null +++ b/src/limine.conf @@ -0,0 +1,3 @@ +/SimpleKernel + protocol: multiboot1 + kernel_path: boot():/boot/kernel \ No newline at end of file