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,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "AmlNamespace.hpp"
|
||||
#include <CppLib/Spinlock.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Hal {
|
||||
@@ -105,6 +106,24 @@ namespace Hal {
|
||||
static constexpr int MaxCallDepth = 16;
|
||||
static constexpr int MaxLoopIterations = 1024;
|
||||
|
||||
// Backstop cap on evaluation nesting. This counter is shared by
|
||||
// expression evaluation AND block execution, and block nesting is
|
||||
// legitimately deep -- every If/Else/While body is another level, so a
|
||||
// long firmware method reaches well past a handful. The real protection
|
||||
// against running off the stack is HaveStackHeadroom(), which measures
|
||||
// actual usage; this only catches a decode that recurses without
|
||||
// consuming input.
|
||||
static constexpr int MaxExprDepth = 48;
|
||||
|
||||
// How much stack the interpreter may consume before it gives up. Note
|
||||
// this is an ALLOWANCE, not a reserve: frames here are expensive (a
|
||||
// name-resolving EvalTerm frame carries a 256-byte path buffer plus
|
||||
// 272-byte Object temporaries, so ~800 bytes each), and a real
|
||||
// firmware _BIF nests far enough to need tens of them. Sized against
|
||||
// Sched::StackPages -- keep well under it, since the syscall path below
|
||||
// has already spent some of that stack.
|
||||
static constexpr uint64_t StackBudget = 32768;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
// Interpreter
|
||||
@@ -138,6 +157,31 @@ namespace Hal {
|
||||
// Check if the interpreter has been initialized
|
||||
bool IsInitialized() const { return m_initialized; }
|
||||
|
||||
// Log every opcode executed, with its offset, for the next
|
||||
// `budget` opcodes. The only way to see where a method that runs to
|
||||
// completion without returning a value actually goes.
|
||||
void SetTrace(int budget) { m_traceBudget = budget; }
|
||||
|
||||
// ============================================================================
|
||||
|
||||
// Packages
|
||||
|
||||
// ============================================================================
|
||||
// Read one element of a Package object. Works for both a package
|
||||
// whose elements were computed at run time (materialized in the
|
||||
// package store) and one that is still just the constant AML bytes
|
||||
// it was declared with. Returns false when the object is not a
|
||||
// package or the index is out of range.
|
||||
bool GetPackageElement(const Object& package, int index, Object& result);
|
||||
|
||||
// Number of elements a Package declares.
|
||||
int GetPackageCount(const Object& package);
|
||||
|
||||
// Give a package stored in a namespace node real per-element
|
||||
// storage so Index() can be written through. Returns the store
|
||||
// index, or -1 if the node does not hold a package.
|
||||
int32_t MaterializeNodePackage(int32_t nodeIndex);
|
||||
|
||||
private:
|
||||
// ============================================================================
|
||||
// Parsing (table load)
|
||||
@@ -158,8 +202,17 @@ namespace Hal {
|
||||
// ============================================================================
|
||||
// Read a NameString from AML and produce an absolute path.
|
||||
// Advances *pos past the name.
|
||||
// Produces the absolute path (rebased onto scopeNode for a
|
||||
// relative name). outRelative, when given, receives the name as it
|
||||
// actually appeared in the AML, and *outSearchable says whether the
|
||||
// ACPI search rule applies to it -- true only when the name carried
|
||||
// no root or parent prefix. Resolution must fall back to
|
||||
// Namespace::SearchUpward() in that case: the absolute path is a
|
||||
// guess at one scope, and the object usually lives in a parent.
|
||||
int ReadNameString(const uint8_t* aml, uint32_t* pos, int32_t scopeNode,
|
||||
char* outPath, int maxLen);
|
||||
char* outPath, int maxLen,
|
||||
char* outRelative = nullptr, int relLen = 0,
|
||||
bool* outSearchable = nullptr);
|
||||
|
||||
// Read a single 4-char NameSeg from AML. Advances *pos.
|
||||
void ReadNameSeg(const uint8_t* aml, uint32_t* pos, char* outSeg);
|
||||
@@ -170,6 +223,13 @@ namespace Hal {
|
||||
|
||||
// ============================================================================
|
||||
uint32_t DecodePkgLength(const uint8_t* aml, uint32_t* pos);
|
||||
|
||||
// Decode one constant package element out of raw AML bytes and
|
||||
// advance *pos past it. Non-constant elements (name references,
|
||||
// locals) decode to integer 0, which is what they were worth
|
||||
// before the package store existed.
|
||||
bool DecodeConstElement(const uint8_t* data, uint32_t length,
|
||||
uint32_t* pos, Object& out);
|
||||
uint64_t DecodeInteger(const uint8_t* aml, uint32_t* pos);
|
||||
|
||||
// ============================================================================
|
||||
@@ -187,7 +247,16 @@ namespace Hal {
|
||||
Object ReturnValue;
|
||||
bool Returned;
|
||||
bool Broken;
|
||||
int Depth;
|
||||
int Depth; // method-call nesting
|
||||
int ExprDepth; // expression/block nesting
|
||||
};
|
||||
|
||||
// Increments a depth counter for the duration of a scope; pairs
|
||||
// with the MaxExprDepth check at each recursive entry point.
|
||||
struct DepthGuard {
|
||||
int& Value;
|
||||
explicit DepthGuard(int& v) : Value(v) { Value++; }
|
||||
~DepthGuard() { Value--; }
|
||||
};
|
||||
|
||||
bool ExecuteBlock(ExecContext& ctx, uint32_t offset, uint32_t endOffset);
|
||||
@@ -199,14 +268,19 @@ namespace Hal {
|
||||
// Evaluate a "SuperName" target for Store operations.
|
||||
// Returns the node index for named targets, or handles locals/args.
|
||||
// If isLocal/isArg is set, localIdx/argIdx contains the index.
|
||||
// A target may also be Index(package, n), which names a package
|
||||
// element rather than a node, local or arg. pkgStore/pkgElement
|
||||
// carry that case (pkgStore > 0 when it applies).
|
||||
bool EvalTarget(ExecContext& ctx, uint32_t* pos,
|
||||
int32_t& nodeIndex, bool& isLocal, int& localIdx,
|
||||
bool& isArg, int& argIdx);
|
||||
bool& isArg, int& argIdx,
|
||||
int32_t& pkgStore, int& pkgElement);
|
||||
|
||||
// Store a value to a target (node, local, or arg).
|
||||
void StoreToTarget(ExecContext& ctx, const Object& value,
|
||||
int32_t nodeIndex, bool isLocal, int localIdx,
|
||||
bool isArg, int argIdx);
|
||||
bool isArg, int argIdx,
|
||||
int32_t pkgStore = -1, int pkgElement = 0);
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -221,10 +295,32 @@ namespace Hal {
|
||||
// State
|
||||
|
||||
// ============================================================================
|
||||
// ExecContext is ~4.4 KB (sixteen Objects, each carrying a
|
||||
// 256-byte buffer inline). One per nested method call on a 16 KiB
|
||||
// kernel stack overflows after three levels, so they come from a
|
||||
// pool instead. The pool is only safe because evaluation is
|
||||
// serialized -- see m_evalLock.
|
||||
// Stack-exhaustion check; `frame` is the address of a local in
|
||||
// the calling frame.
|
||||
bool HaveStackHeadroom(const void* frame) const;
|
||||
|
||||
// One-shot warning when the nesting backstop trips.
|
||||
static void ReportDepthLimit();
|
||||
|
||||
ExecContext* AcquireContext();
|
||||
void ReleaseContext();
|
||||
|
||||
Namespace m_ns;
|
||||
const uint8_t* m_dsdt;
|
||||
uint32_t m_dsdtLength;
|
||||
bool m_initialized;
|
||||
|
||||
ExecContext* m_ctxPool; // MaxCallDepth + 1 entries, heap
|
||||
int m_ctxInUse;
|
||||
int m_evalNesting; // top-level evaluations in progress
|
||||
uint64_t m_stackFloor; // stack address the interpreter stops at
|
||||
int m_traceBudget; // opcodes left to log, 0 = off
|
||||
kcp::Mutex m_evalLock;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in new issue
Block a user