feat: initial
This commit is contained in:
commit
92d8a91be4
20 changed files with 1058 additions and 0 deletions
51
kernel/src/init/init.cpp
Normal file
51
kernel/src/init/init.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "memory/pointer.h"
|
||||
#include "memory/sections.h"
|
||||
#include "init/init.h"
|
||||
#include "init/multiboot2.h"
|
||||
#include "init/print.h"
|
||||
|
||||
[[maybe_unused]] [[noreturn]] __attribute__((used)) static void halt() {
|
||||
while (true) __asm__ volatile ("");
|
||||
}
|
||||
|
||||
[[maybe_unused]] [[noreturn]] __attribute__((used)) static void panic(const char* msg) {
|
||||
print(msg, TextAttr{Color::Red, Color::Black});
|
||||
halt();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void step(const char* name, T&& fn) {
|
||||
print("Starting ", {});
|
||||
print(name, {});
|
||||
print("\n", {});
|
||||
fn();
|
||||
print("Finished ", {});
|
||||
print(name, {});
|
||||
print("\n", {});
|
||||
}
|
||||
|
||||
static void loadMultiboot() {
|
||||
multiboot::visit_all(overloaded{
|
||||
[](const multiboot::tag_mmap* mem) {
|
||||
print("Tag Memory\n", {});
|
||||
},
|
||||
[](const multiboot::tag_string* str) {
|
||||
print("Tag String (0x", {});
|
||||
print_hex(static_cast<uint64_t>(str->type), {});
|
||||
print("): ", {});
|
||||
print(str->string, {});
|
||||
print("\n", {});
|
||||
},
|
||||
[](const auto* tag) {
|
||||
print("Tag (0x", {});
|
||||
print_hex(static_cast<uint64_t>(tag->type), {});
|
||||
print(")\n", {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[[maybe_unused]] [[noreturn]] __attribute__((used)) void init() {
|
||||
print("Reached init\n", {});
|
||||
//step("multiboot", loadMultiboot);
|
||||
halt();
|
||||
}
|
||||
80
kernel/src/init/print.cpp
Normal file
80
kernel/src/init/print.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#include "init/print.h"
|
||||
#include "memory/pointer.h"
|
||||
|
||||
static constexpr uint64_t VGA_PHYS_BASE = 0xb8000;
|
||||
static constexpr int VGA_COLS = 80;
|
||||
static constexpr int VGA_ROWS = 25;
|
||||
static constexpr int BYTES_PER_CELL = 2;
|
||||
static constexpr int BYTES_PER_ROW = VGA_COLS * BYTES_PER_CELL;
|
||||
static constexpr int HEX_BITS = 4;
|
||||
static constexpr int HEX_TOP_SHIFT = (sizeof(uint64_t) * 8) - HEX_BITS;
|
||||
|
||||
static const char hex_chars[] = "0123456789ABCDEF";
|
||||
|
||||
static volatile uint32_t* cursor() {
|
||||
auto cursor_addr = read_symbol("__cursor");
|
||||
return paddr_t{cursor_addr}.access<volatile uint32_t>();
|
||||
}
|
||||
|
||||
static volatile uint16_t* vga_cell(uint32_t offset) {
|
||||
return paddr_t{VGA_PHYS_BASE + offset}.access<volatile uint16_t>();
|
||||
}
|
||||
|
||||
static void next_line() {
|
||||
*cursor() = ((*cursor() + BYTES_PER_ROW - 1) / BYTES_PER_ROW) * BYTES_PER_ROW;
|
||||
}
|
||||
|
||||
static void put_char(char ch, uint16_t attr_word) {
|
||||
if (ch == '\n') {
|
||||
next_line();
|
||||
return;
|
||||
}
|
||||
*vga_cell(*cursor()) = attr_word | (uint8_t)ch;
|
||||
*cursor() += BYTES_PER_CELL;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
*cursor() = 0;
|
||||
for (int i = 0; i < VGA_COLS * VGA_ROWS; i++) {
|
||||
*vga_cell(i * BYTES_PER_CELL) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void print(const char* str, TextAttr attr) {
|
||||
uint16_t w = attr.word();
|
||||
while (*str) {
|
||||
put_char(*str++, w);
|
||||
}
|
||||
}
|
||||
|
||||
void print_dec(uint64_t value, TextAttr attr) {
|
||||
uint16_t w = attr.word();
|
||||
if (value == 0) {
|
||||
put_char('0', w);
|
||||
return;
|
||||
}
|
||||
char buf[20];
|
||||
int len = 0;
|
||||
while (value > 0) {
|
||||
buf[len++] = '0' + (value % 10);
|
||||
value /= 10;
|
||||
}
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
put_char(buf[i], w);
|
||||
}
|
||||
}
|
||||
|
||||
void print_hex(uint64_t value, TextAttr attr) {
|
||||
uint16_t w = attr.word();
|
||||
put_char('0', w);
|
||||
put_char('x', w);
|
||||
bool leading = true;
|
||||
for (int shift = HEX_TOP_SHIFT; shift >= 0; shift -= HEX_BITS) {
|
||||
uint8_t nibble = (value >> shift) & 0xF;
|
||||
if (leading && nibble == 0 && shift > 0) {
|
||||
continue;
|
||||
}
|
||||
leading = false;
|
||||
put_char(hex_chars[nibble], w);
|
||||
}
|
||||
}
|
||||
28
kernel/src/init/sections.cpp
Normal file
28
kernel/src/init/sections.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "memory/sections.h"
|
||||
|
||||
#define RESERVE_SECTION(n) \
|
||||
extern char __##n##_start__[], __##n##_end__[]; \
|
||||
[[maybe_unused]] static const KernelSection _rsv_##n \
|
||||
__attribute__((section(".reserved_ranges"), used)) = { \
|
||||
(uint64_t)__##n##_start__, \
|
||||
(uint64_t)__##n##_end__, \
|
||||
#n \
|
||||
}
|
||||
|
||||
RESERVE_SECTION(boot);
|
||||
RESERVE_SECTION(startup_text);
|
||||
RESERVE_SECTION(startup_data);
|
||||
RESERVE_SECTION(text);
|
||||
RESERVE_SECTION(rodata);
|
||||
RESERVE_SECTION(data);
|
||||
RESERVE_SECTION(bss);
|
||||
[[maybe_unused]] static const KernelSection _rsv_reserved_ranges
|
||||
__attribute__((section(".reserved_ranges"), used)) = {
|
||||
(uint64_t)__reserved_ranges_start__,
|
||||
(uint64_t)__reserved_ranges_end__,
|
||||
"reserved_ranges"
|
||||
};
|
||||
RESERVE_SECTION(trampoline_text);
|
||||
RESERVE_SECTION(trampoline_data);
|
||||
RESERVE_SECTION(trampoline_bss);
|
||||
RESERVE_SECTION(trampoline_rodata);
|
||||
227
kernel/src/startup/entry.cpp
Normal file
227
kernel/src/startup/entry.cpp
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
#include "init/init.h"
|
||||
|
||||
extern "C" [[maybe_unused]] [[noreturn]] __attribute__((used)) void __entry64() {
|
||||
init();
|
||||
while (true) __asm__ volatile ("");
|
||||
}
|
||||
|
||||
asm(R"(
|
||||
.global __start
|
||||
|
||||
.section .startup_text, "ax"
|
||||
.type __start, @function
|
||||
.code32
|
||||
.align 16
|
||||
__start:
|
||||
cli
|
||||
mov $__start_stack_end, %esp
|
||||
mov %ebx, __multiboot_info
|
||||
call __clear
|
||||
mov $__hello_string, %esi
|
||||
call __print
|
||||
call __check_if_x64
|
||||
call __go_to_x64
|
||||
jmp __stop32
|
||||
__stop32:
|
||||
hlt
|
||||
jmp __stop32
|
||||
|
||||
__x64_not_supported:
|
||||
mov $__x64_not_supported_string, %esi
|
||||
call __print
|
||||
jmp __stop32
|
||||
|
||||
__check_if_x64:
|
||||
pushfl
|
||||
pop %eax
|
||||
mov %eax, %ecx
|
||||
xor $(1 << 21), %eax
|
||||
push %eax
|
||||
popfl
|
||||
pushfl
|
||||
pop %eax
|
||||
push %ecx
|
||||
popfl
|
||||
cmp %eax, %ecx
|
||||
je __x64_not_supported
|
||||
|
||||
mov $0x80000000, %eax
|
||||
cpuid
|
||||
cmp $0x80000001, %eax
|
||||
jb __x64_not_supported
|
||||
mov $0x80000001, %eax
|
||||
cpuid
|
||||
test $(1 << 29), %edx
|
||||
jz __x64_not_supported
|
||||
mov $__x64_supported_string, %esi
|
||||
call __print
|
||||
ret
|
||||
|
||||
__go_to_x64:
|
||||
push %ebx
|
||||
mov $__page_level_4, %eax
|
||||
mov %eax, %cr3
|
||||
|
||||
mov %cr4, %eax
|
||||
or $(0x1 << 5), %eax
|
||||
mov %eax, %cr4
|
||||
|
||||
mov $0xC0000080, %ecx
|
||||
rdmsr
|
||||
or $(0x1 << 8), %eax
|
||||
wrmsr
|
||||
|
||||
mov %cr0, %eax
|
||||
or $(0x1 << 31), %eax
|
||||
mov %eax, %cr0
|
||||
|
||||
pop %edi
|
||||
|
||||
lgdt __gdt_end
|
||||
jmp $0b1000, $__start64
|
||||
|
||||
jmp __stop32
|
||||
|
||||
.code64
|
||||
.align 16
|
||||
__start64:
|
||||
mov $0b10000, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
movabsq $__start64_high, %rax
|
||||
jmp* %rax
|
||||
__stop64:
|
||||
hlt
|
||||
jmp __stop64
|
||||
|
||||
.section .text
|
||||
.type __start64_high, @function
|
||||
.code64
|
||||
.align 16
|
||||
__start64_high:
|
||||
call __entry64
|
||||
hlt
|
||||
jmp __start64_high
|
||||
)");
|
||||
|
||||
// data section
|
||||
asm(R"(
|
||||
.global __multiboot_info
|
||||
.global __cursor
|
||||
.section .startup_data, "aw"
|
||||
__cursor:
|
||||
.int 0x0
|
||||
__hello_string:
|
||||
.string "Starting PrOSess! 32bit start!\n"
|
||||
__x64_not_supported_string:
|
||||
.string "x64 is not supported!\n"
|
||||
__x64_supported_string:
|
||||
.string "x64 is supported!\n"
|
||||
__multiboot_info:
|
||||
.long 0x0
|
||||
|
||||
__start_stack:
|
||||
.skip 0x1000
|
||||
.align 8
|
||||
__start_stack_end:
|
||||
.quad 0
|
||||
)");
|
||||
|
||||
// string operation section
|
||||
asm(R"(
|
||||
.section .startup_text, "ax"
|
||||
.code32
|
||||
.align 16
|
||||
__clear:
|
||||
movl $0, (__cursor)
|
||||
mov $0x0, %eax
|
||||
mov $0xb8000, %edi
|
||||
mov $0x2000, %ecx
|
||||
rep stosw
|
||||
ret
|
||||
|
||||
__print:
|
||||
mov $0xB8000, %edi
|
||||
add (__cursor), %edi
|
||||
__print_loop:
|
||||
mov (%esi), %al
|
||||
mov $0x0F, %ah
|
||||
cmp $0, %al
|
||||
je __print_end
|
||||
cmp $'\n', %al
|
||||
je __print_next_line
|
||||
mov %ax, (%edi)
|
||||
add $2, %edi
|
||||
add $1, %esi
|
||||
jmp __print_loop
|
||||
__print_next_line:
|
||||
sub $0xB8000, %edi
|
||||
mov %edi, (__cursor)
|
||||
add $0xB8000, %edi
|
||||
call __next_line
|
||||
mov $0xB8000, %edi
|
||||
add (__cursor), %edi
|
||||
add $1, %esi
|
||||
jmp __print_loop
|
||||
__print_end:
|
||||
sub $0xB8000, %edi
|
||||
mov %edi, (__cursor)
|
||||
ret
|
||||
|
||||
__next_line:
|
||||
push %eax
|
||||
push %ecx
|
||||
mov (__cursor), %eax
|
||||
|
||||
leal 159(%eax), %ecx
|
||||
movl $1717986919, %eax
|
||||
imull %ecx
|
||||
sarl $31, %ecx
|
||||
sarl $6, %edx
|
||||
subl %ecx, %edx
|
||||
leal (%edx,%edx,4), %eax
|
||||
sall $5, %eax
|
||||
|
||||
mov %eax, (__cursor)
|
||||
pop %ecx
|
||||
pop %eax
|
||||
ret
|
||||
)");
|
||||
|
||||
// tmp page table
|
||||
asm(R"(
|
||||
.section .startup_data, "aw"
|
||||
.align 0x1000
|
||||
__page_level_4:
|
||||
.quad __page_level_3_low_1gb_identity_map + ((1 << 0) | (1 << 1))
|
||||
.zero 0x7F8
|
||||
.quad __page_level_3_kernel_1gb_identity_map + ((1 << 0) | (1 << 1))
|
||||
.zero 0x7F8
|
||||
|
||||
.align 0x1000
|
||||
__page_level_3_low_1gb_identity_map:
|
||||
.quad (1 << 0) | (1 << 1) | (1 << 7) | 0x0
|
||||
.zero 0xFF8 # rest of table is 0
|
||||
|
||||
.align 0x1000
|
||||
__page_level_3_kernel_1gb_identity_map:
|
||||
.quad (1 << 0) | (1 << 1) | (1 << 7) | 0x0
|
||||
.zero 0xFF8 # rest of table is 0
|
||||
)");
|
||||
|
||||
// startup gdt
|
||||
asm(R"(
|
||||
.section .startup_data, "aw"
|
||||
.align 0x1000
|
||||
__gdt:
|
||||
.quad 0
|
||||
.quad (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) # code segment
|
||||
.quad (1 << 41) | (1 << 44) | (1 << 47) # data segment
|
||||
.align 0x1000
|
||||
__gdt_end:
|
||||
.word __gdt_end - __gdt - 1
|
||||
.quad __gdt
|
||||
)");
|
||||
16
kernel/src/startup/multiboot.cpp
Normal file
16
kernel/src/startup/multiboot.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
asm(R"(
|
||||
.global __multiboot_header
|
||||
.section .multiboot_header, "a"
|
||||
|
||||
.align 8
|
||||
__multiboot_header:
|
||||
.int 0xe85250d6 # multiboot2
|
||||
.int 0 # protected mode i386
|
||||
.int __multiboot_header_end - __multiboot_header
|
||||
.int 0x100000000 - (0xe85250d6 + 0 + (__multiboot_header_end - __multiboot_header))
|
||||
|
||||
.word 0
|
||||
.word 0
|
||||
.int 8
|
||||
__multiboot_header_end:
|
||||
)");
|
||||
Loading…
Add table
Add a link
Reference in a new issue