diff --git a/src/modules/driver.acpi/main.cpp b/src/modules/driver.acpi/main.cpp new file mode 100644 index 0000000..72b9e94 --- /dev/null +++ b/src/modules/driver.acpi/main.cpp @@ -0,0 +1,152 @@ +// PhoeniX OS Stub hello module +// Copyright © 2019 Yury Popov a.k.a. PhoeniX + +#include "kernmod.hpp" + +MODDESC(name, "Driver/ACPI"); +MODDESC(version, "1.0"); +MODDESC(description, "Generic ACPI Driver"); +MODDESC(requirements, ""); +MODDESC(developer, "PhoeniX"); + +template +static inline size_t putn(T x, uint8_t base = 10, size_t len = 1) { + char buf[sizeof(T) * 4]; + size_t sz = sizeof(buf) - 1, off = sz; + buf[off] = 0; + while (off >= sz + 1 - len || x > 0) { + uint8_t c = uint8_t(x % base); x /= base; + buf[--off] = (c < 10) ? static_cast('0' + c) : static_cast('a' - 10 + c); + } + puts(buf + off); + return sz - off; +} + +namespace ACPI { + struct RSDP { + static const uint64_t SIG = 0x2052545020445352; // 'RSD PTR ' + uint64_t sig; + uint8_t crc; + char oem[6]; + uint8_t rev; + uintptr_t rsdt:32; + + inline bool _isValid0() const { + if (sig != SIG) return 0; + uint8_t sum = 0; + const uint8_t *buf = reinterpret_cast(this); + for (size_t i = 0; i < sizeof(RSDP); i++) sum += buf[i]; + if (sum != 0) return 0; + return 1; + } + inline bool isValid0() const { + return rev == 0 && _isValid0(); + } + } __attribute__((packed)); + struct RSDPv20 : RSDP { + size_t size:32; + uintptr_t xsdt; + uint8_t extcrc; + uint8_t rsvd[3]; + inline bool isValid2() const { + if (!RSDP::_isValid0()) return 0; + if (rev == 0) return 0; + uint8_t sum = 0; + const uint8_t *buf = reinterpret_cast(this); + for (size_t i = 0; i < sizeof(RSDPv20); i++) sum += buf[i]; + if (sum != 0) return 0; + return 1; + } + } __attribute__((packed)); + struct SDT { + uint32_t sig; + uint32_t size; + uint8_t rev; + uint8_t crc; + char oemid[6]; + char oemtblid[8]; + uint32_t oemrev; + uint32_t crid; + uint32_t crrev; + + inline bool isValid() const { + uint8_t sum = 0; + const uint8_t *buf = reinterpret_cast(this); + for (size_t i = 0; i < size; i++) sum += buf[i]; + return sum == 0; + } + inline size_t data_size() const { + return size - sizeof(SDT); + } + } __attribute__((packed)); + struct RSDT : SDT { + static const uint32_t SIG = 0x54445352; + uint32_t ptrs[]; + inline size_t count() const { + return SDT::data_size() / sizeof(*ptrs); + } + } __attribute__((packed)); + struct XSDT : SDT { + static const uint32_t SIG = 0x54445358; + uint64_t ptrs[]; + inline size_t count() const { + return SDT::data_size() / sizeof(*ptrs); + } + } __attribute__((packed)); + + static void parseDT(const void *addr) { + SDT desc; + kread(&desc, addr, sizeof(desc)); + char path[] = "acpi/table.XXXX"; + path[11] = static_cast((desc.sig >> 0) & 0xFF); + path[12] = static_cast((desc.sig >> 8) & 0xFF); + path[13] = static_cast((desc.sig >> 16) & 0xFF); + path[14] = static_cast((desc.sig >> 24) & 0xFF); + ioprovide(path, addr); + } + static void parseXSDT(const void *addr) { + XSDT desc; + kread(&desc, addr, sizeof(desc)); + if (desc.sig != XSDT::SIG) return; + XSDT *xsdt = reinterpret_cast(__builtin_alloca(desc.size)); + kread(xsdt, addr, desc.size); + if (!xsdt->isValid()) return; + for (size_t i = 0; i < xsdt->count(); i++) { + parseDT(reinterpret_cast(xsdt->ptrs[i])); + } + } + static void parseRSDT(const void *addr) { + RSDT desc; + kread(&desc, addr, sizeof(desc)); + if (desc.sig != RSDT::SIG) return; + RSDT *rsdt = reinterpret_cast(__builtin_alloca(desc.size)); + kread(rsdt, addr, desc.size); + if (!rsdt->isValid()) return; + for (size_t i = 0; i < rsdt->count(); i++) { + parseDT(reinterpret_cast(uintptr_t(rsdt->ptrs[i]))); + } + } + static void parseRSDP(const void *addr) { + RSDPv20 desc; + kread(&desc, addr, sizeof(desc)); + + if (desc.isValid2()) { + parseXSDT(reinterpret_cast(desc.xsdt)); + } else if (desc.isValid0()) { + parseRSDT(reinterpret_cast(desc.rsdt)); + } + } +} // namespace ACPI + +extern "C" { + extern const char __attribute__((weak)) kptr_acpi_rsdp[]; +}; + +void module() { + if (kptr_acpi_rsdp == nullptr) { + puts("No ACPI RSDP\n"); + } else { + ACPI::parseRSDP(kptr_acpi_rsdp); + } + exit(0); +} diff --git a/src/modules/driver.acpi/module.cmake b/src/modules/driver.acpi/module.cmake new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/include/kernmod.hpp b/src/modules/include/kernmod.hpp index 8f40041..67e3c1f 100644 --- a/src/modules/include/kernmod.hpp +++ b/src/modules/include/kernmod.hpp @@ -14,6 +14,8 @@ extern "C" { void puts(const char *); void exit(int); + void kread(void *, const void *, size_t); + void ioprovide(const char *, const void *); // Entry point diff --git a/src/platform/syscall.cpp b/src/platform/syscall.cpp index 6ed22c2..def4a9d 100644 --- a/src/platform/syscall.cpp +++ b/src/platform/syscall.cpp @@ -3,6 +3,7 @@ #include "syscall.hpp" #include "processmanager.hpp" +#include "pagetable.hpp" #include "./syscall_hash.hpp" #include "./syscall_setup.hpp" @@ -28,6 +29,14 @@ static void syscall_exit(int code) { ); } +static void syscall_kread(void *out, const void *kaddr, size_t size) { + Process *process = ProcessManager::getManager()->currentProcess(); + for (size_t p = 0; p < size; p += 0x1000) { + Pagetable::map(reinterpret_cast(uintptr_t(kaddr) + p)); + } + process->writeData(uintptr_t(out), kaddr, size); +} + static void syscall_ioprovide(const char *path, const void *ptr) { Process *process = ProcessManager::getManager()->currentProcess(); char *str = process->readString(uintptr_t(path)); @@ -46,6 +55,7 @@ static const struct { } PACKED syscall_map[] = { SYSCALL_ENT(puts), SYSCALL_ENT(exit), + SYSCALL_ENT(kread), SYSCALL_ENT(ioprovide), {0, nullptr} }; diff --git a/src/process/process.cpp b/src/process/process.cpp index 9458c2f..c4dac28 100644 --- a/src/process/process.cpp +++ b/src/process/process.cpp @@ -5,6 +5,7 @@ #include "processmanager.hpp" #include "syscall.hpp" +#include "acpi.hpp" using PTE = Pagetable::Entry; @@ -159,6 +160,10 @@ struct SyscallEntry { explicit SyscallEntry(uint64_t idx) : syscall_id(idx) {} } PACKED; uintptr_t Process::linkLibrary(const char* funcname) { + if (klib::strcmp(funcname, "kptr_acpi_rsdp") == 0) { + return uintptr_t(ACPI::getController()->getRSDPAddr()); + } + uintptr_t ptr = getSymbolByName(funcname); if (ptr != 0) return ptr;