feat: add kernel ACPI support for querying battery percentage, add battery indicator to desktop, move log state to 0:/state directory

This commit is contained in:
daniel committed 2026-09-11 07:11:48 +02:00
1 parent 0a18b2cf2d
commit e641500b40
34 files changed
+2461 -100

No files matched your search

+196 -6
View File
@@ -7,10 +7,114 @@
#include "AmlNamespace.hpp"
#include <Libraries/Memory.hpp>
#include <Memory/Heap.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
using namespace Kt;
namespace Hal {
namespace AML {
// ============================================================================
// Package element store
// ============================================================================
namespace PackageStore {
struct Entry {
Object* Elements;
int Count;
};
static Entry s_persistent[MaxPersistent];
static Entry s_transient[MaxTransient];
static int s_persistentUsed = 0;
static int s_transientNext = 0;
// Indices handed out are 1-based so that a zeroed Object (nodes are
// memset before Clear() runs, and callers zero-init freely) never
// looks like a reference to entry 0.
static constexpr int32_t TransientBase = MaxPersistent;
static Object* AllocElements(int count) {
auto* mem = (Object*)Memory::g_heap->Request(sizeof(Object) * count);
if (!mem) return nullptr;
for (int i = 0; i < count; i++)
mem[i] = Object{};
return mem;
}
int32_t AllocPersistent(int count) {
if (count <= 0 || count > MaxPackageElements) return -1;
if (s_persistentUsed >= MaxPersistent) return -1;
Entry& e = s_persistent[s_persistentUsed];
e.Elements = AllocElements(count);
if (!e.Elements) return -1;
e.Count = count;
return (int32_t)(s_persistentUsed++) + 1;
}
int32_t AllocTransient(int count) {
if (count <= 0 || count > MaxPackageElements) return -1;
int slot = s_transientNext;
if (slot >= MaxTransient) {
// The ring is only rewound between top-level evaluations, so
// a method that builds more packages than this reuses the
// oldest slots rather than failing outright.
slot = 0;
s_transientNext = 0;
}
s_transientNext++;
Entry& e = s_transient[slot];
// Element arrays are sized on first use and reused afterwards;
// a larger request reallocates.
if (e.Elements == nullptr || e.Count < count) {
Object* mem = AllocElements(count);
if (!mem) return -1;
if (e.Elements) Memory::g_heap->Free(e.Elements);
e.Elements = mem;
} else {
for (int i = 0; i < count; i++)
e.Elements[i] = Object{};
}
e.Count = count;
return TransientBase + slot + 1;
}
void ResetTransient() {
s_transientNext = 0;
}
static Entry* Lookup(int32_t index) {
if (index <= 0) return nullptr;
int32_t i = index - 1;
if (i < MaxPersistent) {
if (i >= s_persistentUsed) return nullptr;
return s_persistent[i].Elements ? &s_persistent[i] : nullptr;
}
i -= TransientBase;
if (i < 0 || i >= MaxTransient) return nullptr;
return s_transient[i].Elements ? &s_transient[i] : nullptr;
}
Object* Element(int32_t index, int element) {
Entry* e = Lookup(index);
if (!e || element < 0 || element >= e->Count) return nullptr;
return &e->Elements[element];
}
int Count(int32_t index) {
Entry* e = Lookup(index);
return e ? e->Count : 0;
}
};
Namespace::Namespace() : m_chunkCount(0), m_nodeCount(0) {
for (int i = 0; i < MaxChunks; i++)
m_chunks[i] = nullptr;
@@ -30,7 +134,17 @@ namespace Hal {
}
bool Namespace::AllocChunk() {
if (m_chunkCount >= MaxChunks) return false;
if (m_chunkCount >= MaxChunks) {
static bool warned = false;
if (!warned) {
warned = true;
KernelLogStream(WARNING, "AML")
<< "Namespace node pool full at " << base::dec
<< (uint64_t)(MaxChunks * NodesPerChunk)
<< " nodes; part of the namespace will be missing";
}
return false;
}
auto* chunk = (NamespaceNode*)Memory::g_heap->Request(
sizeof(NamespaceNode) * NodesPerChunk);
@@ -45,6 +159,41 @@ namespace Hal {
return true;
}
bool Namespace::AppendChild(NamespaceNode* parent, int32_t child) {
if (parent->ChildCount >= parent->ChildCapacity) {
int32_t newCap = parent->ChildCapacity ? parent->ChildCapacity * 2
: InitialChildren;
auto* grown = (int32_t*)Memory::g_heap->Request(sizeof(int32_t) * newCap);
if (!grown) {
// Losing a child silently costs whole devices, so say it
// once rather than leaving a hole nobody can see.
static bool warned = false;
if (!warned) {
warned = true;
KernelLogStream(WARNING, "AML")
<< "Out of heap growing a namespace node's child list;"
<< " part of the namespace will be missing";
}
return false;
}
for (int32_t i = 0; i < parent->ChildCount; i++)
grown[i] = parent->ChildIndices[i];
for (int32_t i = parent->ChildCount; i < newCap; i++)
grown[i] = -1;
if (parent->ChildIndices)
Memory::g_heap->Free(parent->ChildIndices);
parent->ChildIndices = grown;
parent->ChildCapacity = newCap;
}
parent->ChildIndices[parent->ChildCount++] = child;
return true;
}
int32_t Namespace::AllocNode() {
// Check if we need a new chunk
int32_t capacity = m_chunkCount * NodesPerChunk;
@@ -165,11 +314,7 @@ namespace Hal {
// Add to parent's children
auto* parent = GetNode(current);
if (!parent) return -1;
if (parent->ChildCount < MaxChildren) {
parent->ChildIndices[parent->ChildCount++] = child;
} else {
return -1; // too many children
}
if (!AppendChild(parent, child)) return -1;
}
current = child;
}
@@ -188,6 +333,51 @@ namespace Hal {
return current;
}
int32_t Namespace::SearchUpward(const char* relative, int32_t scopeNodeIndex) const {
char segments[MaxPathDepth][MaxNameSegLen + 1];
int segCount = 0;
// Split on '.', padding each segment to four characters the way
// node names are stored.
int i = 0;
while (relative[i] && segCount < MaxPathDepth) {
char seg[MaxNameSegLen + 1];
int n = 0;
while (relative[i] && relative[i] != '.' && n < MaxNameSegLen)
seg[n++] = relative[i++];
seg[n] = '\0';
while (relative[i] && relative[i] != '.') i++; // overlong segment
if (relative[i] == '.') i++;
PadSegment(seg, segments[segCount]);
segCount++;
}
if (segCount == 0) return -1;
// Walk up from the current scope looking for the first segment.
int32_t scope = scopeNodeIndex;
while (scope >= 0) {
int32_t found = FindChildByName(scope, segments[0]);
if (found >= 0) {
// Descend the rest. A scope that matches the first segment
// but not the remainder does not win -- keep walking up.
int32_t cur = found;
bool ok = true;
for (int k = 1; k < segCount; k++) {
cur = FindChildByName(cur, segments[k]);
if (cur < 0) { ok = false; break; }
}
if (ok) return cur;
}
auto* node = GetNode(scope);
scope = node ? node->ParentIndex : -1;
}
return -1;
}
int32_t Namespace::ResolveName(const char* name, int32_t scopeNodeIndex) const {
// If it starts with '\', it's absolute
if (name[0] == '\\')