diff --git a/.gitignore b/.gitignore index 14ce310d..28fb3c93 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /cmake-build-debug/ /bin/ -./DragonOS.iso \ No newline at end of file +DragonOS.iso \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 7e4e51ef..d427ee94 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,6 +13,7 @@ "glib.h": "c", "asm.h": "c", "memory.h": "c", - "irq.h": "c" + "irq.h": "c", + "multiboot2.h": "c" } } \ No newline at end of file diff --git a/kernel/Makefile b/kernel/Makefile index f0cfda68..9622b61c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -7,8 +7,8 @@ DIR_LIB=lib lib_patterns := *.a LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns))) all: kernel -#objcopy -I elf64-x86-64 -S -R ".comment" -O elf64-x86-64 kernel ../bin/kernel/kernel.elf - cp kernel ../bin/kernel/kernel.elf + objcopy -I elf64-x86-64 -S -R ".comment" -O elf64-x86-64 kernel ../bin/kernel/kernel.elf +# cp kernel ../bin/kernel/kernel.elf kernel: head.o entry.o main.o printk.o trap.o mm.o irq.o 8259A.o process.o syscall.o multiboot2.o @@ -18,6 +18,7 @@ kernel: head.o entry.o main.o printk.o trap.o mm.o irq.o 8259A.o process.o sysca head.o: head.S gcc -E head.S > head.s # 预处理 as --64 -o head.o head.s +#gcc -mcmodel=large -fno-builtin -m64 -c head.S -o head.o entry.o: exception/entry.S gcc -E exception/entry.S > exception/entry.s diff --git a/kernel/common/boot_info.h b/kernel/common/boot_info.h index 8e854fab..43ea38ae 100644 --- a/kernel/common/boot_info.h +++ b/kernel/common/boot_info.h @@ -2,64 +2,48 @@ /** * @file boot_info.h * @brief 启动信息接口 - * @author Zone.N (Zone.Niuzh@hotmail.com) - * @version 1.0 - * @date 2021-09-18 - * @copyright MIT LICENSE - * https://github.com/Simple-XX/SimpleKernel - * @par change log: - * - *
DateAuthorDescription - *
2021-09-18digmouse233迁移到 doxygen - *
*/ -#ifndef _BOOT_INFO_H_ -#define _BOOT_INFO_H_ - -#include "stdint.h" -//#include "resource.h" +#pragma once +#include "glib.h" /** * @brief 启动信息接口 * 由引导传递的机器信息处理 * 如 grub2 传递的 multiboot2 结构 - * opensbi 传递的 dtb 结构 * 注意这部分是通过内存传递的,在重新保存之前不能被覆盖 * 架构专有的数据在 dtb.h 或 multiboot2.h * 实现在 dtb.cpp 或 multiboot2.cpp */ -namespace BOOT_INFO { /// 声明,定义在具体的实现中 /// 地址 - extern "C" uintptr_t boot_info_addr; + extern uintptr_t boot_info_addr; /// 长度 - extern size_t boot_info_size; + extern unsigned int boot_info_size; /** * @brief 初始化,定义在具体实现中 * @return true 成功 * @return false 成功 */ - extern bool init(void); + extern int init(void); /** * @brief 获取物理内存信息 * @return resource_t 物理内存资源信息 */ - extern resource_t get_memory(void); + //extern resource_t get_memory(void); /** * @brief 获取 clint 信息 * @return resource_t clint 资源信息 */ - extern resource_t get_clint(void); + //extern resource_t get_clint(void); /** * @brief 获取 plic 信息 * @return resource_t plic 资源信息 */ - extern resource_t get_plic(void); -}; + //extern resource_t get_plic(void); + -#endif /* _BOOT_INFO_H_ */ \ No newline at end of file diff --git a/kernel/common/glib.h b/kernel/common/glib.h index 478b7e62..a4c014c7 100644 --- a/kernel/common/glib.h +++ b/kernel/common/glib.h @@ -23,6 +23,7 @@ : "memory") // 在sfence指令前的写操作必须在sfence指令后的写操作前完成 #define io_lfence() __asm__ __volatile__("lfence\n\t" :: \ : "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。 + /** * @brief 根据结构体变量内某个成员变量member的基地址,计算出该结构体变量的基地址 * @param ptr 指向结构体变量内的成员变量member的指针 @@ -50,6 +51,18 @@ ul round(double x) return (ul)(x + 0.5); } +/** + * @brief 地址按照align进行对齐 + * + * @param addr + * @param _align + * @return ul 对齐后的地址 + */ +ul ALIGN(const ul addr, const ul _align) +{ + return (ul)((addr+_align-1)&(~(_align-1))); +} + //链表数据结构 struct List { diff --git a/kernel/common/printk.c b/kernel/common/printk.c index d68b6817..5a65da30 100644 --- a/kernel/common/printk.c +++ b/kernel/common/printk.c @@ -2,6 +2,8 @@ // Created by longjin on 2022/1/22. // #include "printk.h" +#include "../driver/multiboot2/multiboot2.h" +#include "../mm/mm.h" //#include "linkage.h" struct screen_info pos; @@ -34,22 +36,25 @@ int calculate_max_charNum(int len, int size) return len / size; } -int init_printk(const int width, const int height, unsigned int *FB_address, const int FB_length, const int char_size_x, const int char_size_y) +int init_printk(const int char_size_x, const int char_size_y) { - - pos.width = width; - pos.height = height; + struct multiboot_tag_framebuffer_info_t info; + int reserved; + multiboot2_iter(multiboot2_get_Framebuffer_info, &info, &reserved); + + pos.width = info.framebuffer_width; + pos.height = info.framebuffer_height; pos.char_size_x = char_size_x; pos.char_size_y = char_size_y; - pos.max_x = calculate_max_charNum(width, char_size_x); - pos.max_y = calculate_max_charNum(height, char_size_y); - - pos.FB_address = FB_address; - pos.FB_length = FB_length; + pos.max_x = calculate_max_charNum(pos.width, char_size_x); + pos.max_y = calculate_max_charNum(pos.height, char_size_y); + + // @todo:将来需要将帧缓冲区物理地址填写到这个地址的页表项中 + pos.FB_address = 0xa00000; + pos.FB_length = info.framebuffer_pitch - info.framebuffer_addr; pos.x = 0; pos.y = 0; - return 0; } @@ -81,7 +86,7 @@ void auto_newline() { /** * @brief 超过每行最大字符数,自动换行 - * + * */ if (pos.x > pos.max_x) { @@ -314,7 +319,7 @@ static int vsprintf(char *buf, const char *fmt, va_list args) case 'x': flags |= SMALL; case 'X': - //flags |= SPECIAL; + // flags |= SPECIAL; if (qualifier == 'l') str = write_num(str, va_arg(args, ull), 16, field_width, precision, flags); else @@ -352,13 +357,13 @@ static int vsprintf(char *buf, const char *fmt, va_list args) break; case 'f': // 默认精度为3 - //printk("1111\n"); - //va_arg(args, double); - //printk("222\n"); + // printk("1111\n"); + // va_arg(args, double); + // printk("222\n"); if (precision < 0) precision = 3; - + str = write_float_point_num(str, va_arg(args, double), field_width, precision, flags); break; @@ -383,11 +388,11 @@ static char *write_num(char *str, ull num, int base, int field_width, int precis { /** * @brief 将数字按照指定的要求转换成对应的字符串 - * + * * @param str 要返回的字符串 * @param num 要打印的数值 * @param base 基数 - * @param field_width 区域宽度 + * @param field_width 区域宽度 * @param precision 精度 * @param flags 标志位 */ @@ -486,10 +491,10 @@ static char *write_float_point_num(char *str, double num, int field_width, int p { /** * @brief 将浮点数按照指定的要求转换成对应的字符串 - * + * * @param str 要返回的字符串 * @param num 要打印的数值 - * @param field_width 区域宽度 + * @param field_width 区域宽度 * @param precision 精度 * @param flags 标志位 */ @@ -578,7 +583,7 @@ static void putchar(unsigned int *fb, int Xsize, int x, int y, unsigned int FRco { /** * @brief 在屏幕上指定位置打印字符 - * + * * @param fb 帧缓存线性地址 * @param Xsize 行分辨率 * @param x 左上角列像素点位置 @@ -617,7 +622,7 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, .. { /** * @brief 格式化打印字符串 - * + * * @param FRcolor 前景色 * @param BKcolor 背景色 * @param ... 格式化字符串 diff --git a/kernel/common/printk.h b/kernel/common/printk.h index 3c13fccc..1e81c0ad 100644 --- a/kernel/common/printk.h +++ b/kernel/common/printk.h @@ -57,14 +57,10 @@ char buf[4096]; //vsprintf()的缓冲区 /** * @brief 初始化printk的屏幕信息 * - * @param width 屏幕宽度 - * @param height 屏幕高度 - * @param FB_address 帧缓冲区地址 - * @param FB_length 帧缓冲区长度 * @param char_size_x 字符的列坐标 * @param char_size_y 字符的行坐标 */ -int init_printk(const int width, const int height, unsigned int *FB_address, const int FB_length, const int char_size_x, const int char_size_y); +int init_printk(const int char_size_x, const int char_size_y); /** * @brief Set the printk pos object * diff --git a/kernel/driver/multiboot2/boot.S b/kernel/driver/multiboot2/boot.S deleted file mode 100644 index 7941984d..00000000 --- a/kernel/driver/multiboot2/boot.S +++ /dev/null @@ -1,225 +0,0 @@ - -// 以下是来自 multiboot2 规范的定义 -// 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 - - -// 直接用 -m64 编译出来的是 64 位代码, -// 但是启动后的机器是 32 位的,相当于在 32 位机器上跑 64 位程序。 -// 得加一层跳转到 64 位的 -m32 代码,开启 long 模式后再跳转到以 -m64 编译的代码中 -// 对于 x86_64,需要在启动阶段进入长模式(IA32E),这意味着需要一个临时页表 -// See https://wiki.osdev.org/Creating_a_64-bit_kernel: -// With a 32-bit bootstrap in your kernel - -// 这部分是从保护模式启动 long 模式的代码 -// 工作在 32bit -// 声明这一段代码以 32 位模式编译 -.code32 - -// multiboot2 文件头 -// 计算头长度 -.SET HEADER_LENGTH, multiboot_header_end - multiboot_header -// 计算校验和 -.SET CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH) -// 8 字节对齐 -.align MULTIBOOT_HEADER_ALIGN -// 声明所属段 -.section .multiboot_header -multiboot_header: - // 魔数 - .long MULTIBOOT2_HEADER_MAGIC - // 架构 - .long MULTIBOOT_ARCHITECTURE_I386 - // 头长度 - .long HEADER_LENGTH - // 校验和 - .long CHECKSUM - // 添加其它内容在此,详细信息见 Multiboot2 Specification version 2.0.pdf - .short MULTIBOOT_HEADER_TAG_END - // 结束标记 - .short 0 - .long 8 -multiboot_header_end: - -// 临时页表 4KB/页 -.section .data -.align 0x1000 -pml4: - .skip 0x1000 -pdpt: - .skip 0x1000 -pd: - .skip 0x1000 -pt: - .skip 0x1000 - -// 临时 GDT -.align 16 -gdt64: -null_desc: - .short 0xFFFF - .short 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 -code_desc: - .short 0 - .short 0 - .byte 0 - .byte 0x9A - .byte 0x20 - .byte 0 -data_desc: - .short 0 - .short 0 - .byte 0 - .byte 0x92 - .byte 0 - .byte 0 -user_code_desc: - .short 0 - .short 0 - .byte 0 - .byte 0xFA - .byte 0x20 - .byte 0 -user_data_desc: - .short 0 - .short 0 - .byte 0 - .byte 0xF2 - .byte 0 - .byte 0 -gdt64_pointer: - .short gdt64_pointer-gdt64-1 - .quad gdt64 -gdt64_pointer64: - .short gdt64_pointer-gdt64-1 - .quad gdt64 - -.section .text -.global _start -.type _start, @function -# 在 multiboot2.cpp 中定义 -.extern boot_info_addr -.extern multiboot2_magic -_start: - // 关中断 - cli - // multiboot2_info 结构体指针 - //mov %ebx, boot_info_addr - // 魔数 - // mov %eax, multiboot2_magic - // 从保护模式跳转到长模式 - // 1. 允许 PAE - mov %cr4, %eax - or $(1<<5), %eax - mov %eax, %cr4 - // 2. 设置临时页表 - // 最高级 - mov $pml4, %eax - mov $pdpt, %ebx - or $0x3, %ebx - mov %ebx, 0(%eax) - // 次级 - mov $pdpt, %eax - mov $pd, %ebx - or $0x3, %ebx - mov %ebx, 0(%eax) - // 次低级 - mov $pd, %eax - mov $pt, %ebx - or $0x3, %ebx - mov %ebx, 0(%eax) - // 最低级 - // 循环 512 次,填满一页 - mov $512, %ecx - mov $pt, %eax - mov $0x3, %ebx -.fill_pt: - mov %ebx, 0(%eax) - add $0x1000, %ebx - add $8, %eax - loop .fill_pt - // 填写 CR3 - mov $pml4, %eax - mov %eax, %cr3 - // 3. 切换到 long 模式 - mov $0xC0000080, %ecx - rdmsr - or $(1<<8), %eax - wrmsr - // 4. 开启分页 - mov %cr0, %eax - or $(1<<31), %eax - mov %eax, %cr0 - // 5. 重新设置 GDT - mov $gdt64_pointer, %eax - lgdt 0(%eax) - // 6. 跳转到 64 位代码执行 - jmp $0x8, $_start64 - hlt - ret diff --git a/kernel/driver/multiboot2/multiboot2.c b/kernel/driver/multiboot2/multiboot2.c index 2e1bb0f5..a9290a20 100644 --- a/kernel/driver/multiboot2/multiboot2.c +++ b/kernel/driver/multiboot2/multiboot2.c @@ -1,3 +1,100 @@ +#include "multiboot2.h" +#include "assert.h" -int *boot_info_addr; -int *multiboot2_magic; \ No newline at end of file +#include "../../common/glib.h" + +uintptr_t boot_info_addr; +unsigned int multiboot2_magic; +unsigned int boot_info_size; + +bool multiboot2_init(void) +{ + uintptr_t *addr = (uintptr_t*)boot_info_addr; + if(multiboot2_magic != MULTIBOOT2_BOOTLOADER_MAGIC); + return false; + // addr+0 处保存了大小 + boot_info_size = *(unsigned int *)addr; + return true; +} + +void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, int *), + void *data, int *count) +{ + uintptr_t addr = boot_info_addr; + // 下一字节开始为 tag 信息 + struct iter_data_t *tag = (struct iter_data_t *)(addr + 8); + for (; tag->type != MULTIBOOT_TAG_TYPE_END; + tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8))) + { + if (_fun(tag, data, count) == true) + { + return; + } + } + return; +} + +// 读取 grub2 传递的物理内存信息,保存到 e820map_t 结构体中 +// 一般而言是这样的 +// 地址(长度) 类型 +// 0x00(0x9F000) 0x1 +// 0x9F000(0x1000) 0x2 +// 0xE8000(0x18000) 0x2 +// 0x100000(0x7EF0000) 0x1 +// 0x7FF0000(0x10000) 0x3 +// 0xFFFC0000(0x40000) 0x2 +/** + * @brief 获取multiboot2协议提供的内存区域信息 + * + * @param _iter_data 要被迭代的信息的结构体 + * @param _data 返回信息的结构体指针 + * @param count 返回数组的长度 + * @return true + * @return false + */ +bool multiboot2_get_memory(const struct iter_data_t *_iter_data, void *data, int *count) +{ + if (_iter_data->type != MULTIBOOT_TAG_TYPE_MMAP) + return false; + + struct multiboot_mmap_entry_t *resource = (struct multiboot_mmap_entry_t *)data; + struct multiboot_mmap_entry_t *mmap = ((struct multiboot_tag_mmap_t *)_iter_data)->entries; + *count = (uint8_t *)_iter_data + _iter_data->size; + for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size; + mmap = (struct multiboot_mmap_entry_t *)((uint8_t *)mmap + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size)) + { + *resource = *mmap; + // 将指针进行增加 + resource = (struct multiboot_mmap_entry_t *)((uint8_t *)resource + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size); + } + return true; +} + +/** + * @brief 获取VBE信息 + * + * @param _iter_data 要被迭代的信息的结构体 + * @param _data 返回信息的结构体指针 + */ +bool multiboot2_get_VBE_info(const struct iter_data_t *_iter_data, void *data, int *reserved) +{ + + if (_iter_data->type != MULTIBOOT_TAG_TYPE_VBE) + return false; + *(struct multiboot_tag_vbe_t *)data = *(struct multiboot_tag_vbe_t *)_iter_data; + return true; +} + +/** + * @brief 获取帧缓冲区信息 + * + * @param _iter_data 要被迭代的信息的结构体 + * @param _data 返回信息的结构体指针 + */ +bool multiboot2_get_Framebuffer_info(const struct iter_data_t *_iter_data, void *data, int *reserved) +{ + if(_iter_data->type !=MULTIBOOT_TAG_TYPE_FRAMEBUFFER) + return false; + *(struct multiboot_tag_framebuffer_info_t *)data = *(struct multiboot_tag_framebuffer_info_t*)_iter_data; + return true; +} \ No newline at end of file diff --git a/kernel/driver/multiboot2/multiboot2.cpp b/kernel/driver/multiboot2/multiboot2.cpp deleted file mode 100644 index b92dcfed..00000000 --- a/kernel/driver/multiboot2/multiboot2.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file multiboot2.cpp - * @brief multiboot2 解析实现 - * @author Zone.N (Zone.Niuzh@hotmail.com) - * @version 1.0 - * @date 2021-09-18 - * @copyright MIT LICENSE - * https://github.com/Simple-XX/SimpleKernel - * @par change log: - * - *
DateAuthorDescription - *
2021-09-18digmouse233迁移到 doxygen - *
- */ - -#include "assert.h" -#include "stdio.h" -//#include "common.h" -#include "multiboot2.h" -#include "boot_info.h" -//#include "resource.h" -//#include "pmm.h" - -/// @todo 优化 -void MULTIBOOT2::multiboot2_iter(bool (*_fun)(const iter_data_t *, void *), - void *_data) { - uintptr_t addr = BOOT_INFO::boot_info_addr; - // 下一字节开始为 tag 信息 - iter_data_t *tag = (iter_data_t *)(addr + 8); - for (; tag->type != MULTIBOOT_TAG_TYPE_END; - tag = (iter_data_t *)((uint8_t *)tag + COMMON::ALIGN(tag->size, 8))) { - if (_fun(tag, _data) == true) { - return; - } - } - return; -} - -bool MULTIBOOT2::multiboot2_init(void) { - uintptr_t addr = BOOT_INFO::boot_info_addr; - // 判断魔数是否正确 - assert(BOOT_INFO::multiboot2_magic == MULTIBOOT2_BOOTLOADER_MAGIC); - assert((reinterpret_cast(addr) & 7) == 0); - // addr+0 保存大小 - BOOT_INFO::boot_info_size = *(uint32_t *)addr; - return true; -} - -// 读取 grub2 传递的物理内存信息,保存到 e820map_t 结构体中 -// 一般而言是这样的 -// 地址(长度) 类型 -// 0x00(0x9F000) 0x1 -// 0x9F000(0x1000) 0x2 -// 0xE8000(0x18000) 0x2 -// 0x100000(0x7EF0000) 0x1 -// 0x7FF0000(0x10000) 0x3 -// 0xFFFC0000(0x40000) 0x2 -bool MULTIBOOT2::get_memory(const iter_data_t *_iter_data, void *_data) { - if (_iter_data->type != MULTIBOOT2::MULTIBOOT_TAG_TYPE_MMAP) { - return false; - } - resource_t *resource = (resource_t *)_data; - resource->type = resource_t::MEM; - resource->name = (char *)"available phy memory"; - resource->mem.addr = 0x0; - resource->mem.len = 0; - MULTIBOOT2::multiboot_mmap_entry_t *mmap = - ((MULTIBOOT2::multiboot_tag_mmap_t *)_iter_data)->entries; - for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size; - mmap = (MULTIBOOT2::multiboot_mmap_entry_t - *)((uint8_t *)mmap + - ((MULTIBOOT2::multiboot_tag_mmap_t *)_iter_data) - ->entry_size)) { - // 如果是可用内存或地址小于 1M - // 这里将 0~1M 的空间全部算为可用,在 c++ 库可用后进行优化 - if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE || - mmap->addr < 1 * COMMON::MB) { - // 长度+ - resource->mem.len += mmap->len; - } - } - return true; -} - -namespace BOOT_INFO { - // 地址 - uintptr_t boot_info_addr; - // 长度 - size_t boot_info_size; - // 魔数 - uint32_t multiboot2_magic; - - bool init(void) { - auto res = MULTIBOOT2::multiboot2_init(); - info("BOOT_INFO init.\n"); - return res; - } - - resource_t get_memory(void) { - resource_t resource; - MULTIBOOT2::multiboot2_iter(MULTIBOOT2::get_memory, &resource); - return resource; - } -}; \ No newline at end of file diff --git a/kernel/driver/multiboot2/multiboot2.h b/kernel/driver/multiboot2/multiboot2.h index 02386184..0b8cf556 100644 --- a/kernel/driver/multiboot2/multiboot2.h +++ b/kernel/driver/multiboot2/multiboot2.h @@ -1,24 +1,13 @@ /** * @file multiboot2.h * @brief multiboot2 解析 - * @author Zone.N (Zone.Niuzh@hotmail.com) - * @version 1.0 - * @date 2021-09-18 - * @copyright MIT LICENSE - * https://github.com/Simple-XX/SimpleKernel - * @par change log: - * - *
DateAuthorDescription - *
2021-09-18digmouse233迁移到 doxygen - *
*/ -#ifndef _MULTIBOOT2_H_ -#define _MULTIBOOT2_H_ +#pragma once #include "stdint.h" #include "stdbool.h" -#include "boot_info.h" +#include "../../common/boot_info.h" /// @see Multiboot2 Specification version 2.0.pdf // 启动后,在 32 位内核进入点,机器状态如下: @@ -35,300 +24,427 @@ /** * @brief MULTIBOOT2 接口抽象 */ -class MULTIBOOT2 { -private: - /* How many bytes from the start of the file we search for the header. */ - static constexpr const uint32_t MULTIBOOT_SEARCH = 32768; - static constexpr const uint32_t MULTIBOOT_HEADER_ALIGN = 8; - /* The magic field should contain this. */ - static constexpr const uint32_t MULTIBOOT2_HEADER_MAGIC = 0xe85250d6; +extern unsigned int multiboot2_magic; - /* This should be in %eax. */ - static constexpr const uint32_t MULTIBOOT2_BOOTLOADER_MAGIC = 0x36d76289; +/* How many bytes from the start of the file we search for the header. */ +static const unsigned int MULTIBOOT_SEARCH = 32768; +static const unsigned int MULTIBOOT_HEADER_ALIGN = 8; - /* Alignment of multiboot modules. */ - static constexpr const uint32_t MULTIBOOT_MOD_ALIGN = 0x00001000; +/* The magic field should contain this. */ +static const unsigned int MULTIBOOT2_HEADER_MAGIC = 0xe85250d6; - /* Alignment of the multiboot info structure. */ - static constexpr const uint32_t MULTIBOOT_INFO_ALIGN = 0x00000008; +/* This should be in %eax. */ +static const unsigned int MULTIBOOT2_BOOTLOADER_MAGIC = 0x36d76289; - /* Flags set in the 'flags' member of the multiboot header. */ +/* Alignment of multiboot modules. */ +static const unsigned int MULTIBOOT_MOD_ALIGN = 0x00001000; - static constexpr const uint32_t MULTIBOOT_TAG_ALIGN = 8; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_END = 0; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_CMDLINE = 1; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME = 2; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_MODULE = 3; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_BASIC_MEMINFO = 4; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_BOOTDEV = 5; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_MMAP = 6; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_VBE = 7; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_FRAMEBUFFER = 8; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_ELF_SECTIONS = 9; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_APM = 10; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI32 = 11; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI64 = 12; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_SMBIOS = 13; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_ACPI_OLD = 14; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_ACPI_NEW = 15; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_NETWORK = 16; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI_MMAP = 17; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI_BS = 18; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI32_IH = 19; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI64_IH = 20; - static constexpr const uint32_t MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR = 21; +/* Alignment of the multiboot info structure. */ +static const unsigned int MULTIBOOT_INFO_ALIGN = 0x00000008; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_END = 0; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST = - 1; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ADDRESS = 2; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS = 3; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS = 4; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_FRAMEBUFFER = 5; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_MODULE_ALIGN = 6; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_EFI_BS = 7; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 = - 8; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 = - 9; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_RELOCATABLE = 10; +/* Flags set in the 'flags' member of the multiboot header. */ - static constexpr const uint32_t MULTIBOOT_ARCHITECTURE_I386 = 0; - static constexpr const uint32_t MULTIBOOT_ARCHITECTURE_MIPS32 = 4; - static constexpr const uint32_t MULTIBOOT_HEADER_TAG_OPTIONAL = 1; +static const unsigned int MULTIBOOT_TAG_ALIGN = 8; +static const unsigned int MULTIBOOT_TAG_TYPE_END = 0; +static const unsigned int MULTIBOOT_TAG_TYPE_CMDLINE = 1; +static const unsigned int MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME = 2; +static const unsigned int MULTIBOOT_TAG_TYPE_MODULE = 3; +static const unsigned int MULTIBOOT_TAG_TYPE_BASIC_MEMINFO = 4; +static const unsigned int MULTIBOOT_TAG_TYPE_BOOTDEV = 5; +static const unsigned int MULTIBOOT_TAG_TYPE_MMAP = 6; +static const unsigned int MULTIBOOT_TAG_TYPE_VBE = 7; +static const unsigned int MULTIBOOT_TAG_TYPE_FRAMEBUFFER = 8; +static const unsigned int MULTIBOOT_TAG_TYPE_ELF_SECTIONS = 9; +static const unsigned int MULTIBOOT_TAG_TYPE_APM = 10; +static const unsigned int MULTIBOOT_TAG_TYPE_EFI32 = 11; +static const unsigned int MULTIBOOT_TAG_TYPE_EFI64 = 12; +static const unsigned int MULTIBOOT_TAG_TYPE_SMBIOS = 13; +static const unsigned int MULTIBOOT_TAG_TYPE_ACPI_OLD = 14; +static const unsigned int MULTIBOOT_TAG_TYPE_ACPI_NEW = 15; +static const unsigned int MULTIBOOT_TAG_TYPE_NETWORK = 16; +static const unsigned int MULTIBOOT_TAG_TYPE_EFI_MMAP = 17; +static const unsigned int MULTIBOOT_TAG_TYPE_EFI_BS = 18; +static const unsigned int MULTIBOOT_TAG_TYPE_EFI32_IH = 19; +static const unsigned int MULTIBOOT_TAG_TYPE_EFI64_IH = 20; +static const unsigned int MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR = 21; - static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_NONE = 0; - static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_LOW = 1; - static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_HIGH = 2; +static const unsigned int MULTIBOOT_HEADER_TAG_END = 0; +static const unsigned int MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST = + 1; +static const unsigned int MULTIBOOT_HEADER_TAG_ADDRESS = 2; +static const unsigned int MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS = 3; +static const unsigned int MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS = 4; +static const unsigned int MULTIBOOT_HEADER_TAG_FRAMEBUFFER = 5; +static const unsigned int MULTIBOOT_HEADER_TAG_MODULE_ALIGN = 6; +static const unsigned int MULTIBOOT_HEADER_TAG_EFI_BS = 7; +static const unsigned int MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 = + 8; +static const unsigned int MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 = + 9; +static const unsigned int MULTIBOOT_HEADER_TAG_RELOCATABLE = 10; - static constexpr const uint32_t MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED = - 1; - static constexpr const uint32_t MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED = - 2; +static const unsigned int MULTIBOOT_ARCHITECTURE_I386 = 0; +static const unsigned int MULTIBOOT_ARCHITECTURE_MIPS32 = 4; +static const unsigned int MULTIBOOT_HEADER_TAG_OPTIONAL = 1; - struct multiboot_header_t { - // Must be MULTIBOOT_MAGIC - see above. - uint32_t magic; - // ISA - uint32_t architecture; - // Total header length. - uint32_t header_length; - // The above fields plus this one must equal 0 mod 2^32. - uint32_t checksum; - }; +static const unsigned int MULTIBOOT_LOAD_PREFERENCE_NONE = 0; +static const unsigned int MULTIBOOT_LOAD_PREFERENCE_LOW = 1; +static const unsigned int MULTIBOOT_LOAD_PREFERENCE_HIGH = 2; - struct multiboot_header_tag_t { - uint16_t type; - uint16_t flags; - uint32_t size; - }; +static const unsigned int MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED = + 1; +static const unsigned int MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED = + 2; - struct multiboot_header_tag_information_request_t : multiboot_header_tag_t { - uint32_t requests[0]; - }; +static const unsigned int MULTIBOOT_MEMORY_AVAILABLE = 1; +static const unsigned int MULTIBOOT_MEMORY_RESERVED = 2; +static const unsigned int MULTIBOOT_MEMORY_ACPI_RECLAIMABLE = 3; +static const unsigned int MULTIBOOT_MEMORY_NVS = 4; +static const unsigned int MULTIBOOT_MEMORY_BADRAM = 5; - struct multiboot_header_tag_address_t : multiboot_header_tag_t { - uint32_t header_addr; - uint32_t load_addr; - uint32_t load_end_addr; - uint32_t bss_end_addr; - }; - - struct multiboot_header_tag_entry_address_t : multiboot_header_tag_t { - uint32_t entry_addr; - }; - - struct multiboot_header_tag_console_flags_t : multiboot_header_tag_t { - uint32_t console_flags; - }; - - struct multiboot_header_tag_framebuffer_t : multiboot_header_tag_t { - uint32_t width; - uint32_t height; - uint32_t depth; - }; - - struct multiboot_header_tag_module_align_t : multiboot_header_tag_t { - ; - }; - - struct multiboot_header_tag_relocatable_t : multiboot_header_tag_t { - uint32_t min_addr; - uint32_t max_addr; - uint32_t align; - uint32_t preference; - }; - - struct multiboot_color_t { - uint8_t red; - uint8_t green; - uint8_t blue; - }; - - static constexpr const uint32_t MULTIBOOT_MEMORY_AVAILABLE = 1; - static constexpr const uint32_t MULTIBOOT_MEMORY_RESERVED = 2; - static constexpr const uint32_t MULTIBOOT_MEMORY_ACPI_RECLAIMABLE = 3; - static constexpr const uint32_t MULTIBOOT_MEMORY_NVS = 4; - static constexpr const uint32_t MULTIBOOT_MEMORY_BADRAM = 5; - struct multiboot_mmap_entry_t { - uint64_t addr; - uint64_t len; - uint32_t type; - uint32_t zero; - }; - - struct multiboot_tag_t { - uint32_t type; - uint32_t size; - }; - - struct multiboot_tag_string_t : multiboot_tag_t { - char string[0]; - }; - - struct multiboot_tag_module_t : multiboot_tag_t { - uint32_t mod_start; - uint32_t mod_end; - char cmdline[0]; - }; - - struct multiboot_tag_basic_meminfo_t : multiboot_tag_t { - uint32_t mem_lower; - uint32_t mem_upper; - }; - - struct multiboot_tag_bootdev_t : multiboot_tag_t { - uint32_t biosdev; - uint32_t slice; - uint32_t part; - }; - - struct multiboot_tag_mmap_t : multiboot_tag_t { - uint32_t entry_size; - uint32_t entry_version; - multiboot_mmap_entry_t entries[0]; - }; - - struct multiboot_vbe_info_block_t { - uint8_t external_specification[512]; - }; - - struct multiboot_vbe_mode_info_block_t { - uint8_t external_specification[256]; - }; - - struct multiboot_tag_vbe_t : multiboot_tag_t { - uint16_t vbe_mode; - uint16_t vbe_interface_seg; - uint16_t vbe_interface_off; - uint16_t vbe_interface_len; - - multiboot_vbe_info_block_t vbe_control_info; - multiboot_vbe_mode_info_block_t vbe_mode_info; - }; - - struct multiboot_tag_elf_sections_t : multiboot_tag_t { - uint32_t num; - uint32_t entsize; - // 段字符串表索引 - uint32_t shndx; - char sections[0]; - }; - - struct multiboot_tag_apm_t : multiboot_tag_t { - uint16_t version; - uint16_t cseg; - uint32_t offset; - uint16_t cseg_16; - uint16_t dseg; - uint16_t flags; - uint16_t cseg_len; - uint16_t cseg_16_len; - uint16_t dseg_len; - }; - - struct multiboot_tag_efi32_t : multiboot_tag_t { - uint32_t pointer; - }; - - struct multiboot_tag_efi64_t : multiboot_tag_t { - uint64_t pointer; - }; - - struct multiboot_tag_smbios_t : multiboot_tag_t { - uint8_t major; - uint8_t minor; - uint8_t reserved[6]; - uint8_t tables[0]; - }; - - struct multiboot_tag_old_acpi_t : multiboot_tag_t { - uint8_t rsdp[0]; - }; - - struct multiboot_tag_new_acpi_t : multiboot_tag_t { - uint8_t rsdp[0]; - }; - - struct multiboot_tag_network_t : multiboot_tag_t { - uint8_t dhcpack[0]; - }; - - struct multiboot_tag_efi_mmap_t : multiboot_tag_t { - uint32_t descr_size; - uint32_t descr_vers; - uint8_t efi_mmap[0]; - }; - - struct multiboot_tag_efi32_ih_t : multiboot_tag_t { - uint32_t pointer; - }; - - struct multiboot_tag_efi64_ih_t : multiboot_tag_t { - uint64_t pointer; - }; - - struct multiboot_tag_load_base_addr_t : multiboot_tag_t { - uint32_t load_base_addr; - }; - - // 迭代变量 - // 与 multiboot_tag_t 相同 - struct iter_data_t { - uint32_t type; - uint32_t size; - }; - -public: - /** - * @brief 初始化 - * @return true 成功 - * @return false 失败 - */ - static bool multiboot2_init(void); - - /** - * @brief 迭代器 - * @param _fun 迭代操作 - * @param _data 数据 - */ - static void multiboot2_iter(bool (*_fun)(const iter_data_t *, void *), - void *_data); - - /** - * @brief 获取内存信息 - * @param _iter_data 迭代变量 - * @param _data 数据 - * @return true 成功 - * @return false 失败 - */ - static bool get_memory(const iter_data_t *_iter_data, void *_data); +struct multiboot_header_t +{ + // Must be MULTIBOOT_MAGIC - see above. + unsigned int magic; + // ISA + unsigned int architecture; + // Total header length. + unsigned int header_length; + // The above fields plus this one must equal 0 mod 2^32. + unsigned int checksum; }; -namespace BOOT_INFO { - /// 魔数 - extern "C" uint32_t multiboot2_magic; +struct multiboot_header_tag_t +{ + uint16_t type; + uint16_t flags; + unsigned int size; +}; +struct multiboot_header_tag_information_request_t +{ + uint16_t type; + uint16_t flags; + unsigned int size; + + unsigned int requests[0]; +}; +struct multiboot_header_tag_address_t +{ + uint16_t type; + uint16_t flags; + unsigned int size; + + unsigned int header_addr; + unsigned int load_addr; + unsigned int load_end_addr; + unsigned int bss_end_addr; }; -#endif /* _MULTIBOOT2_H_ */ \ No newline at end of file +struct multiboot_header_tag_entry_address_t +{ + uint16_t type; + uint16_t flags; + unsigned int size; + + unsigned int entry_addr; +}; + +struct multiboot_header_tag_console_flags_t +{ + uint16_t type; + uint16_t flags; + unsigned int size; + + unsigned int console_flags; +}; + +struct multiboot_header_tag_framebuffer_t +{ + uint16_t type; + uint16_t flags; + unsigned int size; + + unsigned int width; + unsigned int height; + unsigned int depth; +}; + +struct multiboot_header_tag_module_align_t +{ + uint16_t type; + uint16_t flags; + unsigned int size; +}; + +struct multiboot_header_tag_relocatable_t +{ + uint16_t type; + uint16_t flags; + unsigned int size; + + unsigned int min_addr; + unsigned int max_addr; + unsigned int align; + unsigned int preference; +}; + +struct multiboot_color_t +{ + uint8_t red; + uint8_t green; + uint8_t blue; +}; + +// multiboot2协议的内存区域信息 +struct multiboot_mmap_entry_t +{ + uint64_t addr; + uint64_t len; + unsigned int type; + unsigned int reserved; +}; + +struct multiboot_tag_t +{ + unsigned int type; + unsigned int size; +}; + +struct multiboot_tag_string_t +{ + struct multiboot_tag_t tag_t; + char string[0]; +}; + +struct multiboot_tag_module_t +{ + struct multiboot_tag_t tag_t; + unsigned int mod_start; + unsigned int mod_end; + char cmdline[0]; +}; + +struct multiboot_tag_basic_meminfo_t +{ + struct multiboot_tag_t tag_t; + unsigned int mem_lower; + unsigned int mem_upper; +}; + +struct multiboot_tag_bootdev_t +{ + struct multiboot_tag_t tag_t; + unsigned int biosdev; + unsigned int slice; + unsigned int part; +}; + +struct multiboot_tag_mmap_t +{ + struct multiboot_tag_t tag_t; + unsigned int entry_size; + unsigned int entry_version; + struct multiboot_mmap_entry_t entries[0]; +}; + +struct multiboot_vbe_info_block_t +{ + uint8_t external_specification[512]; +}; + +struct multiboot_vbe_mode_info_block_t +{ + uint8_t external_specification[256]; +}; + +// bootloader传递的VBE信息的结构体 +struct multiboot_tag_vbe_t +{ + struct multiboot_tag_t tag_t; + uint16_t vbe_mode; + uint16_t vbe_interface_seg; + uint16_t vbe_interface_off; + uint16_t vbe_interface_len; + + // The fields ‘vbe_control_info’ and ‘vbe_mode_info’ contain VBE control information returned by the VBE Function 00h and VBE mode information + // returned by the VBE Function 01h, respectively. + struct multiboot_vbe_info_block_t vbe_control_info; + struct multiboot_vbe_mode_info_block_t vbe_mode_info; +}; + +struct multiboot_tag_framebuffer_info_t +{ + struct multiboot_tag_t tag_t; + uint64_t framebuffer_addr; + uint32_t framebuffer_pitch; // 帧缓存上界 + // width and height expressed in pixels except type=2 + // when type=2, they are expressed in characters + uint32_t framebuffer_width; + uint32_t framebuffer_height; + // number of bits per pixel. + uint8_t framebuffer_bpp; + // 帧缓存的类型 + uint8_t framebuffer_type; + uint8_t reserved; +}; + +// indexed color +struct multiboot_tag_framebuffer_info_type0_t +{ + struct multiboot_tag_framebuffer_info_t; + uint32_t framebuffer_palette_num_colors; + struct multiboot_color_t color_desc; +}; + +// direct RGB color +struct multiboot_tag_framebuffer_info_type1_t +{ + struct multiboot_tag_framebuffer_info_t; + + uint8_t framebuffer_red_field_position; + uint8_t framebuffer_red_mask_size; + uint8_t framebuffer_green_field_position; + uint8_t framebuffer_green_mask_size; + uint8_t framebuffer_blue_field_position; + uint8_t framebuffer_blue_mask_size; +}; + +struct multiboot_tag_elf_sections_t +{ + struct multiboot_tag_t tag_t; + unsigned int num; + unsigned int entsize; + // 段字符串表索引 + unsigned int shndx; + char sections[0]; +}; + +struct multiboot_tag_apm_t +{ + struct multiboot_tag_t tag_t; + uint16_t version; + uint16_t cseg; + unsigned int offset; + uint16_t cseg_16; + uint16_t dseg; + uint16_t flags; + uint16_t cseg_len; + uint16_t cseg_16_len; + uint16_t dseg_len; +}; + +struct multiboot_tag_efi32_t +{ + struct multiboot_tag_t tag_t; + unsigned int pointer; +}; + +struct multiboot_tag_efi64_t +{ + struct multiboot_tag_t tag_t; + uint64_t pointer; +}; + +struct multiboot_tag_smbios_t +{ + struct multiboot_tag_t tag_t; + uint8_t major; + uint8_t minor; + uint8_t reserved[6]; + uint8_t tables[0]; +}; + +struct multiboot_tag_old_acpi_t +{ + struct multiboot_tag_t tag_t; + uint8_t rsdp[0]; +}; + +struct multiboot_tag_new_acpi_t +{ + struct multiboot_tag_t tag_t; + uint8_t rsdp[0]; +}; + +struct multiboot_tag_network_t +{ + struct multiboot_tag_t tag_t; + uint8_t dhcpack[0]; +}; + +struct multiboot_tag_efi_mmap_t +{ + struct multiboot_tag_t tag_t; + unsigned int descr_size; + unsigned int descr_vers; + uint8_t efi_mmap[0]; +}; + +struct multiboot_tag_efi32_ih_t +{ + struct multiboot_tag_t tag_t; + unsigned int pointer; +}; + +struct multiboot_tag_efi64_ih_t +{ + struct multiboot_tag_t tag_t; + uint64_t pointer; +}; + +struct multiboot_tag_load_base_addr_t +{ + struct multiboot_tag_t tag_t; + unsigned int load_base_addr; +}; + +// 迭代变量 +// 与 multiboot_tag_t 相同 +struct iter_data_t +{ + unsigned int type; + unsigned int size; +}; + +/** + * @brief 初始化 + * @return true 成功 + * @return false 失败 + */ +static bool multiboot2_init(void); + +/** + * @brief 迭代器 + * @param _fun 迭代操作 + * @param _data 数据 + */ +void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, int *), + void *_data, int *count); + +/** + * @brief 获取multiboot2协议提供的内存区域信息 + * + * @param _iter_data 要被迭代的信息的结构体 + * @param _data 返回信息的结构体指针 + * @param count 返回数组的长度 + * @return true + * @return false + */ +bool multiboot2_get_memory(const struct iter_data_t *_iter_data, void *_data, int *count); + +/** + * @brief 获取VBE信息 + * + * @param _iter_data 要被迭代的信息的结构体 + * @param _data 返回信息的结构体指针 + */ +bool multiboot2_get_VBE_info(const struct iter_data_t *_iter_data, void *_data, int *reserved); + +/** + * @brief 获取帧缓冲区信息 + * + * @param _iter_data 要被迭代的信息的结构体 + * @param _data 返回信息的结构体指针 + */ +bool multiboot2_get_Framebuffer_info(const struct iter_data_t *_iter_data, void *_data, int *reserved); \ No newline at end of file diff --git a/kernel/head.S b/kernel/head.S index b1f4af66..65fe9d8a 100644 --- a/kernel/head.S +++ b/kernel/head.S @@ -72,6 +72,74 @@ #define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 +// 以下是来自 multiboot2 规范的定义 +// 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 + + + // 直接用 -m64 编译出来的是 64 位代码, // 但是启动后的机器是 32 位的,相当于在 32 位机器上跑 64 位程序。 // 得加一层跳转到 64 位的 -m32 代码,开启 long 模式后再跳转到以 -m64 编译的代码中 @@ -103,12 +171,25 @@ multiboot_header: // 校验和 .long CHECKSUM // 添加其它内容在此,详细信息见 Multiboot2 Specification version 2.0.pdf + +// 设置帧缓冲区 +.align 8 +framebuffer_tag_start: + .short MULTIBOOT_HEADER_TAG_FRAMEBUFFER + .short MULTIBOOT_HEADER_TAG_OPTIONAL + .long framebuffer_tag_end - framebuffer_tag_start + .long 1440 + .long 900 + .long 32 +framebuffer_tag_end: +.align 8 .short MULTIBOOT_HEADER_TAG_END // 结束标记 .short 0 .long 8 multiboot_header_end: + // 临时页表 4KB/页 .section .data .align 0x1000 @@ -172,13 +253,14 @@ gdt64_pointer64: # 在 multiboot2.cpp 中定义 .extern boot_info_addr .extern multiboot2_magic +.extern _start64 _start: // 关中断 cli // multiboot2_info 结构体指针 - //mov %ebx, boot_info_addr + mov %ebx, boot_info_addr // 魔数 - //mov %eax, multiboot2_magic + mov %eax, multiboot2_magic / 从保护模式跳转到长模式 // 1. 允许 PAE mov %cr4, %eax @@ -238,6 +320,7 @@ _start: hlt ret + .section .text .code64 @@ -279,6 +362,8 @@ ENTRY(_start64) mov $__PDE, %ebx or $0x7, %ebx mov %ebx, 0(%eax) + + // ==== 加载CR3寄存器 movq $__PML4E, %rax //设置页目录基地址 movq %rax, %cr3 @@ -421,7 +506,7 @@ __PDE: .quad 0x400087 .quad 0x600087 .quad 0x800087 - .quad 0xe0000087 /*0x a00000*/ + .quad 0xe0000087 /*虚拟地址0x a00000 帧缓冲区映射到这里*/ .quad 0xe0200087 .quad 0xe0400087 .quad 0xe0600087 /*0x1000000*/ diff --git a/kernel/link.lds b/kernel/link.lds index b4897f60..694dcc69 100644 --- a/kernel/link.lds +++ b/kernel/link.lds @@ -2,15 +2,15 @@ OUTPUT_FORMAT("elf64-x86-64","elf64-x86-64","elf64-x86-64") OUTPUT_ARCH(i386:x86-64) ENTRY(_start) + SECTIONS { - . = 0; - - - . = 1M; + . = 0x100000; + .text : { + _text = .; *(.multiboot_header) *(.text) @@ -23,10 +23,9 @@ SECTIONS _data = .; *(.data) - *(.eh_frame) _edata = .; } - .rodata : + .rodata : { _rodata = .; *(.rodata) @@ -42,5 +41,10 @@ SECTIONS _ebss = .; } + .eh_frame : + { + *(.eh_frame) + } + _end = .; } diff --git a/kernel/main.c b/kernel/main.c index 102ca4b9..274eac8e 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -12,7 +12,7 @@ #include "process/process.h" #include "syscall/syscall.h" -unsigned int *FR_address = (unsigned int *)0xffff800000a00000; //帧缓存区的地址 +unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址 // char fxsave_region[512] __attribute__((aligned(16))); struct memory_desc memory_management_struct = {{0}, 0}; @@ -62,17 +62,17 @@ void test_mm() // 初始化系统各模块 void system_initialize() { + // 初始化printk - init_printk(1024, 768, FR_address, 1024 * 768 * 4, 8, 16); - printk("11111\n"); + + init_printk(8, 16); + load_TR(10); // 加载TR寄存器 - while(1); - // 初始化任务状态段表 - ul tss_item_addr = 0xffff800000007c00; + ul tss_item_addr = 0x7c00; set_TSS64(_stack_start, _stack_start, _stack_start, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr); - + // 初始化中断描述符表 init_sys_vector(); @@ -84,6 +84,7 @@ void system_initialize() // 先初始化系统调用模块 syscall_init(); + // 再初始化进程模块。顺序不能调转 process_init(); } @@ -93,7 +94,7 @@ void Start_Kernel(void) { system_initialize(); - + // show_welcome(); // test_mm(); diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index 18da78a1..a744cccd 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -7,7 +7,7 @@ #define PTRS_PER_PGT 512 // 内核层的起始地址 -#define KERNEL_BASE_ADDR ((unsigned long)0xffff800000000000) +#define KERNEL_BASE_ADDR ((unsigned long)0x100000) #define PAGE_4K_SHIFT 12 #define PAGE_2M_SHIFT 21 diff --git a/run.sh b/run.sh index 2ffd8605..9b54c6fb 100644 --- a/run.sh +++ b/run.sh @@ -12,7 +12,7 @@ if [ ! "$1" == "--nobuild" ]; then make clean fi -IA32_USE_QEMU=1 +IA32_USE_QEMU=0 bochsrc="./bochsrc" ARCH="x86_64"