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

+64 -6
View File
@@ -55,10 +55,15 @@ namespace Hal {
// ============================================================================
static constexpr int MaxNameSegLen = 4;
static constexpr int MaxPathDepth = 16;
static constexpr int MaxChildren = 64;
// Children are held in a heap array that grows on demand, starting at
// this many entries. A fixed ceiling here is not survivable: an EC or
// GPE scope in a modern laptop DSDT carries well over a hundred named
// objects, and dropping the overflow loses whole devices (the battery
// among them) with no way to tell from the outside.
static constexpr int InitialChildren = 8;
static constexpr int MaxStringLen = 64;
static constexpr int MaxBufferLen = 256;
static constexpr int MaxPackageElements = 16;
static constexpr int MaxPackageElements = 32;
static constexpr int MaxMethodArgs = 7;
static constexpr int MaxMethodLocals = 8;
@@ -76,6 +81,14 @@ namespace Hal {
struct Object {
ObjectType Type = ObjectType::None;
// Packages keep their raw AML bytes in Buffer (constant elements can
// be decoded straight from there), but a package whose elements are
// computed or written through Index() needs real per-element
// storage. PkgIndex names that storage once it is materialized;
// -1 means "not materialized yet". It lives outside the union so a
// package can carry both representations at once.
int32_t PkgIndex = -1;
union {
uint64_t Integer;
@@ -116,7 +129,36 @@ namespace Hal {
} Processor;
};
Object() : Type(ObjectType::None), Integer(0) {}
Object() : Type(ObjectType::None), PkgIndex(-1), Integer(0) {}
};
// ============================================================================
// Package element store
// ============================================================================
// Element arrays for materialized packages, kept outside Object so the
// tagged union stays small. Entries are split in two: a persistent
// region for packages declared with Name() (materialized once and kept
// for the life of the namespace) and a transient ring for packages
// built inside a method, which is rewound at each top-level evaluation
// so repeated calls -- polling _BST, say -- cannot exhaust it.
namespace PackageStore {
static constexpr int MaxPersistent = 32;
static constexpr int MaxTransient = 32;
// Allocate an element array of `count` objects. Returns -1 when the
// store is full or the count is out of range.
int32_t AllocPersistent(int count);
int32_t AllocTransient(int count);
// Rewind the transient ring. Called once per top-level evaluation.
void ResetTransient();
// Element access. Returns nullptr for an unknown entry or an
// out-of-range element.
Object* Element(int32_t index, int element);
int Count(int32_t index);
};
// ============================================================================
@@ -129,16 +171,19 @@ namespace Hal {
char Name[MaxNameSegLen + 1]; // null-terminated 4-char segment
Object Obj;
int32_t ParentIndex; // -1 for root
int32_t ChildIndices[MaxChildren];
int32_t* ChildIndices; // heap array, ChildCapacity long
int32_t ChildCount;
int32_t ChildCapacity;
// Only ever called on a freshly allocated (zeroed) node, so there is
// no child array to release here.
void Clear() {
Name[0] = 0;
Obj = Object{};
ParentIndex = -1;
ChildIndices = nullptr;
ChildCount = 0;
for (int i = 0; i < MaxChildren; i++)
ChildIndices[i] = -1;
ChildCapacity = 0;
}
};
@@ -166,6 +211,14 @@ namespace Hal {
// 3. Root scope
int32_t ResolveName(const char* name, int32_t scopeNodeIndex) const;
// The ACPI name search rule: for a name written WITHOUT a root or
// parent prefix, search the current scope for its first segment,
// then each parent scope up to the root, and descend the remaining
// segments from wherever it matched. `relative` is the name as it
// appeared in the AML ("PBIF", "BAT0.PBIF"), never a path already
// rebased onto a scope. Returns -1 if no scope contains it.
int32_t SearchUpward(const char* relative, int32_t scopeNodeIndex) const;
// Get a node by index.
NamespaceNode* GetNode(int32_t index);
const NamespaceNode* GetNode(int32_t index) const;
@@ -217,6 +270,11 @@ namespace Hal {
private:
int32_t AllocNode();
bool AllocChunk();
// Append a child index to a parent, growing its array as needed.
// Returns false only when the heap is exhausted.
bool AppendChild(NamespaceNode* parent, int32_t child);
void EnsureRoot();
int32_t FindChildByName(int32_t parentIndex, const char* seg) const;