2#include "pedigree/kernel/BootstrapInfo.h"
3#include "pedigree/kernel/LockGuard.h"
4#include "pedigree/kernel/Log.h"
5#include "pedigree/kernel/Spinlock.h"
6#include "pedigree/kernel/machine/Device.h"
7#include "pedigree/kernel/machine/Pci.h"
8#include "pedigree/kernel/panic.h"
9#include "pedigree/kernel/process/Mutex.h"
10#include "pedigree/kernel/process/Semaphore.h"
11#include "pedigree/kernel/processor/MemoryRegion.h"
12#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
13#include "pedigree/kernel/processor/Processor.h"
14#include "pedigree/kernel/processor/VirtualAddressSpace.h"
15#include "pedigree/kernel/time/Time.h"
16#include "pedigree/kernel/utilities/new"
18#include <uacpi/kernel_api.h>
23 void* address =
nullptr;
25 Mapping* next =
nullptr;
28Mapping* mappings =
nullptr;
35bool wait(
Semaphore* semaphore, uint16_t milliseconds) {
39 if (milliseconds == 0xffff) {
45uacpi_status status(
bool success) {
46 return success ? UACPI_STATUS_OK : UACPI_STATUS_INTERNAL_ERROR;
50uacpi_status readPort(uacpi_handle handle,
size_t offset, T* value) {
51 const auto* range =
static_cast<const PortRange*
>(handle);
52 if (!range || !value || offset >= range->bytes ||
sizeof(T) > range->bytes - offset) {
53 return UACPI_STATUS_INVALID_ARGUMENT;
56 const uint16_t port = range->base + offset;
57 if constexpr (
sizeof(T) == 1) {
58 asm volatile(
"inb %1, %0" :
"=a"(*value) :
"Nd"(port));
59 }
else if constexpr (
sizeof(T) == 2) {
60 asm volatile(
"inw %1, %0" :
"=a"(*value) :
"Nd"(port));
62 asm volatile(
"inl %1, %0" :
"=a"(*value) :
"Nd"(port));
64 return UACPI_STATUS_OK;
66 return UACPI_STATUS_UNIMPLEMENTED;
71uacpi_status writePort(uacpi_handle handle,
size_t offset, T value) {
72 const auto* range =
static_cast<const PortRange*
>(handle);
73 if (!range || offset >= range->bytes ||
sizeof(T) > range->bytes - offset) {
74 return UACPI_STATUS_INVALID_ARGUMENT;
77 const uint16_t port = range->base + offset;
78 if constexpr (
sizeof(T) == 1) {
79 asm volatile(
"outb %0, %1" : :
"a"(value),
"Nd"(port));
80 }
else if constexpr (
sizeof(T) == 2) {
81 asm volatile(
"outw %0, %1" : :
"a"(value),
"Nd"(port));
83 asm volatile(
"outl %0, %1" : :
"a"(value),
"Nd"(port));
85 return UACPI_STATUS_OK;
87 return UACPI_STATUS_UNIMPLEMENTED;
92uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr* result) {
93 const uintptr_t address = g_pBootstrapInfo ? g_pBootstrapInfo->getAcpiRsdp() : 0;
94 if (!address || !result) {
95 return UACPI_STATUS_NOT_FOUND;
100 constexpr uintptr_t DirectMapBase = 0xffff800000000000ULL;
101 constexpr uintptr_t DirectMapEnd = 0xffffc00000000000ULL;
102 if (address >= DirectMapBase && address < DirectMapEnd) {
103 *result = address - DirectMapBase;
104 return UACPI_STATUS_OK;
108 physical_uintptr_t physical = 0;
111 reinterpret_cast<void*
>(address & ~(pageSize - 1)), physical, flags)) {
112 return UACPI_STATUS_MAPPING_FAILED;
114 *result = physical + (address & (pageSize - 1));
115 return UACPI_STATUS_OK;
118void* uacpi_kernel_map(uacpi_phys_addr address, uacpi_size bytes) {
120 const size_t offset = address & (pageSize - 1);
121 if (!bytes || address > ~physical_uintptr_t{0} || bytes - 1 > ~physical_uintptr_t{0} - address ||
122 bytes > ~size_t{0} - offset - (pageSize - 1)) {
123 return UACPI_MAP_FAILED;
125 auto* mapping =
new Mapping;
128 if (g_pBootstrapInfo) {
129 for (
void* entry = g_pBootstrapInfo->getMemoryMap(); entry;
130 entry = g_pBootstrapInfo->nextMemoryMapEntry(entry)) {
131 const uint64_t base = g_pBootstrapInfo->getMemoryMapEntryAddress(entry);
132 const uint64_t length = g_pBootstrapInfo->getMemoryMapEntryLength(entry);
133 const uint32_t type = g_pBootstrapInfo->getMemoryMapEntryType(entry);
134 if ((type == 1 || type == 3 || type == 4) && address >= base && address - base < length &&
135 bytes <= length - (address - base)) {
143 mapping->region, (bytes + offset + pageSize - 1) / pageSize,
146 flags, address & ~(physical_uintptr_t(pageSize) - 1))) {
148 return UACPI_MAP_FAILED;
150 mapping->address =
static_cast<uint8_t*
>(mapping->region.virtualAddress()) + offset;
151 mapping->bytes = bytes;
153 mapping->next = mappings;
155 return mapping->address;
158void uacpi_kernel_unmap(
void* address, uacpi_size bytes) {
159 Mapping* found =
nullptr;
162 for (Mapping** cursor = &mappings; *cursor; cursor = &(*cursor)->next) {
163 if ((*cursor)->address == address && (*cursor)->bytes == bytes) {
165 *cursor = found->next;
171 panic(
"ACPI: invalid firmware mapping retirement");
176void uacpi_kernel_log(uacpi_log_level level,
const uacpi_char*
message) {
177 if (level <= UACPI_LOG_WARN) {
184uacpi_status uacpi_kernel_pci_device_open(uacpi_pci_address address, uacpi_handle* result) {
185 if (!result || address.segment || address.device >= 32 || address.function >= 8) {
186 return UACPI_STATUS_NOT_FOUND;
188 auto* device =
new Device;
189 device->setPciPosition(address.bus, address.device, address.function);
191 return UACPI_STATUS_OK;
193void uacpi_kernel_pci_device_close(uacpi_handle device) {
194 delete static_cast<Device*
>(device);
197uacpi_status uacpi_kernel_pci_read8(uacpi_handle device, uacpi_size offset, uacpi_u8* value) {
198 return status(device && value && offset < 4096 &&
199 PciBus::instance().readConfig8(
static_cast<Device*
>(device), offset, *value));
201uacpi_status uacpi_kernel_pci_read16(uacpi_handle device, uacpi_size offset, uacpi_u16* value) {
202 return status(device && value && offset < 4096 &&
203 PciBus::instance().readConfig16(
static_cast<Device*
>(device), offset, *value));
205uacpi_status uacpi_kernel_pci_read32(uacpi_handle device, uacpi_size offset, uacpi_u32* value) {
206 return status(device && value && offset < 4096 &&
207 PciBus::instance().readConfig32(
static_cast<Device*
>(device), offset, *value));
209uacpi_status uacpi_kernel_pci_write8(uacpi_handle device, uacpi_size offset, uacpi_u8 value) {
210 return status(device && offset < 4096 &&
211 PciBus::instance().writeConfig8(
static_cast<Device*
>(device), offset, value));
213uacpi_status uacpi_kernel_pci_write16(uacpi_handle device, uacpi_size offset, uacpi_u16 value) {
214 return status(device && offset < 4096 &&
215 PciBus::instance().writeConfig16(
static_cast<Device*
>(device), offset, value));
217uacpi_status uacpi_kernel_pci_write32(uacpi_handle device, uacpi_size offset, uacpi_u32 value) {
218 return status(device && offset < 4096 &&
219 PciBus::instance().writeConfig32(
static_cast<Device*
>(device), offset, value));
222uacpi_status uacpi_kernel_io_map(uacpi_io_addr base, uacpi_size bytes, uacpi_handle* result) {
223 if (!result || !bytes || base > 0xffff || bytes > 0x10000 - base) {
224 return UACPI_STATUS_INVALID_ARGUMENT;
227 *result =
new PortRange{
static_cast<uint16_t
>(base), bytes};
228 return UACPI_STATUS_OK;
230 return UACPI_STATUS_UNIMPLEMENTED;
233void uacpi_kernel_io_unmap(uacpi_handle handle) {
234 delete static_cast<PortRange*
>(handle);
236uacpi_status uacpi_kernel_io_read8(uacpi_handle h, uacpi_size o, uacpi_u8* v) {
237 return readPort(h, o, v);
239uacpi_status uacpi_kernel_io_read16(uacpi_handle h, uacpi_size o, uacpi_u16* v) {
240 return readPort(h, o, v);
242uacpi_status uacpi_kernel_io_read32(uacpi_handle h, uacpi_size o, uacpi_u32* v) {
243 return readPort(h, o, v);
245uacpi_status uacpi_kernel_io_write8(uacpi_handle h, uacpi_size o, uacpi_u8 v) {
246 return writePort(h, o, v);
248uacpi_status uacpi_kernel_io_write16(uacpi_handle h, uacpi_size o, uacpi_u16 v) {
249 return writePort(h, o, v);
251uacpi_status uacpi_kernel_io_write32(uacpi_handle h, uacpi_size o, uacpi_u32 v) {
252 return writePort(h, o, v);
255void* uacpi_kernel_alloc(uacpi_size bytes) {
256 return new uint8_t[bytes];
258void uacpi_kernel_free(
void* memory) {
259 delete[]
static_cast<uint8_t*
>(memory);
261uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot() {
262 return Time::getTicks();
264void uacpi_kernel_stall(uacpi_u8 microseconds) {
265 const auto deadline = Time::getTicks() + microseconds * Time::Multiplier::Microsecond;
266 while (Time::getTicks() < deadline) {
270void uacpi_kernel_sleep(uacpi_u64 milliseconds) {
271 while (milliseconds) {
272 const auto chunk = milliseconds > 1000 ? 1000 : milliseconds;
273 const auto deadline = Time::getTicks() + chunk * Time::Multiplier::Millisecond;
274 auto now = Time::getTicks();
275 while (now < deadline) {
276 Time::delay(deadline - now);
277 now = Time::getTicks();
279 milliseconds -= chunk;
283uacpi_handle uacpi_kernel_create_mutex() {
286void uacpi_kernel_free_mutex(uacpi_handle handle) {
287 delete static_cast<Mutex*
>(handle);
289uacpi_status uacpi_kernel_acquire_mutex(uacpi_handle handle, uacpi_u16 timeout) {
290 return wait(
static_cast<Mutex*
>(handle), timeout) ? UACPI_STATUS_OK : UACPI_STATUS_TIMEOUT;
292void uacpi_kernel_release_mutex(uacpi_handle handle) {
293 static_cast<Mutex*
>(handle)->release();
295uacpi_handle uacpi_kernel_create_event() {
298void uacpi_kernel_free_event(uacpi_handle handle) {
301uacpi_bool uacpi_kernel_wait_for_event(uacpi_handle handle, uacpi_u16 timeout) {
302 return wait(
static_cast<Semaphore*
>(handle), timeout);
304void uacpi_kernel_signal_event(uacpi_handle handle) {
305 static_cast<Semaphore*
>(handle)->release();
307void uacpi_kernel_reset_event(uacpi_handle handle) {
308 [[maybe_unused]]
const size_t drained =
static_cast<Semaphore*
>(handle)->drainAvailable();
310uacpi_thread_id uacpi_kernel_get_thread_id() {
313uacpi_interrupt_state uacpi_kernel_disable_interrupts() {
318void uacpi_kernel_restore_interrupts(uacpi_interrupt_state state) {
321uacpi_handle uacpi_kernel_create_spinlock() {
324void uacpi_kernel_free_spinlock(uacpi_handle handle) {
325 delete static_cast<Spinlock*
>(handle);
327uacpi_cpu_flags uacpi_kernel_lock_spinlock(uacpi_handle handle) {
328 auto* lock =
static_cast<Spinlock*
>(handle);
330 return lock->interrupts();
332void uacpi_kernel_unlock_spinlock(uacpi_handle handle, uacpi_cpu_flags) {
333 static_cast<Spinlock*
>(handle)->release();
335uacpi_status uacpi_kernel_handle_firmware_request(uacpi_firmware_request* request) {
336 WARNING(
"ACPI: firmware request " <<
Dec << request->type);
337 return request->type == UACPI_FIRMWARE_REQUEST_TYPE_BREAKPOINT ? UACPI_STATUS_OK
338 : UACPI_STATUS_DENIED;
Special memory entity in the kernel's virtual address space.
static const size_t continuous
static PhysicalMemoryManager & instance()
static constexpr size_t getPageSize() PURE
static const size_t force
static const size_t nonRamMemory
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1)=0
static bool getInterrupts()
static ProcessorInformation & information()
static void setInterrupts(bool bEnable)
MUST_USE_RESULT bool acquireForCompletion(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
bool tryAcquire(size_t n=1)
bool acquire(bool recurse=false, bool safe=true)
static const size_t CacheDisable
static const size_t KernelMode
static const size_t Write
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
void EXPORTED_PUBLIC panic(const char *msg) NORETURN