:: commit 15cff010c3d7a1df5e314b062353b277ee681f50

Andy-Python-Programmer <andypythonappdeveloper@gmail.com> — 2021-11-09 05:33

parents: 93cd5b1de3

tests: add basic multiboot2 test kernel

Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
diff --git a/test/Makefile b/test/Makefile
index 28e7bbde..f11b62d5 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -14,6 +14,13 @@ INTERNALLDFLAGS :=         \
 	--no-dynamic-linker    \
 	-ztext
 
+INTERNALLDFLAGSMBOOT2 :=   \
+	-Tmultiboot2.ld        \
+	-nostdlib              \
+	-zmax-page-size=0x1000 \
+	-static                \
+	--no-dynamic-linker    \
+
 INTERNALCFLAGS  :=       \
 	-I../stivale         \
 	-I.                  \
@@ -29,13 +36,21 @@ INTERNALCFLAGS  :=       \
 	-mno-sse2            \
 	-mno-red-zone
 
-all: test.elf
+all: test.elf multiboot2.elf
 
 test.elf: stivale.o stivale2.o e9print.o memory.o
 	$(LD) $^ $(LDFLAGS) $(INTERNALLDFLAGS) -o $@
 
+multiboot2.elf: multiboot2_trampoline.o
+	$(CC) $(CFLAGS) $(INTERNALCFLAGS) -I../stage23/protos -m32 -c multiboot2.c -o multiboot2.o
+	$(CC) $(CFLAGS) $(INTERNALCFLAGS) -m32 -c e9print.c -o e9print.o
+	$(LD) $^ multiboot2.o e9print.o $(LDFLAGS) $(INTERNALLDFLAGSMBOOT2) -m elf_i386 -o $@
+
 %.o: %.c
 	$(CC) $(CFLAGS) $(INTERNALCFLAGS) -c $< -o $@
 
+%.o: %.asm
+	nasm -felf32 $< -o $@
+
 clean:
-	rm -rf test.elf stivale.o stivale2.o e9print.o memory.o
+	rm -rf test.elf stivale.o stivale2.o e9print.o memory.o multiboot2.o multiboot2.elf multiboot2_trampoline.o
diff --git a/test/limine.cfg b/test/limine.cfg
index 9bd6c21b..1cf676f0 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -1,4 +1,4 @@
-DEFAULT_ENTRY=1
+DEFAULT_ENTRY=2
 TIMEOUT=3
 GRAPHICS=yes
 VERBOSE=yes
@@ -21,6 +21,24 @@ KERNEL_CMDLINE=Woah! Another example!
 MODULE_PATH=boot:///boot/bg.bmp
 MODULE_STRING=yooooo
 
+# Test that the module string provided to the kernel will be 
+# the module path since a module string is not specified. 
+# (cc CONFIG.md stivale2.`MODULE_STRING` section)
+MODULE_PATH=boot:///boot/bg.bmp
+
+:Multiboot2 Test
+
+COMMENT=Test of the multiboot2 boot protocol.
+
+PROTOCOL=multiboot2
+RESOLUTION=800x600
+KERNEL_PATH=boot:///boot/multiboot2.elf
+KERNEL_CMDLINE=Woah! Another another example!
+
+MODULE_PATH=boot:///boot/bg.bmp
+MODULE_STRING=This is the background image!
+
+# Test that this should be NULL:
 MODULE_PATH=boot:///boot/bg.bmp
 
 :EFI Chainloading
diff --git a/test/multiboot2.c b/test/multiboot2.c
new file mode 100644
index 00000000..0fb7ec55
--- /dev/null
+++ b/test/multiboot2.c
@@ -0,0 +1,140 @@
+#include <e9print.h>
+#include <stdint.h>
+#include <multiboot2.h>
+
+struct multiboot_info {
+    uint32_t size;
+    uint32_t reserved;
+    struct multiboot_tag *first;
+};
+
+void multiboot2_main(uint32_t magic, struct multiboot_info* mb_info_addr) {
+    if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
+        e9_printf("multiboot2: Invalid magic: %x\n", magic);
+        goto out;
+    }
+
+    e9_printf("Welcome to the multiboot2 test kernel: ");
+    e9_printf("\t size=%d", mb_info_addr->size);
+    e9_printf("\t reserved=%d", mb_info_addr->reserved);
+
+    e9_print("\nTags:\n");
+
+    size_t add_size = 0;
+
+    // NOTE: We set i to 8 to skip size and reserved fields:
+    for (size_t i = 8; i < mb_info_addr->size; i += add_size) { 
+        struct multiboot_tag *tag = (struct multiboot_tag *)((uint8_t *)mb_info_addr + i);
+
+        if (tag->type == MULTIBOOT_TAG_TYPE_END) {
+            break;
+        }
+
+        switch (tag->type) {
+            case MULTIBOOT_TAG_TYPE_CMDLINE: {
+                struct multiboot_tag_string *cmdline = (struct multiboot_tag_string *)tag;
+                e9_printf("\t cmdline:");
+                e9_printf("\t\t string=%s", cmdline->string);
+                break;
+            }
+
+            case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: {
+                struct multiboot_tag_string *name = (struct multiboot_tag_string *)tag;
+                e9_printf("\t bootloader_name:");
+                e9_printf("\t\t string=%s", name->string);
+                break;
+            }
+
+            case MULTIBOOT_TAG_TYPE_MODULE: {
+                struct multiboot_tag_module *module = (struct multiboot_tag_module *)tag;
+                e9_printf("\t module:");
+                e9_printf("\t\t mod_start=%x", module->mod_start);
+                e9_printf("\t\t mod_end=%x", module->mod_end);
+                e9_printf("\t\t cmdline=%s", module->cmdline);
+                break;
+            }
+
+            case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: {
+                struct multiboot_tag_basic_meminfo *meminfo = (struct multiboot_tag_basic_meminfo *)tag;
+                e9_printf("\t basic_meminfo:");
+                e9_printf("\t\t mem_lower=%x", meminfo->mem_lower);
+                e9_printf("\t\t mem_upper=%x", meminfo->mem_upper);
+                break;
+            }
+
+            // unimplemented(Andy-Python-Programmer): MULTIBOOT_TAG_TYPE_BOOTDEV
+
+            case MULTIBOOT_TAG_TYPE_MMAP: {
+                struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap *)tag;
+                e9_printf("\t mmap:");
+                e9_printf("\t\t entry_size=%d", mmap->entry_size);
+                e9_printf("\t\t entry_version=%d", mmap->entry_version);
+                e9_printf("\t\t useable_entries:");
+
+                struct multiboot_mmap_entry *start = (struct multiboot_mmap_entry *)(mmap->entries);
+                struct multiboot_mmap_entry *end = (struct multiboot_mmap_entry *)(mmap->entries + mmap->size);
+
+                size_t total_mem = 0;
+
+                // For now we only print the useable memory map entries since
+                // printing the whole memory map blows my terminal up. We also
+                // iterate through the avaliable memory map entries and add up
+                // to find the total amount of useable memory.
+                for (struct multiboot_mmap_entry* entry = start; entry < end; entry++) {
+                    if (entry->type != MULTIBOOT_MEMORY_AVAILABLE) {
+                        continue;
+                    }
+
+                    e9_printf("\t\t\t addr=%x", entry->addr);
+                    e9_printf("\t\t\t len=%x", entry->len);
+                    e9_printf("\t\t\t type=%x", entry->type);
+
+                    total_mem += entry->len;
+                }
+
+                e9_printf("Total usable memory: %x", total_mem);
+
+                break;
+            }
+        
+            // unimplemented(Andy-Python-Programmer): MULTIBOOT_TAG_TYPE_VBE
+
+            case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: {
+                struct multiboot_tag_framebuffer *fb = (struct multiboot_tag_framebuffer *)tag;
+
+                e9_printf("\t framebuffer:");
+                e9_printf("\t\t framebuffer_pitch: %x", fb->common.framebuffer_pitch);
+                e9_printf("\t\t framebuffer_width: %x", fb->common.framebuffer_width);
+                e9_printf("\t\t framebuffer_height: %x", fb->common.framebuffer_height);
+                e9_printf("\t\t framebuffer_bpp: %x", fb->common.framebuffer_bpp);
+                e9_printf("\t\t framebuffer_type: %x", fb->common.framebuffer_type);
+                e9_printf("\t\t framebuffer_adddress: %x", fb->common.framebuffer_addr);
+
+                switch (fb->common.framebuffer_type) {
+                    case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: {
+                        e9_printf("\t\t framebuffer_red_field_position: %x", fb->framebuffer_red_field_position);
+                        e9_printf("\t\t framebuffer_red_mask_size: %x", fb->framebuffer_red_mask_size);
+                        e9_printf("\t\t framebuffer_green_field_position: %x", fb->framebuffer_green_field_position);
+                        e9_printf("\t\t framebuffer_green_mask_size: %x", fb->framebuffer_green_mask_size);
+                        e9_printf("\t\t framebuffer_blue_field_position: %x", fb->framebuffer_blue_field_position);
+                        e9_printf("\t\t framebuffer_blue_mask_size: %x", fb->framebuffer_blue_mask_size);
+                        break;
+                    }
+
+                    // Rest are unimplemented(Andy-Python-Programmer):
+                }
+
+                break;
+            }
+        }
+
+        add_size = tag->size;
+
+        // Align the size to 8 bytes.
+        if ((add_size % 8) != 0) 
+			add_size += (8 - add_size % 8);
+    }
+
+out:
+    for (;;);
+}
diff --git a/test/multiboot2.ld b/test/multiboot2.ld
new file mode 100644
index 00000000..22de8775
--- /dev/null
+++ b/test/multiboot2.ld
@@ -0,0 +1,35 @@
+ENTRY(_start)
+
+SECTIONS {
+    . = 1M;
+
+    .boot :
+    {
+        /* Ensure that the multiboot header is at the beginning! */
+        *(.multiboot_header)
+    }
+
+    . = ALIGN(4K);
+    .text :
+    {
+        *(.text .text.*)
+    }
+
+    . = ALIGN(4K);
+    .rodata :
+    {
+        *(.rodata.*)
+    }
+
+    . = ALIGN(4K);
+    .data :
+    {
+        *(.data .data.*)
+    }
+
+    . = ALIGN(4K);
+    .bss :
+    {
+        *(.bss .bss.*)
+    }
+}
diff --git a/test/multiboot2_trampoline.asm b/test/multiboot2_trampoline.asm
new file mode 100644
index 00000000..8c22ba5d
--- /dev/null
+++ b/test/multiboot2_trampoline.asm
@@ -0,0 +1,45 @@
+extern multiboot2_main
+
+global _start
+
+section .multiboot_header
+header_start:
+    dd 0xe85250d6 	                                                ; Magic number (multiboot 2)
+    dd 0				                                            ; Architecture 0 (protected mode i386)
+    dd header_end - header_start 	                                ; Header length
+    dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) ; Checksum
+
+align 8
+framebuffer_tag_start:
+    dw 5                                              ; type
+    dw 1                                              ; flags
+    dd framebuffer_tag_end - framebuffer_tag_start    ; size
+    dd 800                                            ; width
+    dd 600                                            ; height
+    dd 32                                             ; depth
+framebuffer_tag_end:
+
+align 8
+    ; Required end tag:
+    dw 0	; type
+    dw 0	; flags
+    dw 8	; size
+header_end:
+
+section .text
+bits 32
+
+_start:
+    cli
+
+    mov esp, stack_top
+
+	push ebx
+	push eax
+
+    call multiboot2_main ; Jump to our multiboot test kernel
+
+section .bss
+stack_bottom:
+    resb 4096 * 16
+stack_top:
tab: 248 wrap: offon