diff --git a/include/sys/amd64/loader/util.h b/include/sys/amd64/loader/util.h index ee5c232..0229bd4 100644 --- a/include/sys/amd64/loader/util.h +++ b/include/sys/amd64/loader/util.h @@ -6,6 +6,7 @@ void *memset(void *blk, int v, size_t sz); void *memcpy(void *dst, const void *src, size_t sz); int strcmp(const char *a, const char *b); +int strncmp(const char *a, const char *b, size_t lim); // Debug utils void panic(const char *s); diff --git a/sys/amd64/conf.mk b/sys/amd64/conf.mk index 55a12db..5ee67ba 100644 --- a/sys/amd64/conf.mk +++ b/sys/amd64/conf.mk @@ -56,7 +56,8 @@ kernel_CFLAGS=-ffreestanding \ DIRS+=$(O)/sys/amd64/mm \ $(O)/sys/amd64/hw \ $(O)/sys/amd64/acpi \ - $(O)/sys/amd64/sys + $(O)/sys/amd64/sys \ + $(O)/sys/amd64/image/boot/grub # add .inc includes for asm HEADERS+=$(shell find include -name "*.inc") @@ -73,7 +74,7 @@ $(O)/sys/%.o: sys/%.c $(HEADERS) @$(CC64) $(kernel_CFLAGS) -c -o $@ $< ### Kernel loader build -TARGETS+=$(O)/sys/amd64/loader.elf $(O)/sys/amd64/kernel.elf +TARGETS+=$(O)/sys/amd64/image.iso DIRS+=$(O)/sys/amd64/loader loader_OBJS+=$(O)/sys/amd64/loader/boot.o \ $(O)/sys/amd64/loader/loader.o \ @@ -109,7 +110,14 @@ QEMU_OPTS?=-nographic \ -serial mon:stdio \ -m 512 +$(O)/sys/amd64/image.iso: $(O)/sys/amd64/kernel.elf $(O)/sys/amd64/loader.elf sys/amd64/grub.cfg + @printf " ISO\t%s\n" $(@:$(O)/%=%) + @cp sys/amd64/grub.cfg $(O)/sys/amd64/image/boot/grub/grub.cfg + @cp $(O)/sys/amd64/kernel.elf $(O)/sys/amd64/image/boot/kernel + @cp $(O)/sys/amd64/loader.elf $(O)/sys/amd64/image/boot/loader + @grub-mkrescue -o $(O)/sys/amd64/image.iso $(O)/sys/amd64/image 2>/dev/null + qemu: all @$(QEMU_BIN) \ - -kernel $(O)/sys/amd64/loader.elf \ - -initrd $(O)/sys/amd64/kernel.elf $(QEMU_OPTS) + -cdrom $(O)/sys/amd64/image.iso \ + $(QEMU_OPTS) diff --git a/sys/amd64/grub.cfg b/sys/amd64/grub.cfg new file mode 100644 index 0000000..44e532e --- /dev/null +++ b/sys/amd64/grub.cfg @@ -0,0 +1,5 @@ +menuentry "yggdrasil" { + multiboot /boot/loader + module /boot/kernel kernel + module /boot/test-mod.img initrd +} diff --git a/sys/amd64/loader/loader.c b/sys/amd64/loader/loader.c index 2cea2cd..218273c 100644 --- a/sys/amd64/loader/loader.c +++ b/sys/amd64/loader/loader.c @@ -91,9 +91,37 @@ void loader_main(uint32_t magic, struct multiboot_info *mb_info) { loader_data.multiboot_info_ptr = (uintptr_t) mb_info; struct multiboot_mod_list *mod_list = (struct multiboot_mod_list *) (uintptr_t) mb_info->mods_addr; + const char *kernel_cmdline = NULL; + uintptr_t kernel_mod = 0; + uintptr_t initrd_mod = 0; - if (mb_info->mods_count != 1) { - panic("Expected 1 module"); + if (mb_info->mods_count == 1) { + // Only kernel is provided, ignore cmdline + kernel_mod = mod_list[0].mod_start; + } else if (mb_info->mods_count == 2) { + // initrd and kernel provided + // Find out which is which + + for (size_t i = 0; i < mb_info->mods_count; ++i) { + if (!strncmp((const char *) (uintptr_t) mod_list[i].cmdline, "kernel", 6)) { + if (kernel_mod) { + panic("Two \"kernel\"s provided!"); + } + kernel_mod = mod_list[i].mod_start; + kernel_cmdline = (const char *) (uintptr_t) mod_list[i].cmdline; + } else { + if (initrd_mod) { + panic("Two \"initrd\"s provided!"); + } + initrd_mod = mod_list[i].mod_start; + } + } + } else { + panic("More than two modules provided"); + } + + if (!kernel_mod) { + panic("No kernel to load"); } // Calculate boundaries so we don't overwrite something accidentally @@ -103,6 +131,11 @@ void loader_main(uint32_t magic, struct multiboot_info *mb_info) { } } + if (kernel_cmdline) { + puts("Kernel cmdline: "); + puts(kernel_cmdline); + putc('\n'); + } puts("Modules end addr: "); putx(modules_end); putc('\n'); diff --git a/sys/amd64/loader/util.c b/sys/amd64/loader/util.c index 12cbc4f..9a538aa 100644 --- a/sys/amd64/loader/util.c +++ b/sys/amd64/loader/util.c @@ -23,6 +23,16 @@ int strcmp(const char *a, const char *b) { return *a != *b; } +int strncmp(const char *a, const char *b, size_t n) { + size_t c = 0; + for (; c < n && (*a || *b); ++c, ++a, ++b) { + if (*a != *b) { + return -1; + } + } + return 0; +} + static inline void outb(uint16_t addr, uint8_t v) { asm volatile("outb %0, %1"::"a"(v), "Nd"(addr)); } @@ -74,6 +84,7 @@ void putx(uint64_t v) { void panic(const char *s) { memset((void *) 0xB8000, 0, 80 * 25 * 2); + puts(s); for (size_t i = 0; *s; ++i, ++s) { ((uint16_t *) 0xB8000)[i] = *s | 0x700;