mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-15 07:27:42 -04:00
Use the new boot 16
This commit is contained in:
parent
1b01a35c8d
commit
76bf1c1577
@ -6,42 +6,60 @@
|
|||||||
//=======================================================================
|
//=======================================================================
|
||||||
|
|
||||||
#define CODE_16
|
#define CODE_16
|
||||||
#define THOR_INIT
|
|
||||||
|
|
||||||
#include "code16gcc.h"
|
#include "boot/code16gcc.h"
|
||||||
#include "boot_32.hpp"
|
#include "boot/boot_32.hpp"
|
||||||
|
|
||||||
#include "gdt.hpp"
|
#include "gdt_types.hpp"
|
||||||
#include "e820.hpp" //Just for the address of the e820 map
|
#include "e820_types.hpp"
|
||||||
#include "vesa.hpp"
|
#include "vesa_types.hpp"
|
||||||
#include "early_logging.hpp"
|
#include "early_memory.hpp"
|
||||||
|
|
||||||
// For debugging purposes
|
e820::bios_e820_entry bios_e820_entries[e820::MAX_E820_ENTRIES];
|
||||||
#include "virtual_debug.hpp"
|
|
||||||
#include "serial.hpp"
|
|
||||||
|
|
||||||
//The Task State Segment
|
gdt::task_state_segment_t tss; // TODO Remove this (causes relocation errors for now)
|
||||||
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 {
|
namespace {
|
||||||
|
|
||||||
|
vesa::vbe_info_block_t vbe_info_block;
|
||||||
|
vesa::mode_info_block_t mode_info_block;
|
||||||
|
|
||||||
|
// Note: it seems to be impossible to pass parameters > 16 bit to
|
||||||
|
// functions, thus the macros. This should be fixable by
|
||||||
|
// reconfiguring better gcc for 16bit compilation which is highly
|
||||||
|
// inconvenient right now
|
||||||
|
|
||||||
|
#define early_write_32(ADDRESS, VALUE) \
|
||||||
|
{ \
|
||||||
|
auto seg = early::early_base / 0x10; \
|
||||||
|
auto offset = ADDRESS - early::early_base; \
|
||||||
|
asm volatile("mov fs, %[seg]; mov eax, %[offset]; mov [fs:0x0 + eax], %[value]; xor eax, eax; mov fs, eax;" \
|
||||||
|
: /* nothing */ \
|
||||||
|
: [seg] "r" (seg), [offset] "r" (offset), [value] "r" (VALUE) \
|
||||||
|
: "eax"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define early_read_32(ADDRESS, VALUE) \
|
||||||
|
{\
|
||||||
|
uint32_t temp_value; \
|
||||||
|
auto seg = early::early_base / 0x10; \
|
||||||
|
auto offset = ADDRESS - early::early_base; \
|
||||||
|
asm volatile("mov fs, %[seg]; mov eax, %[offset]; mov %[value], [fs:0x0 + eax]; xor eax, eax; mov fs, eax;" \
|
||||||
|
: [value] "=r" (temp_value) \
|
||||||
|
: [seg] "r" (seg), [offset] "r" (offset) \
|
||||||
|
: "eax"); \
|
||||||
|
VALUE = temp_value; \
|
||||||
|
}
|
||||||
|
|
||||||
/* Early Logging */
|
/* Early Logging */
|
||||||
|
|
||||||
//TODO Check out why only very few early log are possible and it seems only
|
#define early_log(STRING) \
|
||||||
//at some position...
|
{ \
|
||||||
void early_log(const char* s){
|
uint32_t c; \
|
||||||
early::early_logs[early::early_logs_count++] = reinterpret_cast<uint32_t>(s);
|
early_read_32(early::early_logs_count_address, c); \
|
||||||
}
|
early_write_32(early::early_logs_address + c * 4, STRING); \
|
||||||
|
early_write_32(early::early_logs_count_address, c + 1); \
|
||||||
|
}
|
||||||
|
|
||||||
/* VESA */
|
/* VESA */
|
||||||
|
|
||||||
@ -49,6 +67,16 @@ constexpr const uint16_t DEFAULT_WIDTH = 1280;
|
|||||||
constexpr const uint16_t DEFAULT_HEIGHT = 1024;
|
constexpr const uint16_t DEFAULT_HEIGHT = 1024;
|
||||||
constexpr const uint16_t DEFAULT_BPP = 32;
|
constexpr const uint16_t DEFAULT_BPP = 32;
|
||||||
|
|
||||||
|
void out_byte(uint8_t value, uint16_t port){
|
||||||
|
asm volatile("out %1, %0" : : "a" (value), "dN" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t in_byte(uint16_t port){
|
||||||
|
uint8_t value;
|
||||||
|
asm volatile("in %0,%1" : "=a" (value) : "dN" (port));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
void set_ds(uint16_t seg){
|
void set_ds(uint16_t seg){
|
||||||
asm volatile("mov ds, %0" : : "rm" (seg));
|
asm volatile("mov ds, %0" : : "rm" (seg));
|
||||||
}
|
}
|
||||||
@ -66,10 +94,10 @@ void reset_segments(){
|
|||||||
set_es(0);
|
set_es(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int detect_memory_e820(){
|
uint32_t detect_memory_e820(){
|
||||||
auto smap = &e820::bios_e820_entries[0];
|
auto smap = &bios_e820_entries[0];
|
||||||
|
|
||||||
uint16_t entries = 0;
|
uint32_t entries = 0;
|
||||||
|
|
||||||
uint32_t contID = 0;
|
uint32_t contID = 0;
|
||||||
int signature;
|
int signature;
|
||||||
@ -99,17 +127,31 @@ int detect_memory_e820(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void detect_memory(){
|
void detect_memory(){
|
||||||
//TODO If e820 fails, try other solutions to get memory map
|
// Init it to 0
|
||||||
|
early_write_32(early::e820_entry_count_address, 0);
|
||||||
|
|
||||||
e820::bios_e820_entry_count = detect_memory_e820();
|
auto entry_count = detect_memory_e820();
|
||||||
|
early_write_32(early::e820_entry_count_address, entry_count);
|
||||||
|
|
||||||
|
auto smap = reinterpret_cast<uint32_t*>((&bios_e820_entries[0]));
|
||||||
|
|
||||||
|
// Copy to early memory
|
||||||
|
for(uint16_t i = 0; i < entry_count; ++i){
|
||||||
|
for(uint16_t j = 0; j < 5; ++j){
|
||||||
|
early_write_32(early::e820_entry_address + (i * 5 + j) * 4, *smap);
|
||||||
|
++smap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO If e820 fails, try other solutions to get memory map
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t read_mode(uint16_t i){
|
uint16_t read_mode(uint16_t i){
|
||||||
uint16_t mode;
|
uint16_t mode;
|
||||||
asm volatile("mov gs, %2; mov si, %1; add si, %3; mov %0, gs:[si]"
|
asm volatile("mov gs, %2; mov si, %1; add si, %3; mov %0, gs:[si]"
|
||||||
: "=a" (mode)
|
: "=a" (mode)
|
||||||
: "rm" (vesa::vbe_info_block.video_modes_ptr[0]),
|
: "rm" (vbe_info_block.video_modes_ptr[0]),
|
||||||
"rm" (vesa::vbe_info_block.video_modes_ptr[1]),
|
"rm" (vbe_info_block.video_modes_ptr[1]),
|
||||||
"rm" (i));
|
"rm" (i));
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
@ -128,15 +170,15 @@ constexpr bool bit_set(const T& value, uint8_t bit){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setup_vesa(){
|
void setup_vesa(){
|
||||||
vesa::vbe_info_block.signature[0] = 'V';
|
vbe_info_block.signature[0] = 'V';
|
||||||
vesa::vbe_info_block.signature[1] = 'B';
|
vbe_info_block.signature[1] = 'B';
|
||||||
vesa::vbe_info_block.signature[2] = 'E';
|
vbe_info_block.signature[2] = 'E';
|
||||||
vesa::vbe_info_block.signature[3] = '2';
|
vbe_info_block.signature[3] = '2';
|
||||||
|
|
||||||
uint16_t return_code;
|
uint16_t return_code;
|
||||||
asm volatile ("int 0x10"
|
asm volatile ("int 0x10"
|
||||||
: "=a"(return_code)
|
: "=a"(return_code)
|
||||||
: "a"(0x4F00), "D"(&vesa::vbe_info_block)
|
: "a"(0x4F00), "D"(&vbe_info_block)
|
||||||
: "memory");
|
: "memory");
|
||||||
|
|
||||||
if(return_code == 0x4F){
|
if(return_code == 0x4F){
|
||||||
@ -148,7 +190,7 @@ void setup_vesa(){
|
|||||||
for(uint16_t i = 0, mode = read_mode(i); mode != 0xFFFF; mode = read_mode(2 * ++i)){
|
for(uint16_t i = 0, mode = read_mode(i); mode != 0xFFFF; mode = read_mode(2 * ++i)){
|
||||||
asm volatile ("int 0x10"
|
asm volatile ("int 0x10"
|
||||||
: "=a"(return_code)
|
: "=a"(return_code)
|
||||||
: "a"(0x4F01), "c"(mode), "D"(&vesa::mode_info_block)
|
: "a"(0x4F01), "c"(mode), "D"(&mode_info_block)
|
||||||
: "memory");
|
: "memory");
|
||||||
|
|
||||||
//Make sure the mode is supported by get mode info function
|
//Make sure the mode is supported by get mode info function
|
||||||
@ -157,23 +199,23 @@ void setup_vesa(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check that the mode support Linear Frame Buffer
|
//Check that the mode support Linear Frame Buffer
|
||||||
if(!bit_set(vesa::mode_info_block.mode_attributes, 7)){
|
if(!bit_set(mode_info_block.mode_attributes, 7)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Make sure it is a packed pixel or direct color model
|
//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){
|
if(mode_info_block.memory_model != 4 && mode_info_block.memory_model != 6){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vesa::mode_info_block.bpp != DEFAULT_BPP){
|
if(mode_info_block.bpp != DEFAULT_BPP){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
one = true;
|
one = true;
|
||||||
|
|
||||||
auto x_res = vesa::mode_info_block.width;
|
auto x_res = mode_info_block.width;
|
||||||
auto y_res = vesa::mode_info_block.height;
|
auto y_res = mode_info_block.height;
|
||||||
|
|
||||||
auto size_diff = abs_diff(x_res, DEFAULT_WIDTH) + abs_diff(y_res, DEFAULT_HEIGHT);
|
auto size_diff = abs_diff(x_res, DEFAULT_WIDTH) + abs_diff(y_res, DEFAULT_HEIGHT);
|
||||||
|
|
||||||
@ -183,23 +225,33 @@ void setup_vesa(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
early_write_32(early::vesa_enabled_address, 0);
|
||||||
|
|
||||||
if(!one || best_mode == 0xFFFF){
|
if(!one || best_mode == 0xFFFF){
|
||||||
vesa::vesa_enabled = false;
|
early_write_32(early::vesa_enabled_address, 0);
|
||||||
} else {
|
} else {
|
||||||
best_mode = best_mode | 0x4000;
|
best_mode = best_mode | 0x4000;
|
||||||
|
|
||||||
asm volatile ("int 0x10"
|
asm volatile ("int 0x10"
|
||||||
: "=a"(return_code)
|
: "=a"(return_code)
|
||||||
: "a"(0x4F01), "c"(best_mode), "D"(&vesa::mode_info_block)
|
: "a"(0x4F01), "c"(best_mode), "D"(&mode_info_block)
|
||||||
: "memory");
|
: "memory");
|
||||||
|
|
||||||
if(return_code == 0x4F){
|
if(return_code == 0x4F){
|
||||||
asm volatile ("int 0x10"
|
asm volatile ("int 0x10"
|
||||||
: "=a"(return_code)
|
: "=a"(return_code)
|
||||||
: "a"(0x4F02), "b"(best_mode));
|
: "a"(0x4F02), "b"(best_mode));
|
||||||
vesa::vesa_enabled = return_code == 0x4F;
|
|
||||||
|
early_write_32(early::vesa_enabled_address, return_code == 0x4F ? 1 : 0);
|
||||||
|
|
||||||
|
auto value = reinterpret_cast<uint32_t*>(&mode_info_block);
|
||||||
|
|
||||||
|
// Copy to early memory
|
||||||
|
for(uint16_t i = 0; i < 256 / 4; ++i){
|
||||||
|
early_write_32(early::vesa_mode_info_address + i * 4, *value++);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
vesa::vesa_enabled = false;
|
early_write_32(early::vesa_enabled_address, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +266,6 @@ void disable_interrupts(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void enable_a20_gate(){
|
void enable_a20_gate(){
|
||||||
early_log("A20 gate enabled");
|
|
||||||
|
|
||||||
//TODO This should really be improved:
|
//TODO This should really be improved:
|
||||||
// 1. Test if a20 already enabled
|
// 1. Test if a20 already enabled
|
||||||
@ -226,6 +277,7 @@ void enable_a20_gate(){
|
|||||||
port_a &= ~0x01;
|
port_a &= ~0x01;
|
||||||
out_byte(port_a, 0x92);
|
out_byte(port_a, 0x92);
|
||||||
|
|
||||||
|
early_log("A20 gate enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_idt(){
|
void setup_idt(){
|
||||||
@ -358,7 +410,7 @@ void setup_gdt(){
|
|||||||
|
|
||||||
//2. Init TSS Descriptor
|
//2. Init TSS Descriptor
|
||||||
|
|
||||||
uint32_t base = reinterpret_cast<uint32_t>(&gdt::tss);
|
uint32_t base = early::tss_address;
|
||||||
uint32_t limit = base + sizeof(gdt::task_state_segment_t);
|
uint32_t limit = base + sizeof(gdt::task_state_segment_t);
|
||||||
|
|
||||||
auto tss_selector = reinterpret_cast<gdt::tss_descriptor_t*>(&gdt[6]);
|
auto tss_selector = reinterpret_cast<gdt::tss_descriptor_t*>(&gdt[6]);
|
||||||
@ -388,9 +440,8 @@ void setup_gdt(){
|
|||||||
asm volatile("lgdt [%0]" : : "m" (gdtr));
|
asm volatile("lgdt [%0]" : : "m" (gdtr));
|
||||||
|
|
||||||
//5. Zero-out the TSS
|
//5. Zero-out the TSS
|
||||||
auto tss_ptr = reinterpret_cast<char*>(&gdt::tss);
|
for(uint16_t i = 0; i < 128; i += 4){
|
||||||
for(unsigned int i = 0; i < sizeof(gdt::task_state_segment_t); ++i){
|
early_write_32(early::tss_address + i * 4, 0);
|
||||||
*tss_ptr++ = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,6 +465,9 @@ void __attribute__ ((noreturn)) rm_main(){
|
|||||||
//Make sure segments are clean
|
//Make sure segments are clean
|
||||||
reset_segments();
|
reset_segments();
|
||||||
|
|
||||||
|
// Initialize the number of early logs
|
||||||
|
early_write_32(early::early_logs_count_address, 0);
|
||||||
|
|
||||||
//Enable VESA
|
//Enable VESA
|
||||||
setup_vesa();
|
setup_vesa();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user