Prepare better initialization of thor

This commit is contained in:
Baptiste Wicht 2016-07-31 12:15:31 +02:00
parent 4c87d6386a
commit f9bea8cfe8
11 changed files with 773 additions and 12 deletions

View File

@ -5,6 +5,9 @@ default: thor.flp
kernel/debug/kernel.bin: force_look
cd kernel; $(MAKE)
init/debug/init.bin: force_look
cd init; $(MAKE)
tlib/libtlib.a: force_look
cd tlib; $(MAKE)
@ -17,13 +20,13 @@ bootloader/stage2.bin: force_look
programs: force_look tlib/libtlib.a
cd programs/; ${MAKE} dist
compile: bootloader/stage1.bin bootloader/stage2.bin kernel/debug/kernel.bin programs
compile: bootloader/stage1.bin bootloader/stage2.bin init/debug/init.bin kernel/debug/kernel.bin programs
hdd.img:
dd if=/dev/zero of=hdd.img bs=516096c count=1000
(echo n; echo p; echo 1; echo ""; echo ""; echo t; echo c; echo a; echo 1; echo w;) | sudo fdisk -u -C1000 -S63 -H16 hdd.img
thor.flp: hdd.img bootloader/stage1.bin bootloader/stage2.bin kernel/debug/kernel.bin programs
thor.flp: hdd.img bootloader/stage1.bin bootloader/stage2.bin init/debug/init.bin kernel/debug/kernel.bin programs
mkdir -p mnt/fake/
dd if=bootloader/stage1.bin of=hdd.img conv=notrunc
dd if=bootloader/stage2.bin of=hdd.img seek=1 conv=notrunc
@ -33,6 +36,7 @@ thor.flp: hdd.img bootloader/stage1.bin bootloader/stage2.bin kernel/debug/kerne
sudo mkdir mnt/fake/bin/
sudo mkdir mnt/fake/sys/
sudo mkdir mnt/fake/dev/
sudo /bin/cp init/debug/init.bin mnt/fake/
sudo /bin/cp kernel/debug/kernel.bin mnt/fake/
sudo /bin/cp programs/dist/* mnt/fake/bin/
sleep 0.1
@ -67,6 +71,7 @@ force_look:
clean:
cd bootloader; $(MAKE) clean
cd init; $(MAKE) clean
cd kernel; $(MAKE) clean
cd programs/; $(MAKE) clean
cd tlib/; $(MAKE) clean

View File

@ -142,15 +142,15 @@ second_step:
je .end_of_directory
mov ax, [gs:si]
cmp ax, 0x454B ; EK
cmp ax, 0x4E49 ; NI
jne .continue
mov ax, [gs:(si+2)]
cmp ax, 0x4E52 ; NR
cmp ax, 0x5449 ; TI
jne .continue
mov ax, [gs:(si+4)]
cmp ax, 0x4C45 ; LE
cmp ax, 0x2020 ; space space
jne .continue
mov ax, [gs:(si+6)]
@ -383,4 +383,4 @@ error_end:
; Make it sector-aligned
times 1536-($-$$) db 0
times 1536-($-$$) db 0

1
init/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
debug

32
init/Makefile Normal file
View File

@ -0,0 +1,32 @@
default: debug/init.bin
include ../cpp.mk
# Compile the 16-bit and 32-bit parts of the executable
INIT_FLAGS=-I../kernel/include
debug/boot_16.o: src/boot_16.cpp
@ mkdir -p debug/
$(CXX) $(COMMON_CPP_FLAGS) $(FLAGS_16) $(INIT_FLAGS) $(WARNING_FLAGS) -c src/boot_16.cpp -o debug/boot_16.o
debug/boot_32.o: src/boot_32.cpp
@ mkdir -p debug/
$(CXX) $(COMMON_CPP_FLAGS) $(FLAGS_32) $(INIT_FLAGS) $(WARNING_FLAGS) -c src/boot_32.cpp -o debug/boot_32.o
debug/boot_16_64.o: debug/boot_16.o
$(OC) -I elf32-i386 -O elf64-x86-64 debug/boot_16.o debug/boot_16_64.o
debug/boot_32_64.o: debug/boot_32.o
$(OC) -I elf32-i386 -O elf64-x86-64 debug/boot_32.o debug/boot_32_64.o
LINK_O_FILES=debug/boot_16_64.o debug/boot_32_64.o
debug/init.bin: $(LINK_O_FILES)
@ echo -e "$(MODE_COLOR)[debug]$(NO_COLOR) Link $(FILE_COLOR)$@$(NO_COLOR)"
$(CXX) $(KERNEL_LINK_FLAGS) $(KERNEL_CPP_FLAGS_64) -o $@.o $(LINK_O_FILES)
$(OC) -R .note -R .comment -O binary --set-section-flags .bss=alloc,load,contents $@.o $@
clean:
@ echo -e "Remove compiled files (deps/objects)"
@ rm -rf debug

17
init/include/boot_32.hpp Normal file
View File

@ -0,0 +1,17 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef BOOT_32_HPP
#define BOOT_32_HPP
extern "C" {
void __attribute((noreturn)) pm_main();
} //end of exern "C"
#endif

12
init/include/code16gcc.h Normal file
View File

@ -0,0 +1,12 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
/*
* Hack to make GCC output 16-bit code.
*/
asm(".code16gcc");

50
init/linker.ld Normal file
View File

@ -0,0 +1,50 @@
ENTRY(rm_main)
SECTIONS
{
/* This is where the bootloader will load the code */
. = 0x6000;
.text_16 BLOCK(512) : ALIGN(512)
{
debug/boot_16_64.o(.text)
}
.rodata_16 BLOCK(512) : ALIGN(512)
{
debug/boot_16_64.o(.rodata)
}
.bss_16 BLOCK(512) : ALIGN(512)
{
debug/boot_16_64.o(.bss)
}
.data_16 BLOCK(512) : ALIGN(512)
{
debug/boot_16_64.o(.data)
}
.text_32 BLOCK(512) : ALIGN(512)
{
debug/boot_32_64.o(.text)
}
/* 4K of Read-only data */
.rodata BLOCK(1K) : ALIGN(1K)
{
*(.rodata)
}
/* 4K of Read-write initialized data. */
.data BLOCK(1K) : ALIGN(1K)
{
*(.data)
}
/* 4K of Read-write uninitialized data. */
.bss BLOCK(1K) : ALIGN(1K)
{
*(.bss)
}
}

444
init/src/boot_16.cpp Normal file
View File

@ -0,0 +1,444 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#define CODE_16
#define THOR_INIT
#include "code16gcc.h"
#include "boot_32.hpp"
#include "gdt.hpp"
#include "e820.hpp" //Just for the address of the e820 map
#include "vesa.hpp"
#include "early_logging.hpp"
// For debugging purposes
#include "virtual_debug.hpp"
#include "serial.hpp"
//The Task State Segment
gdt::task_state_segment_t gdt::tss;
uint32_t early::early_logs_count = 0;
uint32_t early::early_logs[early::MAX_EARLY_LOGGING];
e820::bios_e820_entry e820::bios_e820_entries[e820::MAX_E820_ENTRIES];
int16_t e820::bios_e820_entry_count = 0;
vesa::vbe_info_block_t vesa::vbe_info_block;
vesa::mode_info_block_t vesa::mode_info_block;
bool vesa::vesa_enabled = false;
namespace {
/* Early Logging */
//TODO Check out why only very few early log are possible and it seems only
//at some position...
void early_log(const char* s){
early::early_logs[early::early_logs_count++] = reinterpret_cast<uint32_t>(s);
}
/* VESA */
constexpr const uint16_t DEFAULT_WIDTH = 1280;
constexpr const uint16_t DEFAULT_HEIGHT = 1024;
constexpr const uint16_t DEFAULT_BPP = 32;
void set_ds(uint16_t seg){
asm volatile("mov ds, %0" : : "rm" (seg));
}
void set_es(uint16_t seg){
asm volatile("mov es, %0" : : "rm" (seg));
}
void set_gs(uint16_t seg){
asm volatile("mov gs, %0" : : "rm" (seg));
}
void reset_segments(){
set_ds(0);
set_es(0);
}
int detect_memory_e820(){
auto smap = &e820::bios_e820_entries[0];
uint16_t entries = 0;
uint32_t contID = 0;
int signature;
int bytes;
static e820::bios_e820_entry buf;
do {
asm volatile ("int 0x15"
: "=a"(signature), "=c"(bytes), "=b"(contID)
: "a"(0xE820), "b"(contID), "c"(24), "d"(0x534D4150), "D"(&buf));
if (signature != 0x534D4150){
early_log("e820 failed");
return -1;
}
if (bytes > 20 && (smap->acpi & 0x0001) == 0){
// ignore this entry
} else {
*smap++ = buf;
entries++;
}
} while (contID != 0 && entries < e820::MAX_E820_ENTRIES);
return entries;
}
void detect_memory(){
//TODO If e820 fails, try other solutions to get memory map
e820::bios_e820_entry_count = detect_memory_e820();
}
uint16_t read_mode(uint16_t i){
uint16_t mode;
asm volatile("mov gs, %2; mov si, %1; add si, %3; mov %0, gs:[si]"
: "=a" (mode)
: "rm" (vesa::vbe_info_block.video_modes_ptr[0]),
"rm" (vesa::vbe_info_block.video_modes_ptr[1]),
"rm" (i));
return mode;
}
uint16_t abs_diff(uint16_t a, uint16_t b){
if(a > b){
return a - b;
} else {
return b - a;
}
}
template<typename T>
constexpr bool bit_set(const T& value, uint8_t bit){
return value & (1 << bit);
}
void setup_vesa(){
vesa::vbe_info_block.signature[0] = 'V';
vesa::vbe_info_block.signature[1] = 'B';
vesa::vbe_info_block.signature[2] = 'E';
vesa::vbe_info_block.signature[3] = '2';
uint16_t return_code;
asm volatile ("int 0x10"
: "=a"(return_code)
: "a"(0x4F00), "D"(&vesa::vbe_info_block)
: "memory");
if(return_code == 0x4F){
uint16_t best_mode = 0;
uint16_t best_size_diff = 65535;
bool one = false;
for(uint16_t i = 0, mode = read_mode(i); mode != 0xFFFF; mode = read_mode(2 * ++i)){
asm volatile ("int 0x10"
: "=a"(return_code)
: "a"(0x4F01), "c"(mode), "D"(&vesa::mode_info_block)
: "memory");
//Make sure the mode is supported by get mode info function
if(return_code != 0x4F){
continue;
}
//Check that the mode support Linear Frame Buffer
if(!bit_set(vesa::mode_info_block.mode_attributes, 7)){
continue;
}
//Make sure it is a packed pixel or direct color model
if(vesa::mode_info_block.memory_model != 4 && vesa::mode_info_block.memory_model != 6){
continue;
}
if(vesa::mode_info_block.bpp != DEFAULT_BPP){
continue;
}
one = true;
auto x_res = vesa::mode_info_block.width;
auto y_res = vesa::mode_info_block.height;
auto size_diff = abs_diff(x_res, DEFAULT_WIDTH) + abs_diff(y_res, DEFAULT_HEIGHT);
if(size_diff < best_size_diff){
best_mode = mode;
best_size_diff = size_diff;
}
}
if(!one || best_mode == 0xFFFF){
vesa::vesa_enabled = false;
} else {
best_mode = best_mode | 0x4000;
asm volatile ("int 0x10"
: "=a"(return_code)
: "a"(0x4F01), "c"(best_mode), "D"(&vesa::mode_info_block)
: "memory");
if(return_code == 0x4F){
asm volatile ("int 0x10"
: "=a"(return_code)
: "a"(0x4F02), "b"(best_mode));
vesa::vesa_enabled = return_code == 0x4F;
} else {
vesa::vesa_enabled = false;
}
}
}
set_gs(0);
}
void disable_interrupts(){
asm volatile ("cli");
early_log("Interrupts disabled");
}
void enable_a20_gate(){
early_log("A20 gate enabled");
//TODO This should really be improved:
// 1. Test if a20 already enabled
// 2- Use several methods of enabling if necessary until one succeeds
//Enable A20 gate using fast method
auto port_a = in_byte(0x92);
port_a |= 0x02;
port_a &= ~0x01;
out_byte(port_a, 0x92);
}
void setup_idt(){
static const gdt::gdt_ptr null_idt = {0, 0};
asm volatile("lidt %0" : : "m" (null_idt));
}
gdt::gdt_descriptor_t null_descriptor(){
gdt::gdt_descriptor_t descriptor;
//zero-out the descriptor;
*(reinterpret_cast<uint64_t*>(&descriptor)) = 0;
return descriptor;
}
gdt::gdt_descriptor_t code_32_descriptor(){
gdt::gdt_descriptor_t descriptor;
descriptor.type = gdt::SEG_CODE_EXRD;
descriptor.base_low = 0;
descriptor.base_high = 0;
descriptor.limit_low = 0xFFFF;
descriptor.limit_high = 0xF;
descriptor.always_1 = 1;
descriptor.dpl = 0;
descriptor.present = 1;
descriptor.avl = 0;
descriptor.big = 1;
descriptor.long_mode = 0;
descriptor.granularity = 1;
return descriptor;
}
gdt::gdt_descriptor_t code_64_descriptor(){
gdt::gdt_descriptor_t descriptor;
descriptor.type = gdt::SEG_CODE_EXRD;
descriptor.base_low = 0;
descriptor.base_high = 0;
descriptor.limit_low = 0xFFFF;
descriptor.limit_high = 0xF;
descriptor.always_1 = 1;
descriptor.dpl = 0;
descriptor.present = 1;
descriptor.avl = 0;
descriptor.big = 0;
descriptor.long_mode = 1;
descriptor.granularity = 1;
return descriptor;
}
gdt::gdt_descriptor_t user_code_64_descriptor(){
gdt::gdt_descriptor_t descriptor;
descriptor.type = gdt::SEG_CODE_EXRD;
descriptor.base_low = 0;
descriptor.base_high = 0;
descriptor.limit_low = 0xFFFF;
descriptor.limit_high = 0xF;
descriptor.always_1 = 1;
descriptor.dpl = 3;
descriptor.present = 1;
descriptor.avl = 0;
descriptor.big = 0;
descriptor.long_mode = 1;
descriptor.granularity = 1;
return descriptor;
}
gdt::gdt_descriptor_t data_descriptor(){
gdt::gdt_descriptor_t descriptor;
descriptor.type = gdt::SEG_DATA_RDWR;
descriptor.base_low = 0;
descriptor.base_high = 0;
descriptor.limit_low = 0xFFFF;
descriptor.limit_high = 0xF;
descriptor.always_1 = 1;
descriptor.dpl = 0;
descriptor.present = 1;
descriptor.avl = 0;
descriptor.big = 1;
descriptor.long_mode = 0;
descriptor.granularity = 1;
return descriptor;
}
gdt::gdt_descriptor_t user_data_descriptor(){
gdt::gdt_descriptor_t descriptor;
descriptor.type = gdt::SEG_DATA_RDWR;
descriptor.base_low = 0;
descriptor.base_high = 0;
descriptor.limit_low = 0xFFFF;
descriptor.limit_high = 0xF;
descriptor.always_1 = 1;
descriptor.dpl = 3;
descriptor.present = 1;
descriptor.avl = 0;
descriptor.big = 0;
descriptor.long_mode = 1;
descriptor.granularity = 1;
return descriptor;
}
//TODO On some machines, this should be aligned to 16 bits
static gdt::gdt_descriptor_t gdt[8];
static gdt::gdt_ptr gdtr;
void setup_gdt(){
//1. Init GDT descriptor
gdt[0] = null_descriptor();
gdt[1] = code_32_descriptor();
gdt[2] = data_descriptor();
gdt[3] = code_64_descriptor();
gdt[4] = user_code_64_descriptor();
gdt[5] = user_data_descriptor();
//2. Init TSS Descriptor
uint32_t base = reinterpret_cast<uint32_t>(&gdt::tss);
uint32_t limit = base + sizeof(gdt::task_state_segment_t);
auto tss_selector = reinterpret_cast<gdt::tss_descriptor_t*>(&gdt[6]);
tss_selector->type = gdt::SEG_TSS_AVAILABLE;
tss_selector->always_0_1 = 0;
tss_selector->always_0_2 = 0;
tss_selector->always_0_3 = 0;
tss_selector->dpl = 3;
tss_selector->present = 1;
tss_selector->avl = 0;
tss_selector->granularity = 0;
tss_selector->base_low = base & 0xFFFFFF; //Bottom 24 bits
tss_selector->base_middle = (base & 0xFF000000) >> 24; //Top 8 bits
tss_selector->base_high = 0; //Top 32 bits are clear
tss_selector->limit_low = limit & 0xFFFF; //Low 16 bits
tss_selector->limit_high = (limit & 0xF0000) >> 16; //Top 4 bits
//3. Init the GDT Pointer
gdtr.length = sizeof(gdt) - 1;
gdtr.pointer = reinterpret_cast<uint32_t>(&gdt);
//4. Load the GDT
asm volatile("lgdt [%0]" : : "m" (gdtr));
//5. Zero-out the TSS
auto tss_ptr = reinterpret_cast<char*>(&gdt::tss);
for(unsigned int i = 0; i < sizeof(gdt::task_state_segment_t); ++i){
*tss_ptr++ = 0;
}
}
void protected_mode_enable(){
asm volatile("mov eax, cr0; or al, 1; mov cr0, eax;");
}
void disable_paging(){
asm volatile("mov eax, cr0; and eax, 0b01111111111111111111111111111111; mov cr0, eax;");
}
void __attribute__((noreturn)) pm_jump(){
asm volatile(".byte 0x66, 0xea; .long pm_main; .word 0x8;");
__builtin_unreachable();
}
} //end of anonymous namespace
void __attribute__ ((noreturn)) rm_main(){
//Make sure segments are clean
reset_segments();
//Enable VESA
setup_vesa();
//Analyze memory
detect_memory();
//Make sure a20 gate is enabled
enable_a20_gate();
//Disable interrupts
disable_interrupts();
//Setup an IDT with null limits to prevents interrupts from being used in
//protected mode
setup_idt();
//Setup the GDT
setup_gdt();
//Switch to protected mode by activate PE bit of CR0
protected_mode_enable();
//Disable paging
disable_paging();
//Protected mode jump
pm_jump();
}

185
init/src/boot_32.cpp Normal file
View File

@ -0,0 +1,185 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#define CODE_32
#define THOR_INIT
#include "boot/boot_32.hpp"
#include "kernel.hpp"
#include "paging.hpp"
#include "early_logging.hpp"
#include "virtual_debug.hpp"
namespace {
constexpr const uint16_t COM1_PORT = 0x3f8;
void early_log(const char* s){
virtual_debug(s);
virtual_debug("\n");
early::early_logs[early::early_logs_count++] = reinterpret_cast<uint32_t>(s);
}
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int uint64_t __attribute__ ((__mode__ (__DI__)));
static_assert(sizeof(uint8_t) == 1, "uint8_t must be 1 byte long");
static_assert(sizeof(uint16_t) == 2, "uint16_t must be 2 bytes long");
static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes long");
static_assert(sizeof(uint64_t) == 8, "uint64_t must be 8 bytes long");
const uint32_t PML4T = 0x70000;
void set_segments(){
asm volatile(
"mov ax, 0x10; \t\n"
"mov ds, ax \t\n"
"mov es, ax \t\n"
"mov fs, ax \t\n"
"mov gs, ax \t\n"
"mov ss, ax");
}
void activate_pae(){
asm volatile("mov eax, cr4; or eax, 1 << 5; mov cr4, eax");
early_log("PAE Activated");
}
inline void clear_tables(uint32_t page){
auto page_ptr = reinterpret_cast<uint32_t*>(page);
for(uint32_t i = 0; i < (4 * 4096) / sizeof(uint32_t); ++i){
*page_ptr++ = 0;
}
}
void setup_paging(){
//Clear all tables
clear_tables(PML4T);
//Link tables (0x3 means Writeable and Supervisor)
//PML4T[0] -> PDPT
*reinterpret_cast<uint32_t*>(PML4T) = PML4T + paging::PAGE_SIZE + 0x7;
//PDPT[0] -> PDT
*reinterpret_cast<uint32_t*>(PML4T + 1 * paging::PAGE_SIZE) = PML4T + 2 * paging::PAGE_SIZE + 0x7;
//PD[0] -> PT
*reinterpret_cast<uint32_t*>(PML4T + 2 * paging::PAGE_SIZE) = PML4T + 3 * paging::PAGE_SIZE + 0x7;
//Map the first MiB
auto page_table_ptr = reinterpret_cast<uint32_t*>(PML4T + 3 * paging::PAGE_SIZE);
auto phys = 0x3;
for(uint32_t i = 0; i < 256; ++i){
*page_table_ptr = phys;
phys += paging::PAGE_SIZE;
//A page entry is 64 bit in size
page_table_ptr += 2;
}
early_log("Paging configured");
}
void enable_long_mode(){
asm volatile(
"mov ecx, 0xC0000080 \t\n"
"rdmsr \t\n"
"or eax, 0b100000000 \t\n"
"wrmsr \t\n");
early_log("Long mode enabled");
}
void set_pml4t(){
asm volatile(
"mov eax, 0x70000 \t\n" // Bass address of PML4
"mov cr3, eax \t\n"); // load page-map level-4 base
early_log("PML4T set");
}
void enable_paging(){
asm volatile(
"mov eax, cr0 \t\n"
"or eax, 0b10000000000000000000000000000000 \t\n"
"mov cr0, eax \t\n");
early_log("Paging enabled");
}
void __attribute__((noreturn)) lm_jump(){
//The trick done in boot_16 does not work, so just jump at the same
//place and then call the function
asm volatile("jmp 0x18:fake_label; fake_label:");
//TODO kernel_main();
__builtin_unreachable();
}
void serial_init() {
out_byte(COM1_PORT + 1, 0x00); // Disable all interrupts
out_byte(COM1_PORT + 3, 0x80); // Enable DLAB
out_byte(COM1_PORT + 0, 0x03); // 38400 baud
out_byte(COM1_PORT + 1, 0x00);
out_byte(COM1_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
out_byte(COM1_PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
out_byte(COM1_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
}
} //end of anonymous namespace
bool serial_is_transmit_buffer_empty() {
return in_byte(COM1_PORT + 5) & 0x20;
}
void serial_transmit(char a) {
while (serial_is_transmit_buffer_empty() == 0){}
out_byte(COM1_PORT, a);
}
extern "C" {
void pm_main(){
//Update segments
set_segments();
//Activate PAE
activate_pae();
//Setup paging
setup_paging();
// Initialize serial transmission (for debugging in Qemu)
serial_init();
//Enable long mode by setting the EFER.LME flag
enable_long_mode();
//Set the address of the PML4T
set_pml4t();
//Enable paging
enable_paging();
asm volatile("cli; hlt");
__builtin_unreachable();
//long mode jump
lm_jump();
}
} //end of exern "C"

View File

@ -8,7 +8,9 @@
#ifndef KERNEL_UTILS_H
#define KERNEL_UTILS_H
#ifndef THOR_INIT
#include <types.hpp>
#endif
inline uint8_t in_byte(uint16_t _port){
uint8_t rv;
@ -20,6 +22,14 @@ inline uint8_t in_byte(uint16_t _port){
return rv;
}
inline void out_byte (uint16_t _port, uint8_t _data){
asm volatile ("out %[port], %[data]"
: /* No outputs */
: [port] "dN" (_port), [data] "a" (_data));
}
#ifndef THOR_INIT
inline uint16_t in_word(uint16_t _port){
uint16_t rv;
@ -50,12 +60,6 @@ inline uint64_t in_qword(uint16_t _port){
return rv;
}
inline void out_byte (uint16_t _port, uint8_t _data){
asm volatile ("out %[port], %[data]"
: /* No outputs */
: [port] "dN" (_port), [data] "a" (_data));
}
inline void out_word(uint16_t _port, uint16_t _data){
asm volatile ("out %[port], %[data]"
: /* No outputs */
@ -88,4 +92,6 @@ inline uint32_t switch_endian_32(uint32_t nb) {
void print_stack(const char* msg, size_t check);
#define SHOW_STACK(M) { size_t check = 0; asm volatile("mov %0, rsp;" : "=r" (check)); print_stack(((M)), check); }
#endif //THOR_INIT
#endif

View File

@ -11,7 +11,12 @@
//TODO Integrate Bochs Parallel debugging
#include "kernel_utils.hpp"
#ifdef THOR_INIT
void serial_transmit(char a);
#else
#include "serial.hpp"
#endif
#define BOCHS_E9 0xE9
@ -32,7 +37,11 @@ inline void bochs_print(const char* s){
inline void serial_print(const char* s){
for(uint64_t i = 0; s[i] != '\0'; ++i){
#ifdef THOR_INIT
serial_transmit(s[i]);
#else
serial::transmit(s[i]);
#endif
}
}