:: commit 7d400d30d6b2d330a9524510d1eaef4ba8d26b98

streaksu <assemblyislaw@gmail.com> — 2020-09-29 22:31

parents: b171d8fb02

Add a unified test image for stivale1 and stivale2 for both x86_64 and i386

diff --git a/Makefile b/Makefile
index c27e0ba3..7dfa4a98 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ all: stage2 decompressor
 	gzip -n -9 < stage2/stage2.bin > stage2/stage2.bin.gz
 	cd bootsect && nasm bootsect.asm -fbin -o ../limine.bin
 
-clean: stage2-clean decompressor-clean
+clean: stage2-clean decompressor-clean test-clean
 	rm -f stage2/stage2.bin.gz
 
 stage2:
@@ -23,6 +23,9 @@ decompressor:
 decompressor-clean:
 	$(MAKE) -C decompressor clean
 
+test-clean:
+	$(MAKE) -C test clean
+
 toolchain:
 	cd toolchain && ./make_toolchain.sh -j`nproc`
 
diff --git a/test/Makefile b/test/Makefile
index 8dc22c83..a9336673 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,22 @@
-test.elf: test.asm linker.ld
-	nasm test.asm -felf64 -o test.o
-	ld test.o -no-pie -nostdlib -T ./linker.ld -o test.elf
+TARGET := test.elf
+
+CC              = cc
+CFLAGS          = -O2
+LD              = ld
+QEMU            = qemu-system-x86_64
+QEMUFLAGS       = -m 1G -enable-kvm -cpu host
+LDINTERNALFLAGS := -Tlinker.ld -static -nostdlib -no-pie
+INTERNALCFLAGS  := -I../stivale -I. -ffreestanding -fno-stack-protector   \
+	-fno-pic -fomit-frame-pointer -mno-80387 -mno-mmx -mno-3dnow -mno-sse \
+	-mno-sse2 -masm=intel
+
+all: $(TARGET)
+
+$(TARGET): stivale.o stivale2.o e9print.o
+	$(LD) $(LDINTERNALFLAGS) stivale.o stivale2.o e9print.o -o $@
+
+%.o: %.c
+	$(CC) $(CFLAGS) $(INTERNALCFLAGS) -c $< -o $@
+
+clean:
+	rm -rf $(TARGET) stivale.o stivale2.o e9print.o
diff --git a/test/e9print.c b/test/e9print.c
new file mode 100644
index 00000000..f027e4ec
--- /dev/null
+++ b/test/e9print.c
@@ -0,0 +1,82 @@
+#include <e9print.h>
+#include <stddef.h>
+
+static const char CONVERSION_TABLE[] = "0123456789abcdef";
+
+void e9_putc(char c) {
+    asm volatile ("out dx, al" :: "a" (c), "d" (0xE9) : "memory");
+}
+
+void e9_print(const char *msg) {
+    for (size_t i = 0; msg[i]; i++) {
+        e9_putc(msg[i]);
+    }
+}
+
+void e9_puts(const char *msg) {
+    e9_print(msg);
+    e9_putc('\n');
+}
+
+static void e9_printhex(size_t num) {
+    int i;
+    char buf[17];
+
+    if (!num) {
+        e9_print("0x0");
+        return;
+    }
+
+    buf[16] = 0;
+
+    for (i = 15; num; i--) {
+        buf[i] = CONVERSION_TABLE[num % 16];
+        num /= 16;
+    }
+
+    i++;
+    e9_print("0x");
+    e9_print(&buf[i]);
+}
+
+static void e9_printdec(size_t num) {
+    int i;
+    char buf[21] = {0};
+
+    if (!num) {
+        e9_putc('0');
+        return;
+    }
+
+    for (i = 19; num; i--) {
+        buf[i] = (num % 10) + 0x30;
+        num = num / 10;
+    }
+
+    i++;
+    e9_print(buf + i);
+}
+
+void e9_printf(const char *format, ...) {
+    va_list argp;
+    va_start(argp, format);
+
+    while (*format != '\0') {
+        if (*format == '%') {
+            format++;
+            if (*format == 'x') {
+                e9_printhex(va_arg(argp, size_t));
+            } else if (*format == 'd') {
+                e9_printdec(va_arg(argp, size_t));
+            } else if (*format == 's') {
+                e9_print(va_arg(argp, char*));
+            } 
+        } else {
+            e9_putc(*format);
+        }
+        format++;
+    }
+
+    e9_putc('\n');
+    va_end(argp);
+}
diff --git a/test/e9print.h b/test/e9print.h
new file mode 100644
index 00000000..44ac8e2f
--- /dev/null
+++ b/test/e9print.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <stdarg.h>
+
+void e9_putc(char c);
+void e9_print(const char *msg);
+void e9_puts(const char *msg);
+void e9_printf(const char *format, ...);
diff --git a/test/limine.cfg b/test/limine.cfg
index ab43e465..380682f3 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -1,4 +1,4 @@
-DEFAULT_ENTRY=2
+DEFAULT_ENTRY=0
 TIMEOUT=3
 GRAPHICS=yes
 
@@ -16,26 +16,16 @@ THEME_MARGIN=64
 BACKGROUND_PARTITION=0
 BACKGROUND_PATH=bg.bmp
 
-:MyOS 0
-
-PROTOCOL=stivale2
+:Stivale Test
 
+PROTOCOL=stivale
 KERNEL_PARTITION=0
 KERNEL_PATH=boot/test.elf
-KERNEL_CMDLINE=something
+KERNEL_CMDLINE=Hi! This is an example!
 
-:MyOS 1
+:Stivale2 Test
 
 PROTOCOL=stivale2
-
-KERNEL_PARTITION=0
-KERNEL_PATH=boot/test.elf
-KERNEL_CMDLINE=something
-
-:MyOS 2
-
-PROTOCOL=stivale2
-
 KERNEL_PARTITION=0
 KERNEL_PATH=boot/test.elf
-KERNEL_CMDLINE=something
+KERNEL_CMDLINE=Woah! Another example!
diff --git a/test/linker.ld b/test/linker.ld
index 14f6027d..768751a6 100644
--- a/test/linker.ld
+++ b/test/linker.ld
@@ -1,26 +1,37 @@
-ENTRY(_start)
+ENTRY(stivale_main)
 
-SECTIONS {
-    . = 0xffffffff80100000;
+SECTIONS
+{
+    . = 0x100000;
 
-    .stivalehdr : ALIGN(4K) {
-        *(.stivalehdr)
+    .stivalehdr ALIGN(4K) :
+    {
+        KEEP(*(.stivalehdr))
     }
 
-    .text : ALIGN(4K) {
-        *(.text*)
+    .stivale2hdr ALIGN(4K) :
+    {
+        KEEP(*(.stivale2hdr))
     }
 
-    .rodata : ALIGN(4K) {
-        *(.rodata*)
+    .text ALIGN(4K) :
+    {
+        KEEP(*(.text*))
     }
 
-    .data : ALIGN(4K) {
-        *(.data*)
+    .rodata ALIGN(4K) :
+    {
+        KEEP(*(.rodata*))
     }
 
-    .bss : ALIGN(4K) {
-        *(.bss*)
-        *(COMMON)
+    .data ALIGN(4K) :
+    {
+        KEEP(*(.data*))
+    }
+
+    .bss ALIGN(4K) :
+    {
+        KEEP(*(COMMON))
+        KEEP(*(.bss*))
     }
 }
diff --git a/test/stivale.c b/test/stivale.c
new file mode 100644
index 00000000..4616ec6b
--- /dev/null
+++ b/test/stivale.c
@@ -0,0 +1,51 @@
+#include <stivale.h>
+#include <stdint.h>
+#include <e9print.h>
+#include <stddef.h>
+
+static uint8_t stack[4096] = {0};
+void stivale_main(struct stivale_struct *info);
+
+__attribute__((section(".stivalehdr"), used))
+struct stivale_header header = {
+    .stack              = (uint64_t)(uintptr_t)stack + sizeof(stack),
+    .framebuffer_bpp    = 0,
+    .framebuffer_width  = 0,
+    .framebuffer_height = 0,
+    .flags              = 1,
+    .entry_point        = (uint64_t)(uintptr_t)stivale_main
+};
+
+void stivale_main(struct stivale_struct *info) {
+    // Print some info.
+    e9_puts("Stivale information passed to the kernel:");
+    e9_printf("Cmdline: %s", (char*)info->cmdline);
+    e9_printf("Memory map at %x with contents:", info->memory_map_addr);
+
+    struct stivale_mmap_entry *memmap = ((struct stivale_mmap_entry *)(info->memory_map_addr));
+    for (size_t i = 0; i < info->memory_map_entries; i++) {
+        struct stivale_mmap_entry e = memmap[i];
+        e9_printf("\tEntry %d: [%x+%x] %x", i, e.base, e.length, e.type);
+    }
+
+    e9_printf("Framebuffer at %x with specifics:", info->framebuffer_addr);
+    e9_printf("\tPitch:  %d", info->framebuffer_pitch);
+    e9_printf("\tWidth:  %d", info->framebuffer_width);
+    e9_printf("\tHeight: %d", info->framebuffer_height);
+    e9_printf("\tBPP:    %d", info->framebuffer_bpp);
+    e9_printf("RSDP at %x", info->rsdp);
+
+    e9_printf("Module map at %x with modules:", info->modules);
+    struct stivale_module *modules = ((struct stivale_module *)(info->modules));
+    for (size_t i = 0; i < info->module_count; i++) {
+        struct stivale_module e = *modules;
+        e9_printf("\tModule %d: [%x+%x] %s", i, e.begin, e.end, e.string);
+        modules = (struct stivale_module *)e.next;
+    }
+
+    e9_printf("Epoch is  %x", info->epoch);
+    e9_printf("Flags are %x", info->flags);
+
+    // Guru meditation.
+    for (;;);
+}
diff --git a/test/stivale2.c b/test/stivale2.c
new file mode 100644
index 00000000..ef0989b0
--- /dev/null
+++ b/test/stivale2.c
@@ -0,0 +1,124 @@
+#include <stivale2.h>
+#include <stdint.h>
+#include <e9print.h>
+#include <stddef.h>
+
+static uint8_t stack[4096] = {0};
+void stivale2_main(struct stivale2_struct *info);
+
+struct stivale2_header_tag_smp smp_request = {
+    .tag = {
+        .identifier = STIVALE2_HEADER_TAG_SMP_ID,
+        .next       = 0
+    },
+    .flags = 0
+};
+
+struct stivale2_header_tag_framebuffer framebuffer_request = {
+    .tag = {
+        .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID,
+        .next       = (uint64_t)&smp_request
+    },
+    .framebuffer_width  = 0,
+    .framebuffer_height = 0,
+    .framebuffer_bpp    = 0,
+};
+
+__attribute__((section(".stivale2hdr"), used))
+struct stivale2_header header2 = {
+    .entry_point = (uint64_t)stivale2_main,
+    .stack       = (uintptr_t)stack + sizeof(stack),
+    .flags       = 0,
+    .tags        = (uint64_t)&framebuffer_request
+};
+
+void stivale2_main(struct stivale2_struct *info) {
+    // Print stuff.
+    e9_puts("Stivale2 info passed to the kernel:");
+    e9_printf("Bootloader brand:   %s", info->bootloader_brand);
+    e9_printf("Bootloader version: %s", info->bootloader_version);
+
+    // Print the tags.
+    struct stivale2_tag *tag = (struct stivale2_tag *)info->tags;
+
+    while (tag != NULL) {
+        switch (tag->identifier) {
+            case STIVALE2_STRUCT_TAG_CMDLINE_ID: {
+                struct stivale2_struct_tag_cmdline *c = (struct stivale2_struct_tag_cmdline *)tag;
+                e9_puts("Commandline tag:");
+                e9_printf("\tCmdline: %s", (char*)(c->cmdline));
+                break;
+            }
+            case STIVALE2_STRUCT_TAG_MEMMAP_ID: {
+                struct stivale2_struct_tag_memmap *m = (struct stivale2_struct_tag_memmap *)tag;
+                e9_puts("Memmap tag:");
+                e9_printf("\tEntries: %d", m->entries);
+                for (size_t i = 0; i < m->entries; i++) {
+                    struct stivale2_mmap_entry me = m->memmap[i];
+                    e9_printf("\t\t[%x+%x] %x", me.base, me.length, me.type);
+                }
+                break;
+            }
+            case STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID: {
+                struct stivale2_struct_tag_framebuffer *f = (struct stivale2_struct_tag_framebuffer *)tag;
+                e9_puts("Framebuffer tag:");       
+                e9_printf("\tAddress: %x", f->framebuffer_addr);
+                e9_printf("\tWidth:   %d", f->framebuffer_width);
+                e9_printf("\tHeight:  %d", f->framebuffer_height);
+                e9_printf("\tPitch:   %d", f->framebuffer_pitch);
+                e9_printf("\tBPP:     %d", f->framebuffer_bpp);
+                break;
+            }
+            case STIVALE2_STRUCT_TAG_MODULES_ID: {
+                struct stivale2_struct_tag_modules *m = (struct stivale2_struct_tag_modules *)tag;
+                e9_puts("Modules tag:");
+                e9_printf("\tCount: %d", m->module_count);
+                for (size_t i = 0; i < m->module_count; i++) {
+                    struct stivale2_module me = m->modules[i];
+                    e9_printf("\t\t[%x+%x] %s", me.begin, me.end, me.string);
+                }
+                break;
+            }
+            case STIVALE2_STRUCT_TAG_RSDP_ID: {
+                struct stivale2_struct_tag_rsdp *r = (struct stivale2_struct_tag_rsdp *)tag;
+                e9_puts("RSDP tag:");
+                e9_printf("\tRSDP: %x", r->rsdp);
+                break;
+            }
+            case STIVALE2_STRUCT_TAG_EPOCH_ID: {
+                struct stivale2_struct_tag_epoch *e = (struct stivale2_struct_tag_epoch *)tag;
+                e9_puts("Epoch tag:");
+                e9_printf("\tEpoch: %x", e->epoch);
+                break;
+            }
+            case STIVALE2_STRUCT_TAG_FIRMWARE_ID: {
+                struct stivale2_struct_tag_firmware *f = (struct stivale2_struct_tag_firmware *)tag;
+                e9_puts("Firmware tag:");
+                e9_printf("\tFlags: %x", f->flags);
+                break;
+            }
+            case STIVALE2_STRUCT_TAG_SMP_ID: {
+                struct stivale2_struct_tag_smp *s = (struct stivale2_struct_tag_smp *)tag;
+                e9_puts("SMP tag:");
+                e9_printf("\tFlags:     %x", s->flags);
+                e9_printf("\tCPU Count: %d", s->cpu_count);
+                for (size_t i = 0; i < s->cpu_count; i++) {
+                    struct stivale2_smp_info in = s->smp_info[i];
+                    e9_printf("\t\tProcessor ID:   %d", in.processor_id);
+                    e9_printf("\t\tLAPIC ID:       %d", in.lapic_id);
+                    e9_printf("\t\tTarget Stack:   %x", in.target_stack);
+                    e9_printf("\t\tGOTO Address:   %x", in.goto_address);
+                    e9_printf("\t\tExtra Argument: %x", in.extra_argument);
+                }
+                break;
+            }
+            default:
+                e9_printf("BUG: Unidentifier tag %x", tag->identifier);
+        }
+
+        tag = (struct stivale2_tag *)tag->next;
+    }
+
+    // Enter our sublime pale slumber.
+    for (;;);
+}
diff --git a/test/test.asm b/test/test.asm
deleted file mode 100644
index 69bde7c6..00000000
--- a/test/test.asm
+++ /dev/null
@@ -1,42 +0,0 @@
-; This is a compliant "kernel" meant for testing purposes.
-
-; Header
-section .stivale2hdr
-
-stivale_header:
-    dq 0         ; entry point
-    dq stack.top ; rsp
-    dq 0         ; flags
-    dq lv5         ; tags
-
-section .rodata
-
-lv5:
-    dq 0x932f477032007e8f
-    dq smp
-
-smp:
-    dq 0x1ab015085f3273df
-    dq 0
-    dq 1
-
-section .bss
-
-stack:
-    resb 4096
-  .top:
-
-section .text
-
-; Entry point
-
-global _start
-_start:
-    mov rax, 'h e l l '
-    mov rbx, 'o   w o '
-    mov rcx, 'r l d   '
-    mov rdx, 0xb8000
-    mov [rdx], rax
-    mov [rdx+8], rbx
-    mov [rdx+16], rcx
-    jmp $
tab: 248 wrap: offon