From 3e80780859c4cbe5223ca4329bfd6176f5c2c879 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Mon, 15 Aug 2022 20:48:23 +0200 Subject: kernel: port to multiboot2 --- src/kernel/arch/amd64/3rdparty/multiboot2.h | 417 ++++++++++++++++++++++++++++ src/kernel/arch/amd64/boot.c | 56 ++-- src/kernel/arch/amd64/boot.h | 4 +- src/kernel/arch/amd64/multiboot.h | 37 --- src/kernel/arch/amd64/multiboot.s | 20 -- src/kernel/arch/amd64/multiboot2.S | 30 ++ 6 files changed, 481 insertions(+), 83 deletions(-) create mode 100644 src/kernel/arch/amd64/3rdparty/multiboot2.h delete mode 100644 src/kernel/arch/amd64/multiboot.h delete mode 100644 src/kernel/arch/amd64/multiboot.s create mode 100644 src/kernel/arch/amd64/multiboot2.S (limited to 'src/kernel/arch') diff --git a/src/kernel/arch/amd64/3rdparty/multiboot2.h b/src/kernel/arch/amd64/3rdparty/multiboot2.h new file mode 100644 index 0000000..b181607 --- /dev/null +++ b/src/kernel/arch/amd64/3rdparty/multiboot2.h @@ -0,0 +1,417 @@ +/* multiboot2.h - Multiboot 2 header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 32768 +#define MULTIBOOT_HEADER_ALIGN 8 + +/* The magic field should contain this. */ +#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 + +/* This should be in %eax. */ +#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289 + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000008 + +/* Flags set in the 'flags' member of the multiboot header. */ + +#define MULTIBOOT_TAG_ALIGN 8 +#define MULTIBOOT_TAG_TYPE_END 0 +#define MULTIBOOT_TAG_TYPE_CMDLINE 1 +#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 +#define MULTIBOOT_TAG_TYPE_MODULE 3 +#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4 +#define MULTIBOOT_TAG_TYPE_BOOTDEV 5 +#define MULTIBOOT_TAG_TYPE_MMAP 6 +#define MULTIBOOT_TAG_TYPE_VBE 7 +#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 +#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 +#define MULTIBOOT_TAG_TYPE_APM 10 +#define MULTIBOOT_TAG_TYPE_EFI32 11 +#define MULTIBOOT_TAG_TYPE_EFI64 12 +#define MULTIBOOT_TAG_TYPE_SMBIOS 13 +#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 +#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 +#define MULTIBOOT_TAG_TYPE_NETWORK 16 +#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 +#define MULTIBOOT_TAG_TYPE_EFI_BS 18 +#define MULTIBOOT_TAG_TYPE_EFI32_IH 19 +#define MULTIBOOT_TAG_TYPE_EFI64_IH 20 +#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21 + +#define MULTIBOOT_HEADER_TAG_END 0 +#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 +#define MULTIBOOT_HEADER_TAG_ADDRESS 2 +#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3 +#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4 +#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5 +#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6 +#define MULTIBOOT_HEADER_TAG_EFI_BS 7 +#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8 +#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9 +#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10 + +#define MULTIBOOT_ARCHITECTURE_I386 0 +#define MULTIBOOT_ARCHITECTURE_MIPS32 4 +#define MULTIBOOT_HEADER_TAG_OPTIONAL 1 + +#define MULTIBOOT_LOAD_PREFERENCE_NONE 0 +#define MULTIBOOT_LOAD_PREFERENCE_LOW 1 +#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2 + +#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1 +#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 + +#ifndef ASM_FILE + +typedef unsigned char multiboot_uint8_t; +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* ISA */ + multiboot_uint32_t architecture; + + /* Total header length. */ + multiboot_uint32_t header_length; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; +}; + +struct multiboot_header_tag +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; +}; + +struct multiboot_header_tag_information_request +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t requests[0]; +}; + +struct multiboot_header_tag_address +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; +}; + +struct multiboot_header_tag_entry_address +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t entry_addr; +}; + +struct multiboot_header_tag_console_flags +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t console_flags; +}; + +struct multiboot_header_tag_framebuffer +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +struct multiboot_header_tag_module_align +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; +}; + +struct multiboot_header_tag_relocatable +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t min_addr; + multiboot_uint32_t max_addr; + multiboot_uint32_t align; + multiboot_uint32_t preference; +}; + +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry +{ + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; + multiboot_uint32_t zero; +}; +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_tag +{ + multiboot_uint32_t type; + multiboot_uint32_t size; +}; + +struct multiboot_tag_string +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + char string[0]; +}; + +struct multiboot_tag_module +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + char cmdline[0]; +}; + +struct multiboot_tag_basic_meminfo +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; +}; + +struct multiboot_tag_bootdev +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t biosdev; + multiboot_uint32_t slice; + multiboot_uint32_t part; +}; + +struct multiboot_tag_mmap +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t entry_size; + multiboot_uint32_t entry_version; + struct multiboot_mmap_entry entries[0]; +}; + +struct multiboot_vbe_info_block +{ + multiboot_uint8_t external_specification[512]; +}; + +struct multiboot_vbe_mode_info_block +{ + multiboot_uint8_t external_specification[256]; +}; + +struct multiboot_tag_vbe +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + struct multiboot_vbe_info_block vbe_control_info; + struct multiboot_vbe_mode_info_block vbe_mode_info; +}; + +struct multiboot_tag_framebuffer_common +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + multiboot_uint16_t reserved; +}; + +struct multiboot_tag_framebuffer +{ + struct multiboot_tag_framebuffer_common common; + + union + { + struct + { + multiboot_uint16_t framebuffer_palette_num_colors; + struct multiboot_color framebuffer_palette[0]; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; + +struct multiboot_tag_elf_sections +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t num; + multiboot_uint32_t entsize; + multiboot_uint32_t shndx; + char sections[0]; +}; + +struct multiboot_tag_apm +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint16_t version; + multiboot_uint16_t cseg; + multiboot_uint32_t offset; + multiboot_uint16_t cseg_16; + multiboot_uint16_t dseg; + multiboot_uint16_t flags; + multiboot_uint16_t cseg_len; + multiboot_uint16_t cseg_16_len; + multiboot_uint16_t dseg_len; +}; + +struct multiboot_tag_efi32 +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t pointer; +}; + +struct multiboot_tag_efi64 +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint64_t pointer; +}; + +struct multiboot_tag_smbios +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t major; + multiboot_uint8_t minor; + multiboot_uint8_t reserved[6]; + multiboot_uint8_t tables[0]; +}; + +struct multiboot_tag_old_acpi +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t rsdp[0]; +}; + +struct multiboot_tag_new_acpi +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t rsdp[0]; +}; + +struct multiboot_tag_network +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t dhcpack[0]; +}; + +struct multiboot_tag_efi_mmap +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t descr_size; + multiboot_uint32_t descr_vers; + multiboot_uint8_t efi_mmap[0]; +}; + +struct multiboot_tag_efi32_ih +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t pointer; +}; + +struct multiboot_tag_efi64_ih +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint64_t pointer; +}; + +struct multiboot_tag_load_base_addr +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t load_base_addr; +}; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c index 1041c7d..a03c21d 100644 --- a/src/kernel/arch/amd64/boot.c +++ b/src/kernel/arch/amd64/boot.c @@ -6,25 +6,27 @@ #include #include #include -#include +#include #include #include #include #include #include -static void find_init(struct multiboot_info *multiboot, struct kmain_info *info) -{ - struct multiboot_mod *module = (void*)(long)multiboot->mods; - if (multiboot->mods_count != 1) { - kprintf("unexpected amount of multiboot modules\n"); - panic_invalid_state(); +static void *mbi_tag(void *mbi, uint32_t type) { + struct multiboot_tag *tag; + for (tag = mbi + 8; + tag->type != MULTIBOOT_TAG_TYPE_END; + tag = ((void*)tag) + ((tag->size + 7) & ~7)) + { + if (tag->type == type) + return tag; } - info->init.at = (void*)(long)module->start; - info->init.size = module->end - module->start; + kprintf("bootloader didn't pass required tag type %u\n", type); + panic_invalid_state(); } -void kmain_early(struct multiboot_info *multiboot) { +void kmain_early(void *mbi) { struct kmain_info info; struct fb_info vid; @@ -34,10 +36,27 @@ void kmain_early(struct multiboot_info *multiboot) { kprintf("irq..."); irq_init(); - info.memtop = (void*)(long)(multiboot->mem_upper * 1024); - find_init(multiboot, &info); - info.fb.at = (void*)multiboot->framebuffer_addr; - info.fb.size = multiboot->framebuffer_pitch * multiboot->framebuffer_height; + struct multiboot_tag_basic_meminfo *meminfo; + meminfo = mbi_tag(mbi, MULTIBOOT_TAG_TYPE_BASIC_MEMINFO); + info.memtop = (void*)(long)(meminfo->mem_upper * 1024); + + struct multiboot_tag_framebuffer *framebuf; + framebuf = mbi_tag(mbi, MULTIBOOT_TAG_TYPE_FRAMEBUFFER); + vid.b = (void*)framebuf->common.framebuffer_addr; + vid.pitch = framebuf->common.framebuffer_pitch; + vid.width = framebuf->common.framebuffer_width; + vid.height = framebuf->common.framebuffer_height; + vid.bpp = framebuf->common.framebuffer_bpp; + vid.size = vid.pitch * vid.height; + // TODO framebuffer doesn't need to be part of kmain_info + info.fb.at = vid.b; + info.fb.size = vid.size; + + struct multiboot_tag_module *init; + init = mbi_tag(mbi, MULTIBOOT_TAG_TYPE_MODULE); + info.init.at = (void*)(long)init->mod_start; + info.init.size = init->mod_end - init->mod_start; + kprintf("mem...\n"); mem_init(&info); @@ -49,21 +68,12 @@ void kmain_early(struct multiboot_info *multiboot) { kprintf("ata...\n"); pata_init(); - vid.b = (void*)multiboot->framebuffer_addr; - vid.pitch = multiboot->framebuffer_pitch; - vid.width = multiboot->framebuffer_width; - vid.height = multiboot->framebuffer_height; - vid.bpp = multiboot->framebuffer_bpp; - vid.size = vid.pitch * vid.height; - kprintf("kernel %8x -> %8x\n", 0, &_bss_end); kprintf("init %8x -> %8x\n", info.init.at, info.init.at + info.init.size); kprintf("video %8x -> %8x\n", vid.b, vid.b + vid.size); kprintf("limit %8x\n", info.memtop); - kprintf("framebuffer at 0x%x, %ux%u bpp %u\n", vid.b, vid.width, vid.height, vid.bpp); video_init(vid); - kmain(info); } diff --git a/src/kernel/arch/amd64/boot.h b/src/kernel/arch/amd64/boot.h index 98adff5..251086c 100644 --- a/src/kernel/arch/amd64/boot.h +++ b/src/kernel/arch/amd64/boot.h @@ -1,4 +1,2 @@ #pragma once -#include - -void kmain_early(struct multiboot_info *multiboot); +void kmain_early(void *mbi); diff --git a/src/kernel/arch/amd64/multiboot.h b/src/kernel/arch/amd64/multiboot.h deleted file mode 100644 index 526dd4c..0000000 --- a/src/kernel/arch/amd64/multiboot.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include - -struct multiboot_mod { - uint32_t start; - uint32_t end; - uint32_t str; - uint32_t _reserved; -} __attribute__((packed)); - -struct multiboot_info { - uint32_t flag_mem : 1; - uint32_t flag_boot_device : 1; - uint32_t flag_cmdline : 1; - uint32_t flag_mods : 1; - uint32_t _flag_other : 28; // unimplemented - - uint32_t mem_lower; - uint32_t mem_upper; - - uint32_t boot_device; - - uint32_t cmdline; - - uint32_t mods_count; - uint32_t mods; - - uint8_t _padding[60]; - - uint64_t framebuffer_addr; - uint32_t framebuffer_pitch; - uint32_t framebuffer_width; - uint32_t framebuffer_height; - uint8_t framebuffer_bpp; - uint8_t framebuffer_type; - uint8_t color_info[6]; -} __attribute__((packed)); diff --git a/src/kernel/arch/amd64/multiboot.s b/src/kernel/arch/amd64/multiboot.s deleted file mode 100644 index 4af0cd0..0000000 --- a/src/kernel/arch/amd64/multiboot.s +++ /dev/null @@ -1,20 +0,0 @@ -.set MAGIC, 0x1BADB002 - -/* 1<<0 - align modules on page boundaries. - 1<<2 - enable graphic mode fields */ -.set FLAGS, 1<<0 | 1<<2 -.set CHECKSUM, -(MAGIC + FLAGS) - -.section .multiboot -.align 4 -multiboot_header: - .long MAGIC - .long FLAGS - .long CHECKSUM - - .skip 5 * 4 - - .long 0 - .long 0 - .long 0 - .long 32 diff --git a/src/kernel/arch/amd64/multiboot2.S b/src/kernel/arch/amd64/multiboot2.S new file mode 100644 index 0000000..b001eda --- /dev/null +++ b/src/kernel/arch/amd64/multiboot2.S @@ -0,0 +1,30 @@ +#define ASM_FILE 1 +#include "3rdparty/multiboot2.h" + +.section .multiboot +.align 8 +.set HEADERLEN, multiboot_header_end - multiboot_header +multiboot_header: + .long MULTIBOOT2_HEADER_MAGIC + .long MULTIBOOT_ARCHITECTURE_I386 + .long HEADERLEN + .long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADERLEN) + + .align 8 + .short MULTIBOOT_HEADER_TAG_FRAMEBUFFER + .short 0 + .long 20 + .long 0 + .long 0 + .long 32 + + .align 8 + .short MULTIBOOT_HEADER_TAG_MODULE_ALIGN + .short 0 + .long 8 + + .align 8 + .short MULTIBOOT_HEADER_TAG_END + .short 0 + .long 8 +multiboot_header_end: -- cgit v1.2.3