multiboot2 loadng and switching from ia32 to ia32e

This commit is contained in:
pointer-to-bios 2023-12-03 17:08:00 +08:00
commit 12e5817607
41 changed files with 3473 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/target
/.vscode
*.o
*.map
*.elf

36
LICENCE Normal file
View File

@ -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
免费授予获得了本软件及相关文档副本的任何人不受限地使用本软件的权利,此权利包括但不限于:使用、
复制、修改、合并、发布、分发、再许可以及销售本软件的副本,同时允许被提供本软件的人也这样做。
但使用者需满足以下条件:
上述版权声明及本许可证应包含于软件的所有副本或主要部分中。
本软件按原样提供,不提供任何明示或暗示的保证,包括但不限于对适销性、特定用途的适应性和非侵权性
的保证。在任何情况下,作者和版权持有人均不对任何损害及索赔承担责任,也不与该软件的使用和交易相关。

13
Makefile Normal file
View File

@ -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

23
README.MD Normal file
View File

@ -0,0 +1,23 @@
# Metaverse内核
基于multiboot2引导的64位内核。
## 开发计划
* 重新设置内核分页前的准备:
* multiboot2启动信息
* 重设显示模式前的内核日志
* 显示模式设置
* 键盘的连接
## 文档
### kernel
### libk
## 版权声明
版权所有 (c) 2023 - 现在 Random World Studio 保留所有权利。
本软件使用MIT开源许可证进行许可。详细信息请参阅许可证文件。

48
qemu/Makefile Normal file
View File

@ -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

BIN
qemu/bios/OVMF.4m.fd Normal file

Binary file not shown.

BIN
qemu/bios/OVMF.fd Normal file

Binary file not shown.

BIN
qemu/bios/OVMF_CODE.4m.fd Normal file

Binary file not shown.

Binary file not shown.

BIN
qemu/bios/OVMF_CODE.csm.fd Normal file

Binary file not shown.

BIN
qemu/bios/OVMF_CODE.fd Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
qemu/bios/OVMF_VARS.4m.fd Normal file

Binary file not shown.

BIN
qemu/bios/OVMF_VARS.fd Normal file

Binary file not shown.

BIN
qemu/metaverse.img Normal file

Binary file not shown.

49
src/Makefile Normal file
View File

@ -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

6
src/include/asm/sysctl.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef SYSCTL_H
#define SYSCTL_H 1
#define __asm_hlt__() __asm__("hlt");
#endif

View File

@ -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

15
src/include/kernel/klog.h Normal file
View File

@ -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

48
src/include/kernel/mm.h Normal file
View File

@ -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

117
src/include/kernel/tty.h Normal file
View File

@ -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

View File

@ -0,0 +1,6 @@
#ifndef MULTIBOOT2_H
#define MULTIBOOT2_H 1
#include <libk/multiboot2/bootinfo.h>
#endif

View File

@ -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 BSDs 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.
* Its 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 arent 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 wasnt 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

View File

@ -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

24
src/include/types.h Normal file
View File

@ -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

16
src/include/utils.h Normal file
View File

@ -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

76
src/kernel/Makefile Normal file
View File

@ -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

View File

@ -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

View File

@ -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
src/kernel/klog/klog.c Normal file
View File

37
src/kernel/main.c Normal file
View File

@ -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();
}
}

1882
src/kernel/tty/font.c Normal file

File diff suppressed because it is too large Load Diff

207
src/kernel/tty/tty.c Normal file
View File

@ -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);
}

78
src/libk/Makefile Normal file
View File

@ -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
src/libk/libk.c Normal file
View File

View File

@ -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];
}

View File

@ -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

View File

@ -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

66
src/metaverse.lds Normal file
View File

@ -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)
}
}

58
src/scripts/colorize Executable file
View File

@ -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)