multiboot2 loadng and switching from ia32 to ia32e
This commit is contained in:
commit
12e5817607
|
@ -0,0 +1,5 @@
|
|||
/target
|
||||
/.vscode
|
||||
*.o
|
||||
*.map
|
||||
*.elf
|
|
@ -0,0 +1,36 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 - present Random World Studio
|
||||
|
||||
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 THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
|
||||
==============================================================================
|
||||
|
||||
MIT 开源许可证
|
||||
|
||||
版权所有 (c) 2023 - 现在 Random World Studio
|
||||
|
||||
免费授予获得了本软件及相关文档副本的任何人不受限地使用本软件的权利,此权利包括但不限于:使用、
|
||||
复制、修改、合并、发布、分发、再许可以及销售本软件的副本,同时允许被提供本软件的人也这样做。
|
||||
但使用者需满足以下条件:
|
||||
|
||||
上述版权声明及本许可证应包含于软件的所有副本或主要部分中。
|
||||
|
||||
本软件按原样提供,不提供任何明示或暗示的保证,包括但不限于对适销性、特定用途的适应性和非侵权性
|
||||
的保证。在任何情况下,作者和版权持有人均不对任何损害及索赔承担责任,也不与该软件的使用和交易相关。
|
|
@ -0,0 +1,13 @@
|
|||
.PHONY: all clear run debug
|
||||
|
||||
all:
|
||||
@make -C src all --no-print-directory
|
||||
|
||||
clear:
|
||||
@make -C src clear --no-print-directory
|
||||
|
||||
run:
|
||||
@make -C qemu run --no-print-directory
|
||||
|
||||
debug:
|
||||
@make -C qemu debug --no-print-directory
|
|
@ -0,0 +1,23 @@
|
|||
# Metaverse内核
|
||||
|
||||
基于multiboot2引导的64位内核。
|
||||
|
||||
## 开发计划
|
||||
|
||||
* 重新设置内核分页前的准备:
|
||||
* multiboot2启动信息
|
||||
* 重设显示模式前的内核日志
|
||||
* 显示模式设置
|
||||
* 键盘的连接
|
||||
|
||||
## 文档
|
||||
|
||||
### kernel
|
||||
|
||||
### libk
|
||||
|
||||
## 版权声明
|
||||
|
||||
版权所有 (c) 2023 - 现在 Random World Studio 保留所有权利。
|
||||
|
||||
本软件使用MIT开源许可证进行许可。详细信息请参阅许可证文件。
|
|
@ -0,0 +1,48 @@
|
|||
TARGET = ../src/metaverse.elf
|
||||
|
||||
.PHONY: run debug load mount unmount
|
||||
|
||||
BIOS = bios/OVMF_CODE.fd
|
||||
|
||||
run:
|
||||
@sudo modprobe nbd
|
||||
@make load
|
||||
@qemu-system-x86_64 -m 4G metaverse.img -enable-kvm -bios ${BIOS}
|
||||
|
||||
debug:
|
||||
@sudo modprobe nbd
|
||||
@make load
|
||||
@qemu-system-x86_64 -m 4G metaverse.img -enable-kvm -bios ${BIOS} -s -S
|
||||
|
||||
create:
|
||||
@qemu-img create -f qcow2 metaverse.img 512M
|
||||
@sudo modprobe nbd
|
||||
@sudo qemu-nbd --connect=/dev/nbd0 metaverse.img
|
||||
@sudo partprobe /dev/nbd0
|
||||
@echo "你需要为这个虚拟磁盘写入一个GPT分区表并分出efi分区和根分区。"
|
||||
@sudo fdisk /dev/nbd0
|
||||
@sudo mkfs.fat -F 32 /dev/nbd0p1
|
||||
@sudo mkfs.fat -F 32 /dev/nbd0p2
|
||||
@sudo mount /dev/nbd0p2 mnt/
|
||||
@sudo mount -m /dev/nbd0p1 mnt/boot/
|
||||
@sudo mkdir mnt/boot/EFI/
|
||||
@make unmount
|
||||
|
||||
load:
|
||||
@echo loading kernel ...
|
||||
@make mount
|
||||
@sudo cp ${TARGET} mnt/boot/
|
||||
@make unmount
|
||||
|
||||
mount:
|
||||
@sudo modprobe nbd
|
||||
@sudo qemu-nbd --connect=/dev/nbd0 metaverse.img
|
||||
@sudo partprobe /dev/nbd0
|
||||
@sudo mount /dev/nbd0p2 mnt/
|
||||
@sudo mount /dev/nbd0p1 mnt/boot/
|
||||
|
||||
unmount:
|
||||
@sync
|
||||
@sudo umount /dev/nbd0p1
|
||||
@sudo umount /dev/nbd0p2
|
||||
@sudo qemu-nbd --disconnect /dev/nbd0
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,49 @@
|
|||
ARCH := $(shell uname -m)
|
||||
SOURCE := $(shell pwd)/scripts
|
||||
ifeq (${ARCH},x86_64)
|
||||
ASM = nasm
|
||||
ASMFLAGS = -f elf64
|
||||
endif
|
||||
|
||||
ifdef release
|
||||
release = 1
|
||||
endif
|
||||
|
||||
SUBOBJS = kernel/kernel.o libk/libk.o
|
||||
|
||||
DEFINES = ARCH="${ARCH}" ASM="${ASM}" ASMFLAGS="${ASMFLAGS}" SOURCE="${SOURCE}"
|
||||
ifdef release
|
||||
DEFINES := ${DEFINES} release=1
|
||||
endif
|
||||
|
||||
metaverse.elf: kernel libk metaverse.lds
|
||||
@echo -e "\e[1;33mld\e[0m \e[1;32m$@\e[0m \e[34m<--\e[0m \e[32m${SUBOBJS}\e[0m"
|
||||
@ld -T metaverse.lds -Map=metaverse.map -o $@ ${SUBOBJS} 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
|
||||
|
||||
.PHONY: kernel libk all clear postproc
|
||||
|
||||
all: postproc metaverse.elf
|
||||
|
||||
postproc:
|
||||
@echo -n -e "\e[36m"
|
||||
@if [ "${release}" = "1" ]; then \
|
||||
echo -n -e "[Building on ${ARCH} as release]"; \
|
||||
else \
|
||||
echo -n -e "[Building on ${ARCH}]"; \
|
||||
fi
|
||||
@echo -e "\e[0m"
|
||||
|
||||
kernel:
|
||||
@echo -e "\e[33m__\e[0m \e[1;35m[Building kernel]\e[0m \e[33m____\e[0m"
|
||||
@make -C kernel all --no-print-directory ${DEFINES}
|
||||
@echo -e "\e[33m-------------------------\e[0m"
|
||||
|
||||
libk:
|
||||
@echo -e "\e[33m__\e[0m \e[1;35m[Building libk]\e[0m \e[33m______\e[0m"
|
||||
@make -C libk all --no-print-directory ${DEFINES}
|
||||
@echo -e "\e[33m-------------------------\e[0m"
|
||||
|
||||
clear:
|
||||
@make -C kernel clear --no-print-directory
|
||||
@make -C libk clear --no-print-directory
|
||||
@-rm metaverse.elf metaverse.map
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef SYSCTL_H
|
||||
#define SYSCTL_H 1
|
||||
|
||||
#define __asm_hlt__() __asm__("hlt");
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef KERNEL_H
|
||||
#define KERNEL_H 1
|
||||
|
||||
#include <types.h>
|
||||
#include <asm/sysctl.h>
|
||||
|
||||
#define KERNEL_TODO() \
|
||||
while (true) \
|
||||
{ \
|
||||
}
|
||||
|
||||
#define simple_lock_lock(lock) \
|
||||
{ \
|
||||
while (lock == true) \
|
||||
; \
|
||||
(lock) = true; \
|
||||
}
|
||||
#define simple_lock_unlock(lock) (lock) = false;
|
||||
|
||||
extern void *kend; // 内核结束的标记
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef KLOG_H
|
||||
#define KLOG_H 1
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define KLOG_BUFFER_SIZE 2 * 1024 * 1024
|
||||
|
||||
typedef struct __klogger
|
||||
{
|
||||
usize tty;
|
||||
char buffer[KLOG_BUFFER_SIZE];
|
||||
usize index;
|
||||
} klogger;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef MM_H
|
||||
#define MM_H 1
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define MM_PAGE_TABLE_FLAGS_AREA ((u64)0xfff)
|
||||
|
||||
/* 页对齐掩码 */
|
||||
|
||||
#define MM_4K_ALIGN_MASK ((u64)0xfff)
|
||||
#define MM_2M_ALIGN_MASK ((u64)0x1fffff)
|
||||
#define MM_1G_ALIGN_MASK ((u64)0x3fffffff)
|
||||
|
||||
/* 页表项属性FLAGS */
|
||||
|
||||
#define MM_PML4E_KERNEL_RW_FLAG ((u64)0x3)
|
||||
#define MM_PML4E_KERNEL_RO_FLAG ((u64)0x1)
|
||||
|
||||
#define MM_PDPTE_KERNEL_GLB_BP_RW_FLAG ((u64)0x183)
|
||||
#define MM_PDPTE_KERNEL_GLB_RW_FLAG ((u64)0x103)
|
||||
#define MM_PDPTE_KERNEL_GLB_BP_RO_FLAG ((u64)0x181)
|
||||
#define MM_PDPTE_KERNEL_GLB_RO_FLAG ((u64)0x101)
|
||||
|
||||
#define MM_PDPTE_KERNEL_BP_RW_FLAG ((u64)0x83)
|
||||
#define MM_PDPTE_KERNEL_RW_FLAG ((u64)0x3)
|
||||
#define MM_PDPTE_KERNEL_BP_RO_FLAG ((u64)0x81)
|
||||
#define MM_PDPTE_KERNEL_RO_FLAG ((u64)0x1)
|
||||
|
||||
#define MM_PDTE_KERNEL_GLB_BP_RW_FLAG ((u64)0x183)
|
||||
#define MM_PDTE_KERNEL_RW_FLAG ((u64)0x3)
|
||||
#define MM_PDTE_KERNEL_GLB_BP_RO_FLAG ((u64)0x181)
|
||||
#define MM_PDTE_KERNEL_RO_FLAG ((u64)0x1)
|
||||
|
||||
#define MM_PDTE_KERNEL_BP_RW_FLAG ((u64)0x83)
|
||||
#define MM_PDTE_KERNEL_BP_RO_FLAG ((u64)0x81)
|
||||
|
||||
#define MM_PTE_KERNEL_RW_FLAG ((u64)0x103)
|
||||
#define MM_PTE_KERNEL_RO_FLAG ((u64)0x101)
|
||||
|
||||
/* 页表大小枚举 */
|
||||
enum mm_page_size
|
||||
{
|
||||
MM_PAGE_SIZE_4K = 1,
|
||||
MM_PAGE_SIZE_2M = 512,
|
||||
MM_PAGE_SIZE_1G = 262144,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,117 @@
|
|||
#ifndef TTY_H
|
||||
#define TTY_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef enum __tty_type
|
||||
{
|
||||
invalid,
|
||||
// 用于在内核刚刚被引导,只有bootloader提供的显示功能时使用
|
||||
tty_type_raw_framebuffer,
|
||||
// 用于图形功能初始化后,直接连接图形接口
|
||||
tty_type_display,
|
||||
// 用于图形终端的终端模拟器
|
||||
tty_type_vtty,
|
||||
} tty_type;
|
||||
|
||||
typedef enum __framebuffer_pixel_type
|
||||
{
|
||||
rgb,
|
||||
bgr,
|
||||
} framebuffer_pixel_type;
|
||||
|
||||
// 在不同的tty类型下,提供相应的使用显示功能的信息
|
||||
typedef union __tty_typeinfo
|
||||
{
|
||||
struct __framebuffer
|
||||
{
|
||||
void *pointer;
|
||||
usize width, height;
|
||||
framebuffer_pixel_type pixtype;
|
||||
u8 pixsize;
|
||||
} raw_framebuffer;
|
||||
} tty_typeinfo;
|
||||
|
||||
typedef struct __framebuffer framebuffer;
|
||||
|
||||
// tty模式
|
||||
// 分为文本模式和图形模式
|
||||
// 文本模式中的字符由tty模块渲染
|
||||
typedef enum __tty_mode
|
||||
{
|
||||
tty_mode_text,
|
||||
tty_mode_graphics,
|
||||
} tty_mode;
|
||||
|
||||
typedef struct __tty_text_state
|
||||
{
|
||||
usize line, column;
|
||||
usize width, height;
|
||||
volatile u8 lock;
|
||||
} tty_text_state;
|
||||
|
||||
// tty对象
|
||||
typedef struct __tty
|
||||
{
|
||||
usize id;
|
||||
tty_type type;
|
||||
tty_typeinfo typeinfo;
|
||||
tty_mode mode;
|
||||
tty_text_state text;
|
||||
} tty;
|
||||
|
||||
// tty控制器
|
||||
typedef struct __tty_controller
|
||||
{
|
||||
#define TTY_MAX_NUM 128
|
||||
tty *ttys[TTY_MAX_NUM];
|
||||
bool map[TTY_MAX_NUM];
|
||||
} tty_controller;
|
||||
|
||||
/**
|
||||
* @brief 初始化tty控制器
|
||||
*
|
||||
*/
|
||||
void tty_controller_init();
|
||||
|
||||
/**
|
||||
* @brief 创建tty
|
||||
*
|
||||
* @param __tty 若为nullptr,将使用kmalloc申请内存,需要手动释放
|
||||
* @param type
|
||||
* @return tty* 返回tty对象的地址,如果tty数量超过TTY_MAX_NUM返回nullptr,
|
||||
* 无论传入的__tty是否是nullptr
|
||||
*/
|
||||
tty *tty_new(tty *__tty, tty_type type, tty_mode mode);
|
||||
|
||||
/**
|
||||
* @brief 通过tty id获取一个tty
|
||||
*
|
||||
* @param id
|
||||
* @return tty** 二级指针方便判断这个tty是否删除,返回空指针表示当前没有这个tty
|
||||
*/
|
||||
tty **tty_get(usize id);
|
||||
|
||||
/**
|
||||
* @brief 当type为raw_framebuffer时设置帧缓冲区
|
||||
*
|
||||
* @param ttyx
|
||||
* @param fb
|
||||
*/
|
||||
void tty_set_framebuffer(tty *ttyx, framebuffer *fb);
|
||||
|
||||
/**
|
||||
* @brief 当mode为text时打印ascii文字
|
||||
*
|
||||
* @param ttyx
|
||||
* @param string
|
||||
*/
|
||||
void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor);
|
||||
|
||||
#define gen_color(r, g, b) (((b) << 16) | ((g) << 8) | (r))
|
||||
|
||||
#define TTY_FONT_SCALE 2
|
||||
extern u64 font[256][64];
|
||||
extern usize font_width, font_height;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef MULTIBOOT2_H
|
||||
#define MULTIBOOT2_H 1
|
||||
|
||||
#include <libk/multiboot2/bootinfo.h>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,386 @@
|
|||
#ifndef BOOTINFO_H
|
||||
#define BOOTINFO_H 1
|
||||
|
||||
#include <types.h>
|
||||
#include <utils.h>
|
||||
|
||||
#define BOOTINFO_TAG_REPEAT_MAX 32
|
||||
typedef struct __bootinfo_t
|
||||
{
|
||||
void *start;
|
||||
usize size;
|
||||
usize iter_index;
|
||||
void *map[24][BOOTINFO_TAG_REPEAT_MAX];
|
||||
usize map_counts[24];
|
||||
} bootinfo_t;
|
||||
|
||||
typedef struct __bootinfo_tag
|
||||
{
|
||||
u32 type;
|
||||
u32 size;
|
||||
} DISALIGNED bootinfo_tag_t;
|
||||
|
||||
/** Basic memory information
|
||||
* ‘mem_lower’ and ‘mem_upper’ indicate the amount of lower and upper memory,
|
||||
* respectively, in kilobytes. Lower memory starts at address 0, and upper memory
|
||||
* starts at address 1 megabyte. The maximum possible value for lower memory
|
||||
* is 640 kilobytes. The value returned for upper memory is maximally the address
|
||||
* of the first upper memory hole minus 1 megabyte. It is not guaranteed to be this value.
|
||||
*
|
||||
* This tag may not be provided by some boot loaders on EFI platforms if EFI boot services
|
||||
* are enabled and available for the loaded image (EFI boot services not terminated tag
|
||||
* exists in Multiboot2 information structure).
|
||||
*/
|
||||
typedef struct __bootinfo_basic_memory_info_t
|
||||
{
|
||||
u32 mem_lower;
|
||||
u32 mem_upper;
|
||||
} DISALIGNED bootinfo_basic_memory_info_t;
|
||||
#define bootinfo_basic_memory_info(addr) (bootinfo_basic_memory_info_t *)(addr)
|
||||
#define BOOTINFO_BASIC_MEMORY_INFO_TYPE 4
|
||||
|
||||
/** BIOS Boot device
|
||||
* This tag indicates which BIOS disk device the boot loader loaded the OS image from.
|
||||
* If the OS image was not loaded from a BIOS disk, then this tag must not be present.
|
||||
* The operating system may use this field as a hint for determining its own root device,
|
||||
* but is not required to.
|
||||
*
|
||||
* The ‘biosdev’ contains the BIOS drive number as understood by the BIOS INT 0x13
|
||||
* low-level disk interface: e.g. 0x00 for the first floppy disk or 0x80 for the first hard disk.
|
||||
*
|
||||
* The three remaining bytes specify the boot partition. ‘partition’ specifies the top-level
|
||||
* partition number, ‘sub_partition’ specifies a sub-partition in the top-level partition,
|
||||
* etc. Partition numbers always start from zero. Unused partition bytes must be set to 0xFFFFFFFF.
|
||||
* For example, if the disk is partitioned using a simple one-level DOS partitioning scheme,
|
||||
* then ‘partition’ contains the DOS partition number, and ‘sub_partition’ if 0xFFFFFF.
|
||||
* As another example, if a disk is partitioned first into DOS partitions, and then one of
|
||||
* those DOS partitions is subdivided into several BSD partitions using BSD’s disklabel strategy,
|
||||
* then ‘partition’ contains the DOS partition number and ‘sub_partition’ contains
|
||||
* the BSD sub-partition within that DOS partition.
|
||||
*
|
||||
* DOS extended partitions are indicated as partition numbers starting from 4 and increasing,
|
||||
* rather than as nested sub-partitions, even though the underlying disk layout of
|
||||
* extended partitions is hierarchical in nature. For example, if the boot loader boots from
|
||||
* the second extended partition on a disk partitioned in conventional DOS style, then ‘partition’
|
||||
* will be 5, and ‘sub_partiton’ will be 0xFFFFFFFF.
|
||||
*/
|
||||
typedef struct __bootinfo_bios_boot_device_t
|
||||
{
|
||||
u32 biosdev;
|
||||
u32 partition;
|
||||
u32 sub_partition;
|
||||
} DISALIGNED bootinfo_bios_boot_device_t;
|
||||
#define bootinfo_bios_boot_device(addr) (bootinfo_bios_boot_device_t *)(addr)
|
||||
#define BOOTINFO_BIOS_BOOT_DEVICE_TYPE 5
|
||||
|
||||
/** Boot command line
|
||||
* ‘string’ contains command line. The command line is a normal C-style zero-terminated UTF-8 string.
|
||||
*/
|
||||
typedef struct __bootinfo_boot_command_line_t
|
||||
{
|
||||
u32 size;
|
||||
u8 string[0];
|
||||
} DISALIGNED bootinfo_boot_command_line_t;
|
||||
#define bootinfo_boot_command_line(addr) (bootinfo_boot_command_line_t *)((usize)(addr) - sizeof(u32))
|
||||
#define BOOTINFO_BOOT_COMMAND_LINE_TYPE 1
|
||||
|
||||
/** Modules
|
||||
* This tag indicates to the kernel what boot module was loaded along with the kernel image,
|
||||
* and where it can be found.
|
||||
*
|
||||
* The ‘mod_start’ and ‘mod_end’ contain the start and end physical addresses of the boot module
|
||||
* itself. The ‘string’ field provides an arbitrary string to be associated with that particular
|
||||
* boot module; it is a zero-terminated UTF-8 string, just like the kernel command line.
|
||||
* Typically the string might be a command line (e.g. if the operating system treats boot modules
|
||||
* as executable programs), or a pathname (e.g. if the operating system treats boot modules
|
||||
* as files in a file system), but its exact use is specific to the operating system.
|
||||
*
|
||||
* One tag appears per module. This tag type may appear multiple times.
|
||||
*/
|
||||
typedef struct __bootinfo_modules_t
|
||||
{
|
||||
u32 size;
|
||||
u32 mod_start;
|
||||
u32 mod_end;
|
||||
u8 string[0];
|
||||
} DISALIGNED bootinfo_modules_t;
|
||||
#define bootinfo_modules(addr) (bootinfo_modules_t *)((usize)(addr) - sizeof(u32))
|
||||
#define BOOTINFO_MODULES_TYPE 3
|
||||
|
||||
/** ELF-Symbols
|
||||
* This tag contains section header table from an ELF kernel, the size of each entry, number
|
||||
* of entries, and the string table used as the index of names. They correspond to the
|
||||
* ‘shdr_*’ entries (‘shdr_num’, etc.) in the Executable and Linkable Format (ELF) specification
|
||||
* in the program header. All sections are loaded, and the physical address fields of the
|
||||
* ELF section header then refer to where the sections are in memory (refer to the i386 ELF
|
||||
* documentation for details as to how to read the section header(s)).
|
||||
*/
|
||||
typedef struct __bootinfo_elf_symbols_t
|
||||
{
|
||||
u16 num;
|
||||
u16 entsize;
|
||||
u16 shndx;
|
||||
u16 reserved;
|
||||
u8 section_headers[0];
|
||||
} DISALIGNED bootinfo_elf_symbols_t;
|
||||
#define bootinfo_elf_symbols(addr) (bootinfo_elf_symbols_t *)(addr)
|
||||
#define BOOTINFO_ELF_SYMBOLS_TYPE 9
|
||||
|
||||
/** Memory map
|
||||
* This tag provides memory map.
|
||||
*
|
||||
* ‘entry_size’ contains the size of one entry so that in future new fields may be added to it.
|
||||
* It’s guaranteed to be a multiple of 8. ‘entry_version’ is currently set at ‘0’. Future versions
|
||||
* will increment this field. Future version are guranteed to be backward compatible with
|
||||
* older format. Each entry has the following structure: bootinfo_memory_map_entry.
|
||||
*
|
||||
* ‘size’ contains the size of current entry including this field itself. It may be bigger
|
||||
* than 24 bytes in future versions but is guaranteed to be ‘base_addr’ is the starting
|
||||
* physical address.
|
||||
* ‘length’ is the size of the memory region in bytes.
|
||||
* ‘type’ is the variety of address range represented, where a value of 1 indicates available RAM,
|
||||
* value of 3 indicates usable memory holding ACPI information, value of 4 indicates
|
||||
* reserved memory which needs to be preserved on hibernation, value of 5 indicates a memory
|
||||
* which is occupied by defective RAM modules and all other values currently indicated
|
||||
* a reserved area.
|
||||
* ‘reserved’ is set to ‘0’ by bootloader and must be ignored by the OS image.
|
||||
*
|
||||
* The map provided is guaranteed to list all standard RAM that should be available
|
||||
* for normal use. This type however includes the regions occupied by kernel, mbi, segments
|
||||
* and modules. Kernel must take care not to overwrite these regions.
|
||||
*
|
||||
* This tag may not be provided by some boot loaders on EFI platforms if EFI boot services
|
||||
* are enabled and available for the loaded image (EFI boot services not terminated tag
|
||||
* exists in Multiboot2 information structure).
|
||||
*/
|
||||
typedef struct __bootinfo_memory_map_t
|
||||
{
|
||||
u32 size;
|
||||
u32 entry_size;
|
||||
u32 entry_version;
|
||||
struct bootinfo_memory_map_entry_t
|
||||
{
|
||||
u64 base_addr;
|
||||
u64 length;
|
||||
u32 type;
|
||||
u32 reserved;
|
||||
} DISALIGNED entries[0];
|
||||
} DISALIGNED bootinfo_memory_map_t;
|
||||
#define bootinfo_memory_map(addr) (bootinfo_memory_map_t *)((usize)(addr) - sizeof(u32))
|
||||
#define BOOTINFO_MEMORY_MAP_TYPE 6
|
||||
|
||||
/** Boot loader name
|
||||
* ‘string’ contains the name of a boot loader booting the kernel. The name is a normal
|
||||
* C-style UTF-8 zero-terminated string.
|
||||
*/
|
||||
typedef struct __bootinfo_bootloader_name_t
|
||||
{
|
||||
u32 size;
|
||||
u8 string[0];
|
||||
} DISALIGNED bootinfo_bootloader_name_t;
|
||||
#define bootinfo_bootloader_name(addr) (bootinfo_bootloader_name_t *)((usize)(addr) - sizeof(u32))
|
||||
#define BOOTINFO_BOOTLOADER_NAME_TYPE 2
|
||||
|
||||
/** APM table
|
||||
* The fields ‘version’, ‘cseg’, ‘offset’, ‘cseg_16’, ‘dseg’, ‘flags’, ‘cseg_len’, ‘cseg_16_len’,
|
||||
* ‘dseg_len’ indicate the version number, the protected mode 32-bit code segment, the offset
|
||||
* of the entry point, the protected mode 16-bit code segment, the protected mode 16-bit
|
||||
* data segment, the flags, the length of the protected mode 32-bit code segment, the length of
|
||||
* the protected mode 16-bit code segment, and the length of the protected mode 16-bit data segment,
|
||||
* respectively. Only the field ‘offset’ is 4 bytes, and the others are 2 bytes.
|
||||
* See [Advanced Power Management (APM) BIOS Interface Specification]
|
||||
* (http://www.microsoft.com/hwdev/busbios/amp_12.htm), for more information.
|
||||
*/
|
||||
typedef struct __bootinfo_apm_table_t
|
||||
{
|
||||
u16 version;
|
||||
u16 cseg;
|
||||
u32 offset;
|
||||
u16 cseg_16;
|
||||
u16 dseg;
|
||||
u16 flags;
|
||||
u16 cseg_len;
|
||||
u16 cseg_16_len;
|
||||
u16 dseg_len;
|
||||
} DISALIGNED bootinfo_apm_table_t;
|
||||
#define bootinfo_apm_table(addr) (bootinfo_apm_table_t *)(addr)
|
||||
#define BOOTINFO_APM_TABLE_TYPE 10
|
||||
|
||||
/** VBE info
|
||||
* 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.
|
||||
*
|
||||
* The field ‘vbe_mode’ indicates current video mode in the format specified in VBE 3.0.
|
||||
*
|
||||
* The rest fields ‘vbe_interface_seg’, ‘vbe_interface_off’, and ‘vbe_interface_len’ contain
|
||||
* the table of a protected mode interface defined in VBE 2.0+. If this information is not
|
||||
* available, those fields contain zero. Note that VBE 3.0 defines another protected mode
|
||||
* interface which is incompatible with the old one. If you want to use the new protected mode
|
||||
* interface, you will have to find the table yourself.
|
||||
*/
|
||||
typedef struct __bootinfo_vbe_info_t
|
||||
{
|
||||
u16 vbe_mode;
|
||||
u16 vbe_interface_seg;
|
||||
u16 vbe_interface_off;
|
||||
u16 vbe_interface_len;
|
||||
u8 vbe_control_info[512];
|
||||
u8 vbe_mode_info[256];
|
||||
} DISALIGNED bootinfo_vbe_info_t;
|
||||
#define bootinfo_vbe_info(addr) (bootinfo_vbe_info_t *)(addr)
|
||||
#define BOOTINFO_VBE_INFO_TYPE 7
|
||||
|
||||
/** Framebuffer info
|
||||
* The field ‘framebuffer_addr’ contains framebuffer physical address. This field is 64-bit wide
|
||||
* but bootloader should set it under 4GiB if possible for compatibility with payloads
|
||||
* which aren’t aware of PAE or amd64.
|
||||
* The field ‘framebuffer_pitch’ contains pitch in bytes.
|
||||
* The fields ‘framebuffer_width’, ‘framebuffer_height’ contain framebuffer dimensions in pixels.
|
||||
* The field ‘framebuffer_bpp’ contains number of bits per pixel.
|
||||
* ‘reserved’ always contains 0 in current version of specification and must be ignored by OS image.
|
||||
*/
|
||||
typedef struct __bootinfo_framebuffer_info_t
|
||||
{
|
||||
u32 size;
|
||||
u64 framebuffer_addr;
|
||||
u32 framebuffer_pitch;
|
||||
u32 framebuffer_width;
|
||||
u32 framebuffer_height;
|
||||
u8 framebuffer_bpp;
|
||||
u8 framebuffer_type;
|
||||
u8 color_info[0];
|
||||
} DISALIGNED bootinfo_framebuffer_info_t;
|
||||
#define bootinfo_framebuffer_info(addr) (bootinfo_framebuffer_info_t *)((usize)(addr) - sizeof(u32))
|
||||
#define BOOTINFO_FRAMEBUFFER_INFO_TYPE 8
|
||||
|
||||
/**
|
||||
* If ‘framebuffer_type’ is set to 0 it means indexed color. In this case color_info
|
||||
* is defined as follows:
|
||||
*
|
||||
* ‘framebuffer_palette’ is an array of colour descriptors. Each colour descriptor
|
||||
* has following structure: bootinfo_framebuffer_info_framebuffer_palette_t.
|
||||
*/
|
||||
typedef struct __bootinfo_framebuffer_info_color_info_0_t
|
||||
{
|
||||
u32 framebuffer_palette_num_colors;
|
||||
struct bootinfo_framebuffer_info_framebuffer_palette_t
|
||||
{
|
||||
u8 red, green, blue;
|
||||
} DISALIGNED palettes[0];
|
||||
} DISALIGNED bootinfo_framebuffer_info_color_info_0_t;
|
||||
|
||||
/**
|
||||
* If ‘framebuffer_type’ is set to ‘1’ it means direct RGB color. Then color_type
|
||||
* is defined as follows:
|
||||
*
|
||||
* If ‘framebuffer_type’ is set to ‘2’ it means EGA text. In this case ‘framebuffer_width’
|
||||
* and ‘framebuffer_height’ are expressed in characters and not in pixels.
|
||||
* ‘framebuffer_bpp’ is equal 16 (16 bits per character) and ‘framebuffer_pitch’ is expressed
|
||||
* in bytes per text line. All further values of ‘framebuffer_type’ are reserved for
|
||||
* future expansion.
|
||||
*/
|
||||
typedef struct __bootinfo_framebuffer_info_color_info_1_2_t
|
||||
{
|
||||
u8 framebuffer_red_field_position;
|
||||
u8 framebuffer_red_mask_size;
|
||||
u8 framebuffer_green_field_position;
|
||||
u8 framebuffer_green_mask_size;
|
||||
u8 framebuffer_blue_field_position;
|
||||
u8 framebuffer_blue_mask_size;
|
||||
} DISALIGNED bootinfo_framebuffer_info_color_info_1_2_t;
|
||||
|
||||
/** EFI 64-bit system table pointer
|
||||
* This tag contains pointer to amd64 EFI system table.
|
||||
*/
|
||||
typedef struct __bootinfo_efi_system_table_pointer_t
|
||||
{
|
||||
u64 pointer;
|
||||
} DISALIGNED bootinfo_efi_system_table_pointer_t;
|
||||
#define bootinfo_efi_system_table_pointer(addr) (bootinfo_efi_system_table_pointer_t *)(addr)
|
||||
#define BOOTINFO_EFI_SYSTEM_TABLE_POINTER_TYPE 12
|
||||
|
||||
/** ACPI v2 RSDP
|
||||
* This tag contains a copy of RSDP as defined per ACPI 2.0 or later specification.
|
||||
*/
|
||||
typedef struct __bootinfo_acpi_rsdp_t
|
||||
{
|
||||
u32 size;
|
||||
u8 acpi_data[0];
|
||||
} DISALIGNED bootinfo_acpi_rsdp_t;
|
||||
#define bootinfo_acpi_rsdp(addr) (bootinfo_acpi_rsdp_t *)((usize)(addr) - sizeof(u32))
|
||||
#define BOOTINFO_ACPI_RSDP_TYPE 15
|
||||
|
||||
/** Networking information
|
||||
* This tag contains network information in the format specified as DHCP. It may be either
|
||||
* a real DHCP reply or just the configuration info in the same format.
|
||||
* This tag appears once per card.
|
||||
*/
|
||||
typedef struct __bootinfo_networking_info_t
|
||||
{
|
||||
u32 size;
|
||||
u8 dhcp_ack[0];
|
||||
} DISALIGNED bootinfo_networking_info_t;
|
||||
#define bootinfo_networking_info(addr) (bootinfo_networking_info_t *)((usize)(addr) - sizeof(u32))
|
||||
#define BOOTINFO_NETWORKING_INFO_TYPE 16
|
||||
|
||||
/** EFI memory map
|
||||
* This tag contains EFI memory map as per EFI specification.
|
||||
*
|
||||
* This tag may not be provided by some boot loaders on EFI platforms if EFI boot services
|
||||
* are enabled and available for the loaded image (EFI boot services not terminated tag
|
||||
* exists in Multiboot2 information structure).
|
||||
*/
|
||||
typedef struct __bootinfo_efi_memory_map_t
|
||||
{
|
||||
u32 discriptor_size;
|
||||
u32 discriptor_version;
|
||||
u8 efi_memory_map[0];
|
||||
} DISALIGNED bootinfo_efi_memory_map_t;
|
||||
#define bootinfo_efi_memory_map(addr) (bootinfo_efi_memory_map_t *)(addr)
|
||||
#define BOOTINFO_EFI_MEMORY_MAP_TYPE 17
|
||||
|
||||
/** EFI boot services not terminated
|
||||
* This tag indicates ExitBootServices wasn’t called.
|
||||
*/
|
||||
#define BOOTINFO_EFI_BOOTSERVICE_NOT_TERMINATED_TYPE 18
|
||||
|
||||
/** EFI 64-bit image handle pointer
|
||||
* This tag contains pointer to EFI amd64 image handle. Usually it is boot loader image handle.
|
||||
*/
|
||||
typedef struct __bootinfo_efi_image_handle_pointer_t
|
||||
{
|
||||
u64 pointer;
|
||||
} DISALIGNED bootinfo_efi_image_handle_pointer_t;
|
||||
#define bootinfo_efi_image_handle_pointer(addr) (bootinfo_efi_image_handle_pointer_t *)(addr)
|
||||
#define BOOTINFO_EFI_IMAGE_HANDLE_POINTER_TYPE 20
|
||||
|
||||
/** Image load base physical address
|
||||
* This tag contains image load base physical address. It is provided only if image has
|
||||
* relocatable header tag.
|
||||
*/
|
||||
typedef struct __bootinfo_image_load_base_address_t
|
||||
{
|
||||
u32 load_base_addr;
|
||||
} DISALIGNED bootinfo_image_load_base_address_t;
|
||||
#define bootinfo_image_load_base_address(addr) (bootinfo_image_load_base_address_t *)(addr)
|
||||
#define BOOTINFO_IMAGE_LOAD_BASE_ADDRESS_TYPE 21
|
||||
|
||||
/**
|
||||
* @brief 初始化bootinfo结构
|
||||
*
|
||||
* @param bootinfo
|
||||
* @param bootinfo_addr
|
||||
*/
|
||||
void bootinfo_new(bootinfo_t *bootinfo, void *bootinfo_addr);
|
||||
|
||||
/**
|
||||
* @brief 获取bootinfo中的tag
|
||||
*
|
||||
* @param bootinfo
|
||||
* @param type
|
||||
* @param tags 返回的tag的指针数组
|
||||
* @return usize tag的总数
|
||||
*/
|
||||
usize bootinfo_get_tag(bootinfo_t *bootinfo, usize type, void ***tags);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef STRING_H
|
||||
#define STRING_H 1
|
||||
|
||||
#include <types.h>
|
||||
|
||||
extern void memset(void *__dest, u8 __src, usize len);
|
||||
extern void memcpy(void *__dest, void *__src, usize len);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef TYPES_H
|
||||
#define TYPES_H 1
|
||||
|
||||
typedef char i8;
|
||||
typedef short i16;
|
||||
typedef int i32;
|
||||
typedef long long i64;
|
||||
typedef i64 isize;
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
typedef u64 usize;
|
||||
|
||||
typedef u8 bool;
|
||||
|
||||
#define false (0)
|
||||
// 判断相等时不能使用true
|
||||
#define true (!false)
|
||||
|
||||
#define nullptr ((void *)0)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef UTILS_H
|
||||
#define UTILS_H 1
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define UTILS_BIT_GET(byte, bit) ((byte) & (1 << (bit)))
|
||||
#define UTILS_BIT_SET(byte, bit) ((byte) |= (1 << (bit)));
|
||||
#define UTILS_BIT_RESET(byte, bit) ((byte) &= ~(1 << (bit)));
|
||||
|
||||
#define UTILS_BITMAP_GET(map, bit) (((u8 *)(map))[bit / 8] & (1 << ((bit) % 8)))
|
||||
#define UTILS_BITMAP_SET(map, bit) (((u8 *)(map))[bit / 8] |= (1 << ((bit) % 8)));
|
||||
#define UTILS_BITMAP_RESET(map, bit) (((u8 *)(map))[bit / 8] &= ~(1 << ((bit) % 8)));
|
||||
|
||||
#define DISALIGNED __attribute__((packed))
|
||||
|
||||
#endif
|
|
@ -0,0 +1,76 @@
|
|||
################################
|
||||
# C语言环境变量
|
||||
|
||||
CC = gcc
|
||||
CCFLAGS = -m64 -mcmodel=large -I ../include \
|
||||
-fno-stack-protector -fno-exceptions \
|
||||
-fno-builtin -nostdinc -nostdlib
|
||||
ifdef release
|
||||
CCFLAGS := ${CCFLAGS} -O2
|
||||
endif
|
||||
|
||||
C_SRCS = main.c tty.c klog.c font.c
|
||||
C_OBJS = ${C_SRCS:.c=.o}
|
||||
|
||||
################################
|
||||
|
||||
################################
|
||||
# rust语音环境变量
|
||||
|
||||
RSCFLAGS = --emit=obj --target x86_64-unknown-linux-gnu --crate-type=bin
|
||||
|
||||
RS_OBJS =
|
||||
|
||||
################################
|
||||
|
||||
################################
|
||||
# 汇编语言环境变量
|
||||
|
||||
ifndef ASM
|
||||
ASM = as
|
||||
endif
|
||||
|
||||
ASMFLAGS := ${ASMFLAGS}
|
||||
ASMFLAGS32 = -f elf32
|
||||
|
||||
S_OBJS = entry32.32.o entry.o
|
||||
|
||||
################################
|
||||
|
||||
OBJS = ${S_OBJS} ${C_OBJS} ${RS_OBJS}
|
||||
|
||||
STRIP_SECS = -R .comment -R .note.GNU-stack
|
||||
|
||||
OBJCOPY_FLAGS = ${STRIP_SECS}
|
||||
|
||||
# 子目录
|
||||
VPATH = mm/ tty/ klog/
|
||||
|
||||
%.o: %.c
|
||||
@echo -e "\e[1m\e[33m${CC}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||
@${CC} -c ${CCFLAGS} $< -o $@
|
||||
|
||||
%.o: %.rs
|
||||
@echo -e "\e[1m\e[33mrustc\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||
@rustc ${RSCFLAGS} $< -o $@
|
||||
|
||||
%.32.o: arch/${ARCH}/%.s
|
||||
@echo -e "\e[1m\e[33m${ASM}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||
@${ASM} ${ASMFLAGS32} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red"
|
||||
@objcopy -I elf32-i386 -O elf64-x86-64 $@ $@ 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "objcopy=lyellow"
|
||||
|
||||
%.o: arch/${ARCH}/%.s
|
||||
@echo -e "\e[1m\e[33m${ASM}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||
@${ASM} ${ASMFLAGS} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red"
|
||||
|
||||
kernel.o: ${OBJS}
|
||||
@echo -e "\e[1m\e[33mld\e[0m \e[1m\e[32mkernel.o\e[0m \e[34m<--\e[0m \e[32m${OBJS}\e[0m"
|
||||
@ld -r ${OBJS} -o kernel.o -Map=kernel.map -unresolved-symbols=ignore-all 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
|
||||
@objcopy ${OBJCOPY_FLAGS} kernel.o kernel.o
|
||||
|
||||
.PHONY: all clear
|
||||
|
||||
all: kernel.o
|
||||
|
||||
clear:
|
||||
@-rm ${OBJS} kernel.o kernel.map
|
|
@ -0,0 +1,47 @@
|
|||
section .entry align=8
|
||||
extern kmain
|
||||
global init64
|
||||
init64:
|
||||
endbr64
|
||||
cli
|
||||
jmp $
|
||||
mov rax, 0x1000000
|
||||
mov rbp, rax
|
||||
mov rsp, rax
|
||||
mov rdi, rbx
|
||||
jmp qword kmain
|
||||
|
||||
section .multiboot2 align=8
|
||||
MULTIBOOT2_HEADER_MAGIC equ 0xe85250d6
|
||||
MULTIBOOT2_HEADER_LENGTH equ multiboot2_header_end - multiboot2_header
|
||||
multiboot2_header:
|
||||
dd MULTIBOOT2_HEADER_MAGIC
|
||||
dd 0
|
||||
dd MULTIBOOT2_HEADER_LENGTH
|
||||
dd - (MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_HEADER_LENGTH)
|
||||
bootinfo_request_tag:
|
||||
dd 1
|
||||
dd bootinfo_request_tag_end - bootinfo_request_tag
|
||||
dd 4 ; basic mamory info
|
||||
dd 1 ; boot command line
|
||||
dd 3 ; muldules
|
||||
dd 6 ; memory map
|
||||
dd 8 ; framebuffer info
|
||||
dd 12 ; efi64 system table pointer
|
||||
bootinfo_request_tag_end:
|
||||
end_tag:
|
||||
dd 0
|
||||
dd 8
|
||||
multiboot2_header_end:
|
||||
|
||||
section .bss
|
||||
kstack:
|
||||
; TODO 奇怪的问题,在这写0x1000000 - 0x400000,.bss段会超出0x47f,
|
||||
; 写0x1000000 - 0x400000 - 0x47f,.bss段会超出0x1f
|
||||
; 明明在链接脚本里.bss段的起始地址是0x400000
|
||||
resb 0x1000000 - 0x400000 - 0x47f - 0x1f
|
||||
|
||||
section .kend
|
||||
global kend
|
||||
kend:
|
||||
db 0
|
|
@ -0,0 +1,109 @@
|
|||
section .entry
|
||||
extern init64
|
||||
; 寄存器ebx是multiboot2 information,不可以使用
|
||||
init32:
|
||||
cli
|
||||
|
||||
; 设置PML4的第0项
|
||||
mov eax, 0x102000
|
||||
add eax, 0x003
|
||||
mov edi, 0x101000
|
||||
mov dword [edi], eax
|
||||
add edi, 4
|
||||
mov dword [edi], 0
|
||||
|
||||
; 设置PDPT的第0项
|
||||
mov eax, 0x103000
|
||||
add eax, 0x003
|
||||
mov edi, 0x102000
|
||||
mov dword [edi], eax
|
||||
add edi, 4
|
||||
mov dword [edi], 0
|
||||
|
||||
; 设置PD0中的PDE
|
||||
mov ecx, 64
|
||||
mov eax, 0
|
||||
mov edi, 0x103000
|
||||
init32_loop0:
|
||||
mov edx, eax
|
||||
add edx, 0x183
|
||||
mov dword [edi], edx
|
||||
add eax, 0x400000 ; 2MB
|
||||
add edi, 4
|
||||
mov dword [edi], 0
|
||||
add edi, 4
|
||||
loop init32_loop0
|
||||
|
||||
; 加载GDTR和段寄存器
|
||||
db 0x66
|
||||
lgdt [0x104028]
|
||||
jmp after_lgdt
|
||||
after_lgdt:
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
; mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
; 打开PAE
|
||||
mov eax, cr4
|
||||
bts eax, 5
|
||||
mov cr4, eax
|
||||
|
||||
; 加载cr3
|
||||
mov eax, 0x101000
|
||||
mov cr3, eax
|
||||
|
||||
; 切换ia32e模式
|
||||
mov ecx, 0xc0000080 ; ia32_efer在msr中的地址
|
||||
rdmsr
|
||||
bts eax, 8
|
||||
wrmsr
|
||||
|
||||
; 打开分页机制
|
||||
mov eax, cr0
|
||||
bts eax, 31
|
||||
mov cr0, eax
|
||||
|
||||
; 远跳转
|
||||
jmp 0x8:init64
|
||||
|
||||
section .cpumeta align=4096
|
||||
|
||||
; 分页
|
||||
; 链接器会把这些数据替换掉所以要在代码中重新设置
|
||||
PML4:
|
||||
dq 0x003 + PDPT0
|
||||
resq 511
|
||||
|
||||
PDPT0:
|
||||
dq 0x003 + PD0
|
||||
resq 511
|
||||
|
||||
PD0:
|
||||
resq 512
|
||||
|
||||
; 分段
|
||||
gdt:
|
||||
dq 0
|
||||
dq 0x0020980000000000 ; 内核态代码段
|
||||
dq 0x0000920000000000 ; 内核态数据段
|
||||
dq 0x0020f80000000000 ; 用户态代码段
|
||||
dq 0x0000f20000000000 ; 用户态数据段
|
||||
gdt_end:
|
||||
|
||||
gdt_ptr:
|
||||
dw gdt_end - gdt - 1
|
||||
dq gdt
|
||||
|
||||
; 临时的32位分段
|
||||
gdt32:
|
||||
dq 0
|
||||
dq 0x00cf9a000000ffff
|
||||
dq 0x00cf92000000ffff
|
||||
gdt32_end:
|
||||
|
||||
gdt32_ptr:
|
||||
dw gdt32_end - gdt32_end - 1
|
||||
dd gdt32
|
|
@ -0,0 +1,37 @@
|
|||
#include <kernel/kernel.h>
|
||||
#include <kernel/tty.h>
|
||||
|
||||
#include <libk/multiboot2.h>
|
||||
|
||||
// 通过bootinfo获取临时的帧缓冲区信息
|
||||
void get_frame_buffer_with_bootinfo(framebuffer *fb, bootinfo_t *bootinfo);
|
||||
|
||||
void kmain(void *mb2_bootinfo)
|
||||
{
|
||||
bootinfo_t bootinfo;
|
||||
bootinfo_new(&bootinfo, mb2_bootinfo);
|
||||
|
||||
tty_controller_init();
|
||||
|
||||
framebuffer fb;
|
||||
get_frame_buffer_with_bootinfo(&fb, &bootinfo);
|
||||
tty tty0;
|
||||
tty_new(&tty0, tty_type_raw_framebuffer, tty_mode_text);
|
||||
tty_set_framebuffer(&tty0, &fb);
|
||||
|
||||
tty_text_print(&tty0, "Hello Metaverse!\n", gen_color(0xbb, 0xbb, 0xbb), gen_color(0, 0, 0));
|
||||
|
||||
while (true)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void get_frame_buffer_with_bootinfo(framebuffer *fb, bootinfo_t *bootinfo)
|
||||
{
|
||||
void **tags;
|
||||
usize tags_amount;
|
||||
if ((tags_amount = bootinfo_get_tag(bootinfo, BOOTINFO_FRAMEBUFFER_INFO_TYPE, &tags)) == 0)
|
||||
{
|
||||
KERNEL_TODO();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,207 @@
|
|||
#include <kernel/kernel.h>
|
||||
#include <kernel/tty.h>
|
||||
#include <libk/string.h>
|
||||
|
||||
tty_controller tty_ctrler;
|
||||
|
||||
void tty_controller_init()
|
||||
{
|
||||
memset(tty_ctrler.ttys, 0, sizeof(tty_ctrler.ttys));
|
||||
memset(tty_ctrler.map, 0, sizeof(tty_ctrler.map));
|
||||
}
|
||||
|
||||
tty *tty_new(tty *__tty, tty_type type, tty_mode mode)
|
||||
{
|
||||
if (__tty == nullptr)
|
||||
{ // TODO 实现内存管理功能后实现
|
||||
KERNEL_TODO();
|
||||
}
|
||||
memset(__tty, 0, sizeof(tty));
|
||||
__tty->type = type;
|
||||
__tty->mode = mode;
|
||||
tty *res = nullptr;
|
||||
for (usize i = 0; i < TTY_MAX_NUM; ++i)
|
||||
{
|
||||
if (tty_ctrler.map[i] == false)
|
||||
{
|
||||
res = __tty;
|
||||
__tty->id = i;
|
||||
tty_ctrler.ttys[i] = __tty;
|
||||
tty_ctrler.map[i] = true;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
tty **tty_get(usize id)
|
||||
{
|
||||
if (tty_ctrler.map[id] == false)
|
||||
return nullptr;
|
||||
return &tty_ctrler.ttys[id];
|
||||
}
|
||||
|
||||
void tty_set_framebuffer(tty *ttyx, framebuffer *fb)
|
||||
{
|
||||
if (ttyx->type != tty_type_raw_framebuffer)
|
||||
return;
|
||||
memcpy(&ttyx->typeinfo.raw_framebuffer, fb, sizeof(framebuffer));
|
||||
if (ttyx->mode == tty_mode_text)
|
||||
{
|
||||
ttyx->text.width = fb->width / font_width;
|
||||
ttyx->text.height = fb->height / font_height;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void put_pixel(
|
||||
void *buffer, usize width, usize pixsize,
|
||||
usize x, usize y, u32 pix)
|
||||
{
|
||||
*(u32 *)(buffer + y * width * pixsize + x * pixsize) = pix;
|
||||
}
|
||||
|
||||
inline static void scroll_buffer(
|
||||
void *buffer, usize width, usize height, usize pixsize,
|
||||
usize dist)
|
||||
{
|
||||
memcpy(buffer, buffer + width * pixsize * dist, (height - dist) * width * pixsize);
|
||||
}
|
||||
|
||||
inline static void putchar(
|
||||
tty *ttyx, char c, u32 color, u32 bgcolor)
|
||||
{
|
||||
for (usize j = 0; j < font_height; ++j)
|
||||
{
|
||||
for (usize i = 0; i < font_width; ++i)
|
||||
{
|
||||
bool p = font[c][j] & (1 << (font_width - 1 - i));
|
||||
if (p != false)
|
||||
{
|
||||
for (usize a = 0; a < TTY_FONT_SCALE; ++a)
|
||||
{
|
||||
for (usize b = 0; b < TTY_FONT_SCALE; ++b)
|
||||
{
|
||||
put_pixel(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
ttyx->text.column * font_width * TTY_FONT_SCALE + i * TTY_FONT_SCALE + a,
|
||||
ttyx->text.line * font_height * TTY_FONT_SCALE + j * TTY_FONT_SCALE + b,
|
||||
color);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (usize a = 0; a < TTY_FONT_SCALE; ++a)
|
||||
{
|
||||
for (usize b = 0; b < TTY_FONT_SCALE; ++b)
|
||||
{
|
||||
put_pixel(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
ttyx->text.column * font_width * TTY_FONT_SCALE + i * TTY_FONT_SCALE + a,
|
||||
ttyx->text.line * font_height * TTY_FONT_SCALE + j * TTY_FONT_SCALE + b,
|
||||
bgcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline static void newline(tty *ttyx)
|
||||
{
|
||||
ttyx->text.column = 0;
|
||||
ttyx->text.line++;
|
||||
if (ttyx->text.line == ttyx->text.height)
|
||||
{
|
||||
scroll_buffer(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.height,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
font_height * TTY_FONT_SCALE);
|
||||
ttyx->text.line--;
|
||||
}
|
||||
}
|
||||
|
||||
void tty_text_print(tty *ttyx, char *restrict string, u32 color, u32 bgcolor)
|
||||
{
|
||||
if (ttyx->mode != tty_mode_text)
|
||||
return;
|
||||
if (ttyx->typeinfo.raw_framebuffer.pixtype == bgr)
|
||||
{ // bgr格式要把三个颜色的顺序倒过来
|
||||
u32 t = color;
|
||||
color = 0;
|
||||
i32 n = 3;
|
||||
while (n-- != 0)
|
||||
{
|
||||
color <<= 8;
|
||||
color += t & 0xff;
|
||||
t >>= 8;
|
||||
}
|
||||
}
|
||||
simple_lock_lock(ttyx->text.lock);
|
||||
while (*string != '\0')
|
||||
{
|
||||
char c = *string;
|
||||
if (c == '\n')
|
||||
{ // 换行
|
||||
newline(ttyx);
|
||||
continue;
|
||||
}
|
||||
else if (c == '\t')
|
||||
{ // 水平制表符
|
||||
ttyx->text.column += 8;
|
||||
ttyx->text.column -= ttyx->text.column % 8;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\r')
|
||||
{ // 回到行首
|
||||
ttyx->text.column = 0;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\v')
|
||||
{ // 垂直制表符
|
||||
ttyx->text.line++;
|
||||
if (ttyx->text.line == ttyx->text.height)
|
||||
{
|
||||
scroll_buffer(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.height,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
font_height * TTY_FONT_SCALE);
|
||||
ttyx->text.line--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (c == '\b')
|
||||
{ // 退格
|
||||
putchar(ttyx, ' ', 0, 0);
|
||||
ttyx->text.column--;
|
||||
if (ttyx->text.column < 0)
|
||||
ttyx->text.column = 0;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\f')
|
||||
{ // 滚动一行
|
||||
scroll_buffer(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.height,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
font_height * TTY_FONT_SCALE);
|
||||
continue;
|
||||
}
|
||||
// 打印字符c
|
||||
if (*(string + 1) != '\0' && ttyx->text.column + 1 == ttyx->text.width)
|
||||
{
|
||||
putchar(ttyx, '\n', color / 4 * 3, bgcolor / 4 * 3);
|
||||
newline(ttyx);
|
||||
}
|
||||
putchar(ttyx, c, color, bgcolor);
|
||||
ttyx->text.column++;
|
||||
++string;
|
||||
}
|
||||
if (ttyx->text.column == ttyx->text.width)
|
||||
newline(ttyx);
|
||||
putchar(ttyx, '\0', gen_color(0x88, 0x88, 0x88), 0);
|
||||
simple_lock_unlock(ttyx->text.lock);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
ARCH := $(shell uname -m)
|
||||
ifdef release
|
||||
release = 1
|
||||
endif
|
||||
|
||||
################################
|
||||
# C语言环境变量
|
||||
|
||||
CC = gcc
|
||||
CCFLAGS = -m64 -mcmodel=large -I ../include -fno-stack-protector -fno-exceptions -fno-builtin -nostdinc -nostdlib
|
||||
ifdef release
|
||||
CCFLAGS := ${CCFLAGS} -O2
|
||||
endif
|
||||
|
||||
C_OBJS = bootinfo.o
|
||||
|
||||
################################
|
||||
|
||||
################################
|
||||
# rust语音环境变量
|
||||
|
||||
RSCFLAGS = --emit=obj --target x86_64-unknown-linux-gnu --crate-type=bin
|
||||
|
||||
RS_OBJS =
|
||||
|
||||
################################
|
||||
|
||||
################################
|
||||
# 汇编语言环境变量
|
||||
|
||||
ifndef ASM
|
||||
ASM = as
|
||||
endif
|
||||
|
||||
ASMFLAGS := ${ASMFLAGS}
|
||||
|
||||
S_OBJS = memset.o memcpy.o
|
||||
|
||||
################################
|
||||
|
||||
OBJS = ${S_OBJS} ${C_OBJS} ${RS_OBJS}
|
||||
|
||||
STRIP_SECS = -R .comment -R .note.GNU-stack
|
||||
|
||||
OBJCOPY_FLAGS = ${STRIP_SECS}
|
||||
|
||||
# 子目录
|
||||
VPATH = multiboot2/ string/
|
||||
|
||||
%.o: %.c
|
||||
@echo -e "\e[1m\e[33m${CC}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||
@${CC} -c ${CCFLAGS} $< -o $@
|
||||
|
||||
%.o: %.rs
|
||||
@echo -e "\e[1m\e[33mrustc\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||
@rustc ${RSCFLAGS} $< -o $@
|
||||
|
||||
%.o: arch/${ARCH}/%.s
|
||||
@echo -e "\e[1m\e[33m${ASM}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||
@${ASM} ${ASMFLAGS} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red"
|
||||
|
||||
libk.o: ${OBJS}
|
||||
@echo -e "\e[1m\e[33mld\e[0m \e[1m\e[32mlibk.o\e[0m \e[34m<--\e[0m \e[32m${OBJS}\e[0m"
|
||||
@ld -r ${OBJS} -o libk.o -Map=libk.map 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
|
||||
@objcopy ${OBJCOPY_FLAGS} libk.o libk.o
|
||||
|
||||
.PHONY: all postproc postproc_x86_64
|
||||
|
||||
all: postproc libk.o
|
||||
|
||||
postproc: postproc_${ARCH}
|
||||
|
||||
postproc_x86_64:
|
||||
$(eval ASM = nasm)
|
||||
$(eval ASMFLAGS = -f elf64)
|
||||
|
||||
clear:
|
||||
@-rm ${OBJS} libk.o libk.map
|
|
@ -0,0 +1,52 @@
|
|||
#include <libk/multiboot2.h>
|
||||
#include <libk/string.h>
|
||||
|
||||
typedef struct __bootinfo_next_result_t
|
||||
{
|
||||
u32 type;
|
||||
void *addr;
|
||||
} bootinfo_next_result_t;
|
||||
|
||||
void bootinfo_next(bootinfo_t *bootinfo, bootinfo_next_result_t *result)
|
||||
{
|
||||
if (bootinfo->iter_index >= bootinfo->size)
|
||||
{
|
||||
result->type = 0;
|
||||
result->addr = nullptr;
|
||||
}
|
||||
bootinfo_tag_t *tag = bootinfo->start + bootinfo->iter_index;
|
||||
result->type = tag->type;
|
||||
result->addr = bootinfo->start + bootinfo->iter_index + sizeof(bootinfo_tag_t);
|
||||
bootinfo->iter_index += tag->size;
|
||||
if (bootinfo->iter_index % 8)
|
||||
{
|
||||
bootinfo->iter_index = (bootinfo->iter_index / 8 + 1) * 8;
|
||||
}
|
||||
}
|
||||
|
||||
void bootinfo_new(bootinfo_t *bootinfo, void *bootinfo_addr)
|
||||
{
|
||||
bootinfo->start = bootinfo_addr;
|
||||
bootinfo->size = *((u32 *)bootinfo_addr);
|
||||
bootinfo->iter_index = 8; // 跳过bootinfo头
|
||||
bootinfo_next_result_t res;
|
||||
memset(bootinfo->map, 0, sizeof(bootinfo->map));
|
||||
memset(bootinfo->map_counts, 0, sizeof(bootinfo->map_counts));
|
||||
while ((bootinfo_next(bootinfo, &res), res.type))
|
||||
{
|
||||
if (res.type == BOOTINFO_EFI_BOOTSERVICE_NOT_TERMINATED_TYPE)
|
||||
{
|
||||
bootinfo->map_counts[res.type] = true;
|
||||
}
|
||||
else if (res.addr && bootinfo->map_counts[res.type] < 16)
|
||||
{ // 同类型tag数量只能16个以内
|
||||
bootinfo->map[res.type][bootinfo->map_counts[res.type]++] = res.addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usize bootinfo_get_tag(bootinfo_t *bootinfo, usize type, void ***tags)
|
||||
{
|
||||
*tags = bootinfo->map[type];
|
||||
return bootinfo->map_counts[type];
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
section .text
|
||||
|
||||
global memcpy
|
||||
; void memcpy(void *__dest, restrict void *__src, usize len)
|
||||
memcpy:
|
||||
endbr64
|
||||
sub rsp, 8
|
||||
mov [rsp], rcx
|
||||
|
||||
cld
|
||||
mov rcx, rdx
|
||||
rep movsb
|
||||
|
||||
mov rcx, [rsp]
|
||||
add rsp, 8
|
||||
|
||||
ret
|
|
@ -0,0 +1,21 @@
|
|||
section .text
|
||||
|
||||
global memset
|
||||
; void memset(void *__dest, u8 __src, usize len)
|
||||
memset:
|
||||
endbr64
|
||||
|
||||
sub rsp, 0x10
|
||||
mov [rsp], rax
|
||||
mov [rsp + 8], rcx
|
||||
|
||||
cld
|
||||
mov rax, rsi
|
||||
mov rcx, rdx
|
||||
rep stosb
|
||||
|
||||
mov rax, [rsp]
|
||||
mov rcx, [rsp + 8]
|
||||
add rsp, 0x10
|
||||
|
||||
ret
|
|
@ -0,0 +1,66 @@
|
|||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
ENTRY(init32)
|
||||
|
||||
SECTIONS {
|
||||
. = 1M;
|
||||
.entry :
|
||||
{
|
||||
init32 = .;
|
||||
*(.entry)
|
||||
}
|
||||
.multiboot2 :
|
||||
{
|
||||
*(.multiboot2)
|
||||
}
|
||||
.cpumeta :
|
||||
{
|
||||
*(.cpumeta)
|
||||
}
|
||||
. = 4M;
|
||||
.bss :
|
||||
{
|
||||
kstack = .;
|
||||
*(.bss)
|
||||
}
|
||||
. = 16M;
|
||||
.text :
|
||||
{
|
||||
kmain = .;
|
||||
*(.text)
|
||||
}
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
.bss :
|
||||
{
|
||||
*(.bss)
|
||||
}
|
||||
.eh_frame :
|
||||
{
|
||||
*(.eh_frame)
|
||||
}
|
||||
.got :
|
||||
{
|
||||
*(.got)
|
||||
}
|
||||
.got.plt :
|
||||
{
|
||||
*(.got.plt)
|
||||
}
|
||||
.iplt :
|
||||
{}
|
||||
.rela.dyn :
|
||||
{}
|
||||
.igot.plt :
|
||||
{}
|
||||
.kend :
|
||||
{
|
||||
*(.kend)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
|
||||
argv = sys.argv[1:]
|
||||
|
||||
color = {
|
||||
'black': '\033[30m',
|
||||
'red': '\033[31m',
|
||||
'green': '\033[32m',
|
||||
'yellow': '\033[33m',
|
||||
'blue': '\033[34m',
|
||||
'pink': '\033[35m',
|
||||
'cyan': '\033[36m',
|
||||
'white': '\033[37m',
|
||||
'lblack': '\033[1;30m',
|
||||
'lred': '\033[1;31m',
|
||||
'lgreen': '\033[1;32m',
|
||||
'lyellow': '\033[1;33m',
|
||||
'lblue': '\033[1;34m',
|
||||
'lpink': '\033[1;35m',
|
||||
'lcyan': '\033[1;36m',
|
||||
'lwhite': '\033[1;37m',
|
||||
}
|
||||
|
||||
replace = []
|
||||
|
||||
for arg in argv:
|
||||
aarg = arg.split("=")
|
||||
first = aarg[0]
|
||||
second = aarg[1]
|
||||
if color.get(second) == None:
|
||||
print(f"There is no color '{second}'.")
|
||||
exit(0)
|
||||
second = color[second]
|
||||
replace.append((first, second))
|
||||
|
||||
for line in sys.stdin:
|
||||
if line.strip() == '':
|
||||
break
|
||||
line = line.strip()
|
||||
for s in replace:
|
||||
start = 0
|
||||
while start < len(line):
|
||||
for i in range(start, len(line) - len(s[0])):
|
||||
ok = True
|
||||
for j in range(len(s[0])):
|
||||
if line[i+j] != s[0][j]:
|
||||
ok = False
|
||||
break
|
||||
if ok:
|
||||
line = line[:i+j+1] + "\033[0m" + line[i+j+1:]
|
||||
line = line[:i] + s[1] + line[i:]
|
||||
start = i + j + len(s[1]) + len("\033[0m")
|
||||
break
|
||||
if not ok:
|
||||
break
|
||||
print(line)
|
Reference in New Issue