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:
1 parent
0a18b2cf2d
commit
e641500b40
34 files changed
+2461
-100
No files matched your search
@@ -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] == '\\')
|
||||
|
||||
Reference in new issue
Block a user