mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-08 20:10:04 -04:00
Reimplement e820 support
This commit is contained in:
parent
0c30f2ef46
commit
0d0ab18b45
56
kernel/include/e820.hpp
Normal file
56
kernel/include/e820.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013.
|
||||
// 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)
|
||||
//=======================================================================
|
||||
|
||||
/*
|
||||
* The implementation of the memory detection is made in boot_16.cpp
|
||||
* The finalization of the memory detection is made in e820.cpp once in long
|
||||
* mode.
|
||||
*/
|
||||
|
||||
#ifndef CODE_16
|
||||
#include "types.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef E820_HPP
|
||||
#define E820_HPP
|
||||
|
||||
namespace e820 {
|
||||
|
||||
constexpr const uint32_t MAX_E820_ENTRIES = 25;
|
||||
|
||||
struct bios_e820_entry {
|
||||
uint32_t base_low;
|
||||
uint32_t base_high;
|
||||
uint32_t length_low;
|
||||
uint32_t length_high;
|
||||
uint16_t type;
|
||||
uint16_t acpi;
|
||||
// uint32_t damn_padding;
|
||||
} __attribute__((packed));
|
||||
|
||||
extern int16_t bios_e820_entry_count;
|
||||
extern bios_e820_entry bios_e820_entries[MAX_E820_ENTRIES];
|
||||
|
||||
struct mmapentry {
|
||||
uint64_t base;
|
||||
uint64_t size;
|
||||
uint64_t type;
|
||||
};
|
||||
|
||||
//Must be called by the kernel to transform e820 entries into mmap entries
|
||||
void finalize_memory_detection();
|
||||
|
||||
bool mmap_failed();
|
||||
uint64_t mmap_entry_count();
|
||||
const mmapentry& mmap_entry(uint64_t i);
|
||||
const char* str_e820_type(uint64_t type);
|
||||
|
||||
size_t available_memory();
|
||||
|
||||
} //end of namespace e820
|
||||
|
||||
#endif
|
@ -14,11 +14,14 @@ typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
|
||||
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
|
||||
typedef unsigned int uint64_t __attribute__ ((__mode__ (__DI__)));
|
||||
|
||||
typedef unsigned int int16_t __attribute__ ((__mode__ (__HI__)));
|
||||
|
||||
typedef uint64_t uintptr_t;
|
||||
typedef uint64_t size_t;
|
||||
|
||||
static_assert(sizeof(uint8_t) == 1, "uint32_t must be 1 byte long");
|
||||
static_assert(sizeof(uint16_t) == 2, "uint32_t must be 2 bytes long");
|
||||
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(int16_t) == 2, "int16_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");
|
||||
static_assert(sizeof(size_t) == 8, "size_t must be 8 bytes long");
|
||||
|
@ -12,14 +12,27 @@ namespace {
|
||||
|
||||
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
|
||||
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));
|
||||
typedef int int16_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(int16_t) == 2, "int16_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");
|
||||
|
||||
//Just here to be able to compile e820.hpp, should not be
|
||||
//used in boot_16.cpp
|
||||
typedef uint64_t size_t;
|
||||
|
||||
} //end of anonymous namespace
|
||||
|
||||
#define CODE_16
|
||||
#include "e820.hpp" //Just for the address of the e820 map
|
||||
|
||||
namespace {
|
||||
|
||||
struct gdt_ptr {
|
||||
uint16_t length;
|
||||
uint32_t pointer;
|
||||
@ -43,6 +56,41 @@ void reset_segments(){
|
||||
set_ds(0);
|
||||
}
|
||||
|
||||
int detect_memory_e820(){
|
||||
auto* smap = &e820::bios_e820_entries[0];
|
||||
|
||||
uint16_t entries = 0;
|
||||
|
||||
uint32_t contID = 0;
|
||||
int signature;
|
||||
int bytes;
|
||||
|
||||
do {
|
||||
asm volatile ("int 0x15"
|
||||
: "=a"(signature), "=c"(bytes), "=b"(contID)
|
||||
: "a"(0xE820), "b"(contID), "c"(24), "d"(0x534D4150), "D"(smap));
|
||||
|
||||
if (signature != 0x534D4150){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bytes > 20 && (smap->acpi & 0x0001) == 0){
|
||||
// ignore this entry
|
||||
} else {
|
||||
smap++;
|
||||
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();
|
||||
}
|
||||
|
||||
void disable_interrupts(){
|
||||
__asm__ __volatile__ ("cli");
|
||||
}
|
||||
@ -181,7 +229,8 @@ void __attribute__ ((noreturn)) rm_main(){
|
||||
//Make sure segments are clean
|
||||
reset_segments();
|
||||
|
||||
//TODO Detect memory
|
||||
//Analyze memory
|
||||
detect_memory();
|
||||
|
||||
//Disable interrupts
|
||||
disable_interrupts();
|
||||
|
78
kernel/src/e820.cpp
Normal file
78
kernel/src/e820.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013.
|
||||
// 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)
|
||||
//=======================================================================
|
||||
|
||||
#include "e820.hpp"
|
||||
|
||||
e820::bios_e820_entry e820::bios_e820_entries[e820::MAX_E820_ENTRIES];
|
||||
int16_t e820::bios_e820_entry_count = 0;
|
||||
|
||||
namespace {
|
||||
|
||||
e820::mmapentry e820_mmap[e820::MAX_E820_ENTRIES];
|
||||
size_t _available_memory;
|
||||
|
||||
} //end of namespace anonymous
|
||||
|
||||
void e820::finalize_memory_detection(){
|
||||
if(!mmap_failed()){
|
||||
for(uint64_t i = 0; i < bios_e820_entry_count; ++i){
|
||||
auto& bios_entry = bios_e820_entries[i];
|
||||
auto& os_entry = e820_mmap[i];
|
||||
|
||||
uint64_t base = bios_entry.base_low + (static_cast<uint64_t>(bios_entry.base_high) << 32);
|
||||
uint64_t length = bios_entry.length_low + (static_cast<uint64_t>(bios_entry.length_high) << 32);
|
||||
|
||||
os_entry.base = base;
|
||||
os_entry.size = length;
|
||||
os_entry.type = bios_entry.type;
|
||||
|
||||
if(os_entry.base == 0 && os_entry.type == 1){
|
||||
os_entry.type = 7;
|
||||
}
|
||||
|
||||
if(os_entry.type == 1){
|
||||
_available_memory += os_entry.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t e820::mmap_entry_count(){
|
||||
return bios_e820_entry_count;
|
||||
}
|
||||
|
||||
bool e820::mmap_failed(){
|
||||
return bios_e820_entry_count <= 0;
|
||||
}
|
||||
|
||||
const e820::mmapentry& e820::mmap_entry(uint64_t i){
|
||||
return e820_mmap[i];
|
||||
}
|
||||
|
||||
const char* e820::str_e820_type(uint64_t type){
|
||||
switch(type){
|
||||
case 1:
|
||||
return "Free";
|
||||
case 2:
|
||||
return "Reserved";
|
||||
case 3:
|
||||
case 4:
|
||||
return "ACPI";
|
||||
case 5:
|
||||
return "Unusable";
|
||||
case 6:
|
||||
return "Disabled";
|
||||
case 7:
|
||||
return "Kernel";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
size_t e820::available_memory(){
|
||||
return _available_memory;
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
#include "acpi.hpp"
|
||||
#include "interrupts.hpp"
|
||||
#include "arch.hpp"
|
||||
#include "e820.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -22,6 +23,8 @@ void _init();
|
||||
void kernel_main(){
|
||||
arch::enable_sse();
|
||||
|
||||
e820::finalize_memory_detection();
|
||||
|
||||
interrupt::install_idt();
|
||||
interrupt::install_isrs();
|
||||
interrupt::remap_irqs();
|
||||
|
Loading…
x
Reference in New Issue
Block a user