tests: add basic multiboot2 test kernel
Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
This commit is contained in:
parent
93cd5b1de3
commit
15cff010c3
@ -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
|
||||
|
@ -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
|
||||
|
140
test/multiboot2.c
Normal file
140
test/multiboot2.c
Normal file
@ -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 (;;);
|
||||
}
|
35
test/multiboot2.ld
Normal file
35
test/multiboot2.ld
Normal file
@ -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.*)
|
||||
}
|
||||
}
|
45
test/multiboot2_trampoline.asm
Normal file
45
test/multiboot2_trampoline.asm
Normal file
@ -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:
|
Loading…
Reference in New Issue
Block a user