]> code.bitgloo.com Git - clyne/osdev.git/commitdiff
convert boot.s to c++
authorClyne Sullivan <clyne@bitgloo.com>
Fri, 27 Sep 2024 10:45:13 +0000 (06:45 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Fri, 27 Sep 2024 10:45:13 +0000 (06:45 -0400)
Makefile
boot.cpp [new file with mode: 0644]
boot.s [deleted file]
kernel.cpp

index 17adbac7f99b6916ef0934a3f6a3769e292bec91..652f617f2afd29b4449466dec348eb7f63311767 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,20 +1,18 @@
-ASFLAGS := --32
 CXXFLAGS := -m32 -ggdb -g3 -O0 -fno-pic -ffreestanding -fno-rtti -fno-exceptions -std=c++23
 LDFLAGS := -m32 -static -T link.ld -ffreestanding -nostdlib
 
-ASFILES := boot.s
-CXXFILES := gdt.cpp \
-           idt.cpp \
-           memory.cpp \
-           multiboot.cpp \
-           pic.cpp \
-           pit.cpp \
-           tasking.cpp \
-            vgaterminal.cpp \
-           kernel.cpp
+CXXFILES := boot.cpp \
+        gdt.cpp \
+        idt.cpp \
+        memory.cpp \
+        multiboot.cpp \
+        pic.cpp \
+        pit.cpp \
+        tasking.cpp \
+        vgaterminal.cpp \
+        kernel.cpp
 
-OBJS := $(subst .s,.o,$(ASFILES)) \
-       $(subst .cpp,.o,$(CXXFILES))
+OBJS := $(subst .cpp,.o,$(CXXFILES))
 
 all: myos.iso
 
@@ -27,10 +25,6 @@ myos.bin: $(OBJS) link.ld
        @echo "  LD  " $@
        @g++ $(LDFLAGS) -o $@ $(OBJS)
 
-%.o: %.s
-       @echo "  AS  " $<
-       @as $(ASFLAGS) -c $< -o $@
-
 %.o: %.cpp
        @echo "  CXX " $<
        @g++ $(CXXFLAGS) -c $< -o $@
@@ -41,5 +35,5 @@ clean:
 
 run: myos.iso
        @echo "  QEMU"
-       @qemu-system-i386 -cdrom $< -monitor stdio -no-reboot -s -S #-d int
+       @qemu-system-i386 -cdrom $< -monitor stdio -no-reboot #-s -S #-d int
 
diff --git a/boot.cpp b/boot.cpp
new file mode 100644 (file)
index 0000000..0b003fd
--- /dev/null
+++ b/boot.cpp
@@ -0,0 +1,72 @@
+#include <array>
+#include <cstdint>
+
+extern void kernel_main();
+
+struct multiboot2
+{
+    static constexpr std::uint32_t MAGIC    = 0xE85250D6;
+    static constexpr std::uint32_t FLAGS    = 0;
+    static constexpr std::uint32_t LENGTH   = 16;
+    static constexpr std::uint32_t CHECKSUM = -(MAGIC + FLAGS + LENGTH);
+
+    alignas(8)
+    std::uint32_t magic = MAGIC;
+    std::uint32_t flags = FLAGS;
+    std::uint32_t length = LENGTH;
+    std::uint32_t checksum = CHECKSUM;
+} __attribute__((packed));
+
+struct multiboot2_tag
+{
+    alignas(8)
+    std::uint16_t id;
+    std::uint16_t flags;
+    std::uint32_t length;
+    std::uint32_t data[];
+} __attribute__((packed));
+
+__attribute__((section(".multiboot2")))
+multiboot2 multibootHeader;
+
+__attribute__((section(".multiboot2")))
+multiboot2_tag multibootTagInfoRequest = { 
+    1, 0, sizeof(multiboot2_tag) + sizeof(std::uint32_t),
+    {4}
+};
+
+__attribute__((section(".multiboot2")))
+multiboot2_tag multibootTagEnd = { 
+    0, 0, sizeof(multiboot2_tag), {}
+};
+
+alignas(16)
+std::array<std::uint8_t, 16384> stack;
+
+extern "C"
+__attribute__((naked))
+void _start()
+{
+    asm volatile(R"(
+        mov %%eax, multiboot_magic
+        mov %%ebx, multiboot_ptr
+        mov %0, %%esp
+    )" :: "i" (stack.data() + stack.size()));
+
+    extern std::uint32_t __init_array_start;
+    extern std::uint32_t __init_array_end;
+
+    auto it = &__init_array_start;
+    while (it < &__init_array_end) {
+        auto fn = reinterpret_cast<void (*)()>(*it);
+        fn();
+        ++it;
+    }
+
+    kernel_main();
+
+    asm volatile("cli");
+    for (;;)
+        asm volatile("hlt");
+}
+
diff --git a/boot.s b/boot.s
deleted file mode 100644 (file)
index 7908d3e..0000000
--- a/boot.s
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Declare constants for the multiboot header. */
-.set MAGIC,    0xE85250D6
-.set FLAGS,    0x0
-.set LENGTH,   16
-.set CHECKSUM, -(MAGIC + FLAGS + LENGTH)
-
-.section .multiboot2
-.align 8
-.int MAGIC
-.int FLAGS
-.int LENGTH
-.int CHECKSUM
-
-/* info request */
-.align 8
-.hword 1, 0
-.int 12
-.int 4
-
-/* end tag */
-.align 8
-.hword 0, 0
-.int 8
-
-/*
-The multiboot standard does not define the value of the stack pointer register
-(esp) and it is up to the kernel to provide a stack. This allocates room for a
-small stack by creating a symbol at the bottom of it, then allocating 16384
-bytes for it, and finally creating a symbol at the top. The stack grows
-downwards on x86. The stack is in its own section so it can be marked nobits,
-which means the kernel file is smaller because it does not contain an
-uninitialized stack. The stack on x86 must be 16-byte aligned according to the
-System V ABI standard and de-facto extensions. The compiler will assume the
-stack is properly aligned and failure to align the stack will result in
-undefined behavior.
-*/
-.section .bss
-.align 16
-stack_bottom:
-.skip 16384 # 16 KiB
-stack_top:
-
-/*
-The linker script specifies _start as the entry point to the kernel and the
-bootloader will jump to this position once the kernel has been loaded. It
-doesn't make sense to return from this function as the bootloader is gone.
-*/
-.section .text
-.global _start
-.type _start, @function
-_start:
-       /*
-       The bootloader has loaded us into 32-bit protected mode on a x86
-       machine. Interrupts are disabled. Paging is disabled. The processor
-       state is as defined in the multiboot standard. The kernel has full
-       control of the CPU. The kernel can only make use of hardware features
-       and any code it provides as part of itself. There's no printf
-       function, unless the kernel provides its own <stdio.h> header and a
-       printf implementation. There are no security restrictions, no
-       safeguards, no debugging mechanisms, only what the kernel provides
-       itself. It has absolute and complete power over the
-       machine.
-       */
-        mov %eax, multiboot_magic
-        mov %ebx, multiboot_ptr
-
-       /*
-       To set up a stack, we set the esp register to point to the top of the
-       stack (as it grows downwards on x86 systems). This is necessarily done
-       in assembly as languages such as C cannot function without a stack.
-       */
-       mov $stack_top, %esp
-
-       /*
-       This is a good place to initialize crucial processor state before the
-       high-level kernel is entered. It's best to minimize the early
-       environment where crucial features are offline. Note that the
-       processor is not fully initialized yet: Features such as floating
-       point instructions and instruction set extensions are not initialized
-       yet. The GDT should be loaded here. Paging should be enabled here.
-       C++ features such as global constructors and exceptions will require
-       runtime support to work as well.
-       */
-        mov $__init_array_start, %eax
-.again:
-        cmp $__init_array_end, %eax
-        je .next
-        push %eax
-        call *(%eax)
-        pop %eax
-        add $0x4, %eax
-        jmp .again
-
-.next:
-
-       /*
-       Enter the high-level kernel. The ABI requires the stack is 16-byte
-       aligned at the time of the call instruction (which afterwards pushes
-       the return pointer of size 4 bytes). The stack was originally 16-byte
-       aligned above and we've pushed a multiple of 16 bytes to the
-       stack since (pushed 0 bytes so far), so the alignment has thus been
-       preserved and the call is well defined.
-       */
-       call kernel_main
-
-       /*
-       If the system has nothing more to do, put the computer into an
-       infinite loop. To do that:
-       1) Disable interrupts with cli (clear interrupt enable in eflags).
-          They are already disabled by the bootloader, so this is not needed.
-          Mind that you might later enable interrupts and return from
-          kernel_main (which is sort of nonsensical to do).
-       2) Wait for the next interrupt to arrive with hlt (halt instruction).
-          Since they are disabled, this will lock up the computer.
-       3) Jump to the hlt instruction if it ever wakes up due to a
-          non-maskable interrupt occurring or due to system management mode.
-       */
-       cli
-1:     hlt
-       jmp 1b
-
-/*
-Set the size of the _start symbol to the current location '.' minus its start.
-This is useful when debugging or when you implement call tracing.
-*/
-.size _start, . - _start
-
index 41c3a61dc99894fa79b806ffcaeb0ae0283bc432..dab93c6c2f312ac0a5aa4632970723575b66ce64 100644 (file)
@@ -10,7 +10,6 @@
 static VGATerminal vga;
 TextOutput& term = vga;
 
-extern "C"
 void kernel_main(void) 
 {
     term.write("Clyne's kernel, v2024\n\n");