diff --git a/kernel/include/acpi.hpp b/kernel/include/acpi.hpp index 52065d49..0f4257e7 100644 --- a/kernel/include/acpi.hpp +++ b/kernel/include/acpi.hpp @@ -10,7 +10,7 @@ namespace acpi { -void init(); +bool init(); void shutdown(); } //end of acpi namespace diff --git a/kernel/include/paging.hpp b/kernel/include/paging.hpp index 88c4c0bd..237f06cf 100644 --- a/kernel/include/paging.hpp +++ b/kernel/include/paging.hpp @@ -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 diff --git a/kernel/include/utils.hpp b/kernel/include/utils.hpp index be348bad..89fd17c4 100644 --- a/kernel/include/utils.hpp +++ b/kernel/include/utils.hpp @@ -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 void memcopy(T* destination, const T* source, size_t size){ --source; diff --git a/kernel/src/acpi.cpp b/kernel/src/acpi.cpp index e1698641..2db06d1a 100644 --- a/kernel/src/acpi.cpp +++ b/kernel/src/acpi.cpp @@ -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(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(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(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(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(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(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(*ptr), "FACP") == 0){ entrys = -2; - struct FACP *facp = reinterpret_cast(*ptr); + struct FACP* facp = reinterpret_cast(*ptr); + if (check_header(reinterpret_cast(facp->DSDT), "DSDT") == 0){ // search the \_S5 package in the DSDT char *S5Addr = reinterpret_cast(facp->DSDT + 36); // skip header - int dsdtLength = *(facp->DSDT+1) -36; + int dsdtLength = *(reinterpret_cast(static_cast(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(PM1a_CNT), SLP_TYPa | SLP_EN ); + out_word(PM1a_CNT, SLP_TYPa | SLP_EN ); if ( PM1b_CNT != 0 ){ - out_word(reinterpret_cast(PM1b_CNT), SLP_TYPb | SLP_EN ); + out_word(PM1b_CNT, SLP_TYPb | SLP_EN ); } k_print_line("acpi poweroff failed."); diff --git a/kernel/src/paging.cpp b/kernel/src/paging.cpp index f39bdfcf..f3dde5e9 100644 --- a/kernel/src/paging.cpp +++ b/kernel/src/paging.cpp @@ -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(new_page), 0, paging::PAGE_SIZE); + + last_page = new_page; + + return new_page; +} + +constexpr bool page_aligned(void* addr){ + return !(reinterpret_cast(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(virt) >> 12) & 0x1FF; + auto directory = (reinterpret_cast(virt) >> 21) & 0x1FF; + auto directory_ptr = (reinterpret_cast(virt) >> 30) & 0x1FF; + auto pml4 = (reinterpret_cast(virt) >> 39) & 0x1FF; + + pml4t_t pml4t = reinterpret_cast(0x70000); + + auto pdpt = reinterpret_cast(reinterpret_cast(pml4t[pml4]) & ~0xFFF); + auto pdt = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); + auto pt = reinterpret_cast(reinterpret_cast(pdt[directory]) & ~0xFFF); + return reinterpret_cast(reinterpret_cast(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(virt) >> 12) & 0x1FF; + auto directory = (reinterpret_cast(virt) >> 21) & 0x1FF; + auto directory_ptr = (reinterpret_cast(virt) >> 30) & 0x1FF; + auto pml4 = (reinterpret_cast(virt) >> 39) & 0x1FF; + + pml4t_t pml4t = reinterpret_cast(0x70000); + if(!(reinterpret_cast(pml4t[pml4]) & PRESENT)){ + return false; + } + + auto pdpt = reinterpret_cast(reinterpret_cast(pml4t[pml4]) & ~0xFFF); + if(!(reinterpret_cast(pdpt[directory_ptr]) & PRESENT)){ + return false; + } + + auto pdt = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); + if(!(reinterpret_cast(pdt[directory]) & PRESENT)){ + return false; + } + + auto pt = reinterpret_cast(reinterpret_cast(pdt[directory]) & ~0xFFF); + return reinterpret_cast(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(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(physical) >> 12) & 0x1FF; - auto directory = (reinterpret_cast(physical) >> 21) & 0x1FF; - auto directory_ptr = (reinterpret_cast(physical) >> 30) & 0x1FF; - auto pml4 = (reinterpret_cast(physical) >> 39) & 0x1FF; + auto table = (reinterpret_cast(virt) >> 12) & 0x1FF; + auto directory = (reinterpret_cast(virt) >> 21) & 0x1FF; + auto directory_ptr = (reinterpret_cast(virt) >> 30) & 0x1FF; + auto pml4 = (reinterpret_cast(virt) >> 39) & 0x1FF; - //Find the entries pml4t_t pml4t = reinterpret_cast(0x70000); + + //Init new page if necessary + if(!(reinterpret_cast(pml4t[pml4]) & PRESENT)){ + pml4t[pml4] = reinterpret_cast(init_new_page() | (PRESENT | WRITEABLE)); + } + auto pdpt = reinterpret_cast(reinterpret_cast(pml4t[pml4]) & ~0xFFF); + + //Init new page if necessary + if(!(reinterpret_cast(pdpt[directory_ptr]) & PRESENT)){ + pdpt[directory_ptr] = reinterpret_cast(init_new_page() | (PRESENT | WRITEABLE)); + } + auto pdt = reinterpret_cast(reinterpret_cast(pdpt[directory_ptr]) & ~0xFFF); + + //Init new page if necessary + if(!(reinterpret_cast(pdt[directory]) & PRESENT)){ + pdt[directory] = reinterpret_cast(init_new_page() | (PRESENT | WRITEABLE)); + } + auto pt = reinterpret_cast(reinterpret_cast(pdt[directory]) & ~0xFFF); - //Identity map the physical address - pt[table] = reinterpret_cast(reinterpret_cast(physical) | 0x3); + //Check if the page is already present + if(reinterpret_cast(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(pt[table]) == (reinterpret_cast(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(reinterpret_cast(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(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(reinterpret_cast(physical) + page * PAGE_SIZE))){ + auto addr = reinterpret_cast(reinterpret_cast(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(reinterpret_cast(virt) + page * PAGE_SIZE))){ return false; } } diff --git a/kernel/src/shell.cpp b/kernel/src/shell.cpp index 814a92e6..d1f76ec4 100644 --- a/kernel/src/shell.cpp +++ b/kernel/src/shell.cpp @@ -516,9 +516,11 @@ void cat_command(const vector& params){ } void shutdown_command(const vector&){ - k_print_line("Init ACPI"); + if(!acpi::init()){ + k_print_line("Unable to init ACPI"); + } - acpi::init(); + acpi::shutdown(); } } //end of anonymous namespace diff --git a/kernel/src/sysinfo.cpp b/kernel/src/sysinfo.cpp index 7b5dd21f..de8957d0 100644 --- a/kernel/src/sysinfo.cpp +++ b/kernel/src/sysinfo.cpp @@ -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 diff --git a/kernel/src/utils.cpp b/kernel/src/utils.cpp index 4fb63530..3e438610 100644 --- a/kernel/src/utils.cpp +++ b/kernel/src/utils.cpp @@ -8,6 +8,16 @@ #include "utils.hpp" #include "string.hpp" +void memset(void* ptr, unsigned char value, size_t num){ + auto p = static_cast(ptr); + + --p; + + while(num--){ + *++p = value; + } +} + bool str_equals(const char* a, const char* b){ while(*a && *a == *b){ ++a;