mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-08 20:10:04 -04:00
Update ACPI to implement shutdown
This commit is contained in:
parent
03e21e8b37
commit
92fa122b0f
@ -10,7 +10,7 @@
|
||||
|
||||
namespace acpi {
|
||||
|
||||
void init();
|
||||
bool init();
|
||||
void shutdown();
|
||||
|
||||
} //end of acpi namespace
|
||||
|
@ -14,8 +14,11 @@ namespace paging {
|
||||
|
||||
const int PAGE_SIZE = 4096;
|
||||
|
||||
bool identity_map(void* physical);
|
||||
bool identity_map(void* physical, size_t pages);
|
||||
void* physical_address(void* virt);
|
||||
bool page_present(void* virt);
|
||||
bool page_free_or_set(void* virt, void* physical);
|
||||
bool identity_map(void* virt);
|
||||
bool identity_map(void* virt, size_t pages);
|
||||
|
||||
} //end of namespace paging
|
||||
|
||||
|
@ -25,6 +25,8 @@ uint64_t str_len(const char* a);
|
||||
const char* str_until(char* a, char c);
|
||||
const char* str_from(char* a, char c);
|
||||
|
||||
void memset(void * ptr, uint8_t value, size_t num);
|
||||
|
||||
template<typename T>
|
||||
void memcopy(T* destination, const T* source, size_t size){
|
||||
--source;
|
||||
|
@ -15,37 +15,39 @@
|
||||
|
||||
namespace {
|
||||
|
||||
uint32_t *SMI_CMD;
|
||||
uint32_t SMI_CMD; //ptr
|
||||
uint8_t ACPI_ENABLE;
|
||||
uint8_t ACPI_DISABLE;
|
||||
uint32_t *PM1a_CNT;
|
||||
uint32_t *PM1b_CNT;
|
||||
uint32_t PM1a_CNT; //ptr
|
||||
uint32_t PM1b_CNT; //ptr
|
||||
uint16_t SLP_TYPa;
|
||||
uint16_t SLP_TYPb;
|
||||
uint16_t SLP_EN;
|
||||
uint16_t SCI_EN;
|
||||
uint8_t PM1_CNT_LEN;
|
||||
|
||||
bool version_2 = false;
|
||||
|
||||
struct RSDPtr {
|
||||
uint8_t Signature[8];
|
||||
uint8_t CheckSum;
|
||||
uint8_t OemID[6];
|
||||
uint8_t Revision;
|
||||
uint32_t *RsdtAddress;
|
||||
uint32_t RsdtAddress; //ptr
|
||||
};
|
||||
|
||||
struct FACP {
|
||||
uint8_t Signature[4];
|
||||
uint32_t Length;
|
||||
uint8_t unneded1[40 - 8];
|
||||
uint32_t *DSDT;
|
||||
uint32_t DSDT; //ptr
|
||||
uint8_t unneded2[48 - 44];
|
||||
uint32_t *SMI_CMD;
|
||||
uint32_t SMI_CMD; //ptr
|
||||
uint8_t ACPI_ENABLE;
|
||||
uint8_t ACPI_DISABLE;
|
||||
uint8_t unneded3[64 - 54];
|
||||
uint32_t *PM1a_CNT_BLK;
|
||||
uint32_t *PM1b_CNT_BLK;
|
||||
uint32_t PM1a_CNT_BLK; //ptr
|
||||
uint32_t PM1b_CNT_BLK; //ptr
|
||||
uint8_t unneded4[89 - 72];
|
||||
uint8_t PM1_CNT_LEN;
|
||||
};
|
||||
@ -83,10 +85,8 @@ unsigned int* check_rsd_ptr(unsigned int *ptr) {
|
||||
|
||||
// found valid rsdpd
|
||||
if (check == 0) {
|
||||
if (rsdp->Revision == 0)
|
||||
k_print_line("ACPI 1");
|
||||
else
|
||||
k_print_line("ACPI 2");
|
||||
version_2 = rsdp->Revision != 0;
|
||||
|
||||
return reinterpret_cast<unsigned int *>(rsdp->RsdtAddress);
|
||||
}
|
||||
}
|
||||
@ -142,14 +142,14 @@ int check_header(unsigned int *ptr, const char* sig){
|
||||
|
||||
int acpiEnable(void){
|
||||
// check if acpi is enabled
|
||||
if ( (in_word(reinterpret_cast<uint64_t>(PM1a_CNT)) &SCI_EN) == 0 ){
|
||||
if ( (in_word(PM1a_CNT) &SCI_EN) == 0 ){
|
||||
// check if acpi can be enabled
|
||||
if (SMI_CMD != 0 && ACPI_ENABLE != 0){
|
||||
out_byte(reinterpret_cast<uint64_t>(SMI_CMD), ACPI_ENABLE); // send acpi enable command
|
||||
out_byte(SMI_CMD, ACPI_ENABLE); // send acpi enable command
|
||||
// give 3 seconds time to enable acpi
|
||||
int i;
|
||||
for (i=0; i<300; i++ ){
|
||||
if ( (in_word(reinterpret_cast<uint64_t>(PM1a_CNT)) & SCI_EN) == 1 )
|
||||
if ( (in_word(PM1a_CNT) & SCI_EN) == 1 )
|
||||
break;
|
||||
sleep_ms(10);
|
||||
}
|
||||
@ -157,7 +157,7 @@ int acpiEnable(void){
|
||||
if (PM1b_CNT != 0)
|
||||
for (; i<300; i++ )
|
||||
{
|
||||
if ( (in_word(reinterpret_cast<uint64_t>(PM1b_CNT)) & SCI_EN) == 1 )
|
||||
if ( (in_word(PM1b_CNT) & SCI_EN) == 1 )
|
||||
break;
|
||||
sleep_ms(10);
|
||||
}
|
||||
@ -199,17 +199,12 @@ int acpiEnable(void){
|
||||
int init_acpi(){
|
||||
unsigned int *ptr = get_rsd_ptr();
|
||||
|
||||
k_printf("%h\n", reinterpret_cast<uintptr_t>(ptr));
|
||||
|
||||
if(!paging::identity_map(ptr, 16)){
|
||||
k_print_line("Impossible to map the ACPI tables");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if address is correct ( if acpi is available on this pc )
|
||||
if (ptr && check_header(ptr, "RSDT") == 0){
|
||||
//k_print_line("2");
|
||||
// the RSDT contains an unknown number of pointers to acpi tables
|
||||
int entrys = *(ptr + 1);
|
||||
entrys = (entrys-36) /4;
|
||||
@ -220,11 +215,12 @@ int init_acpi(){
|
||||
if (check_header(reinterpret_cast<unsigned int*>(*ptr), "FACP") == 0){
|
||||
entrys = -2;
|
||||
|
||||
struct FACP *facp = reinterpret_cast<FACP*>(*ptr);
|
||||
struct FACP* facp = reinterpret_cast<FACP*>(*ptr);
|
||||
|
||||
if (check_header(reinterpret_cast<unsigned int*>(facp->DSDT), "DSDT") == 0){
|
||||
// search the \_S5 package in the DSDT
|
||||
char *S5Addr = reinterpret_cast<char *>(facp->DSDT + 36); // skip header
|
||||
int dsdtLength = *(facp->DSDT+1) -36;
|
||||
int dsdtLength = *(reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(facp->DSDT)+1)) - 36;
|
||||
while (0 < dsdtLength--){
|
||||
if ( memcmp(S5Addr, "_S5_", 4) == 0)
|
||||
break;
|
||||
@ -287,8 +283,8 @@ int init_acpi(){
|
||||
|
||||
} //end of anonymous namespace
|
||||
|
||||
void acpi::init(){
|
||||
init_acpi();
|
||||
bool acpi::init(){
|
||||
return init_acpi() == 0;
|
||||
}
|
||||
|
||||
void acpi::shutdown(){
|
||||
@ -300,9 +296,9 @@ void acpi::shutdown(){
|
||||
acpiEnable();
|
||||
|
||||
// send the shutdown command
|
||||
out_word(reinterpret_cast<uint64_t>(PM1a_CNT), SLP_TYPa | SLP_EN );
|
||||
out_word(PM1a_CNT, SLP_TYPa | SLP_EN );
|
||||
if ( PM1b_CNT != 0 ){
|
||||
out_word(reinterpret_cast<uint64_t>(PM1b_CNT), SLP_TYPb | SLP_EN );
|
||||
out_word(PM1b_CNT, SLP_TYPb | SLP_EN );
|
||||
}
|
||||
|
||||
k_print_line("acpi poweroff failed.");
|
||||
|
@ -7,6 +7,9 @@
|
||||
|
||||
#include "paging.hpp"
|
||||
#include "types.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include "console.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -16,44 +19,153 @@ typedef pt_t* pdt_t;
|
||||
typedef pdt_t* pdpt_t;
|
||||
typedef pdpt_t* pml4t_t;
|
||||
|
||||
constexpr int PRESENT = 0x1;
|
||||
constexpr int WRITEABLE = 0x2;
|
||||
constexpr int USER = 0x4;
|
||||
|
||||
//Memory from 0x70000 can be used for pages
|
||||
uintptr_t last_page = 0x73000;
|
||||
|
||||
uintptr_t init_new_page(){
|
||||
auto new_page = last_page + paging::PAGE_SIZE;
|
||||
|
||||
memset(reinterpret_cast<void*>(new_page), 0, paging::PAGE_SIZE);
|
||||
|
||||
last_page = new_page;
|
||||
|
||||
return new_page;
|
||||
}
|
||||
|
||||
constexpr bool page_aligned(void* addr){
|
||||
return !(reinterpret_cast<uintptr_t>(addr) & (paging::PAGE_SIZE - 1));
|
||||
}
|
||||
|
||||
} //end of anonymous namespace
|
||||
|
||||
bool paging::identity_map(void* physical){
|
||||
void* paging::physical_address(void* virt){
|
||||
if(!page_present(virt)){
|
||||
//TODO Not a very good value since 0x0 is a valid physical address
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//Find the correct indexes inside the paging table for the physical address
|
||||
auto table = (reinterpret_cast<uintptr_t>(virt) >> 12) & 0x1FF;
|
||||
auto directory = (reinterpret_cast<uintptr_t>(virt) >> 21) & 0x1FF;
|
||||
auto directory_ptr = (reinterpret_cast<uintptr_t>(virt) >> 30) & 0x1FF;
|
||||
auto pml4 = (reinterpret_cast<uintptr_t>(virt) >> 39) & 0x1FF;
|
||||
|
||||
pml4t_t pml4t = reinterpret_cast<pml4t_t>(0x70000);
|
||||
|
||||
auto pdpt = reinterpret_cast<pdpt_t>(reinterpret_cast<uintptr_t>(pml4t[pml4]) & ~0xFFF);
|
||||
auto pdt = reinterpret_cast<pdt_t>(reinterpret_cast<uintptr_t>(pdpt[directory_ptr]) & ~0xFFF);
|
||||
auto pt = reinterpret_cast<pt_t>(reinterpret_cast<uintptr_t>(pdt[directory]) & ~0xFFF);
|
||||
return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(pt[table]) & ~0xFFF);
|
||||
}
|
||||
|
||||
bool paging::page_present(void* virt){
|
||||
//Find the correct indexes inside the paging table for the physical address
|
||||
auto table = (reinterpret_cast<uintptr_t>(virt) >> 12) & 0x1FF;
|
||||
auto directory = (reinterpret_cast<uintptr_t>(virt) >> 21) & 0x1FF;
|
||||
auto directory_ptr = (reinterpret_cast<uintptr_t>(virt) >> 30) & 0x1FF;
|
||||
auto pml4 = (reinterpret_cast<uintptr_t>(virt) >> 39) & 0x1FF;
|
||||
|
||||
pml4t_t pml4t = reinterpret_cast<pml4t_t>(0x70000);
|
||||
if(!(reinterpret_cast<uintptr_t>(pml4t[pml4]) & PRESENT)){
|
||||
return false;
|
||||
}
|
||||
|
||||
auto pdpt = reinterpret_cast<pdpt_t>(reinterpret_cast<uintptr_t>(pml4t[pml4]) & ~0xFFF);
|
||||
if(!(reinterpret_cast<uintptr_t>(pdpt[directory_ptr]) & PRESENT)){
|
||||
return false;
|
||||
}
|
||||
|
||||
auto pdt = reinterpret_cast<pdt_t>(reinterpret_cast<uintptr_t>(pdpt[directory_ptr]) & ~0xFFF);
|
||||
if(!(reinterpret_cast<uintptr_t>(pdt[directory]) & PRESENT)){
|
||||
return false;
|
||||
}
|
||||
|
||||
auto pt = reinterpret_cast<pt_t>(reinterpret_cast<uintptr_t>(pdt[directory]) & ~0xFFF);
|
||||
return reinterpret_cast<uintptr_t>(pt[table]) & PRESENT;
|
||||
}
|
||||
|
||||
bool paging::page_free_or_set(void* virt, void* physical){
|
||||
if(!page_present(virt)){
|
||||
return true;
|
||||
}
|
||||
|
||||
if(physical_address(virt) == physical){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool paging::identity_map(void* virt){
|
||||
//The address must be page-aligned
|
||||
if(reinterpret_cast<uintptr_t>(physical) % PAGE_SIZE != 0){
|
||||
if(!page_aligned(virt)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Find the correct indexes inside the paging table for the physical address
|
||||
auto table = (reinterpret_cast<uintptr_t>(physical) >> 12) & 0x1FF;
|
||||
auto directory = (reinterpret_cast<uintptr_t>(physical) >> 21) & 0x1FF;
|
||||
auto directory_ptr = (reinterpret_cast<uintptr_t>(physical) >> 30) & 0x1FF;
|
||||
auto pml4 = (reinterpret_cast<uintptr_t>(physical) >> 39) & 0x1FF;
|
||||
auto table = (reinterpret_cast<uintptr_t>(virt) >> 12) & 0x1FF;
|
||||
auto directory = (reinterpret_cast<uintptr_t>(virt) >> 21) & 0x1FF;
|
||||
auto directory_ptr = (reinterpret_cast<uintptr_t>(virt) >> 30) & 0x1FF;
|
||||
auto pml4 = (reinterpret_cast<uintptr_t>(virt) >> 39) & 0x1FF;
|
||||
|
||||
//Find the entries
|
||||
pml4t_t pml4t = reinterpret_cast<pml4t_t>(0x70000);
|
||||
|
||||
//Init new page if necessary
|
||||
if(!(reinterpret_cast<uintptr_t>(pml4t[pml4]) & PRESENT)){
|
||||
pml4t[pml4] = reinterpret_cast<pdpt_t>(init_new_page() | (PRESENT | WRITEABLE));
|
||||
}
|
||||
|
||||
auto pdpt = reinterpret_cast<pdpt_t>(reinterpret_cast<uintptr_t>(pml4t[pml4]) & ~0xFFF);
|
||||
|
||||
//Init new page if necessary
|
||||
if(!(reinterpret_cast<uintptr_t>(pdpt[directory_ptr]) & PRESENT)){
|
||||
pdpt[directory_ptr] = reinterpret_cast<pdt_t>(init_new_page() | (PRESENT | WRITEABLE));
|
||||
}
|
||||
|
||||
auto pdt = reinterpret_cast<pdt_t>(reinterpret_cast<uintptr_t>(pdpt[directory_ptr]) & ~0xFFF);
|
||||
|
||||
//Init new page if necessary
|
||||
if(!(reinterpret_cast<uintptr_t>(pdt[directory]) & PRESENT)){
|
||||
pdt[directory] = reinterpret_cast<pt_t>(init_new_page() | (PRESENT | WRITEABLE));
|
||||
}
|
||||
|
||||
auto pt = reinterpret_cast<pt_t>(reinterpret_cast<uintptr_t>(pdt[directory]) & ~0xFFF);
|
||||
|
||||
//Identity map the physical address
|
||||
pt[table] = reinterpret_cast<page_entry>(reinterpret_cast<uintptr_t>(physical) | 0x3);
|
||||
//Check if the page is already present
|
||||
if(reinterpret_cast<uintptr_t>(pt[table]) & PRESENT){
|
||||
//If the page is already set to the correct value, return true
|
||||
//If the page is set to another value, return false
|
||||
return reinterpret_cast<uintptr_t>(pt[table]) == (reinterpret_cast<uintptr_t>(virt) | (PRESENT | WRITEABLE));
|
||||
}
|
||||
|
||||
//TODO Check if pt[table] is already used and if so, return false
|
||||
//Identity map the physical address
|
||||
pt[table] = reinterpret_cast<page_entry>(reinterpret_cast<uintptr_t>(virt) | (PRESENT | WRITEABLE));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool paging::identity_map(void* physical, size_t pages){
|
||||
bool paging::identity_map(void* virt, size_t pages){
|
||||
//The address must be page-aligned
|
||||
if(reinterpret_cast<uintptr_t>(physical) % PAGE_SIZE != 0){
|
||||
if(!page_aligned(virt)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO This should first check each page for the present bit
|
||||
|
||||
//To avoid mapping only a subset of the pages
|
||||
//check if one of the page is already mapped to another value
|
||||
for(size_t page = 0; page < pages; ++page){
|
||||
if(!identity_map(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(physical) + page * PAGE_SIZE))){
|
||||
auto addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(virt) + page * PAGE_SIZE);
|
||||
if(!page_free_or_set(addr, addr)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Identity map each page
|
||||
for(size_t page = 0; page < pages; ++page){
|
||||
if(!identity_map(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(virt) + page * PAGE_SIZE))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -516,9 +516,11 @@ void cat_command(const vector<string>& params){
|
||||
}
|
||||
|
||||
void shutdown_command(const vector<string>&){
|
||||
k_print_line("Init ACPI");
|
||||
if(!acpi::init()){
|
||||
k_print_line("Unable to init ACPI");
|
||||
}
|
||||
|
||||
acpi::init();
|
||||
acpi::shutdown();
|
||||
}
|
||||
|
||||
} //end of anonymous namespace
|
||||
|
@ -36,7 +36,7 @@ void decode_bytes (int data, int descriptor[16], int *next){
|
||||
}
|
||||
|
||||
void get_cache_info() {
|
||||
int next = 0, i = 0;
|
||||
/*int next = 0, i = 0;
|
||||
int descriptor[256];
|
||||
int mem_count;
|
||||
|
||||
@ -199,7 +199,7 @@ void get_cache_info() {
|
||||
k_print_line(" 64-byte prefetching");
|
||||
if ( descriptor[i] == 0xF1)
|
||||
k_print_line(" 128-byte prefetching");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// EDX Features
|
||||
|
@ -8,6 +8,16 @@
|
||||
#include "utils.hpp"
|
||||
#include "string.hpp"
|
||||
|
||||
void memset(void* ptr, unsigned char value, size_t num){
|
||||
auto p = static_cast<unsigned char*>(ptr);
|
||||
|
||||
--p;
|
||||
|
||||
while(num--){
|
||||
*++p = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool str_equals(const char* a, const char* b){
|
||||
while(*a && *a == *b){
|
||||
++a;
|
||||
|
Loading…
x
Reference in New Issue
Block a user