Compare commits

...

2 Commits

Author SHA1 Message Date
Bananymous 135ca8395f Kernel: Implement barebones AML parser
This implements only parsing for AML in qemu. InvokeMethods are not
parsed since number of arguments to Methods is not yet known.

Parsing AML uses multiple kilobytes of stack space, so I increased
boot stack size by a lot :D

I am not sure where my own AML is going, but this is good start if
I decide to implement full ACPI on my own.

This code is very much just ugly macro expansion.

Qemu has 2 DefPackage elements that I am not able to parse. Package
data ends while there should be still multiple elements.
2024-04-07 02:54:02 +03:00
Bananymous e0011d22f2 Kernel: Move ACPI to its own directory and namespace 2024-04-04 15:00:13 +03:00
23 changed files with 2606 additions and 163 deletions

View File

@ -10,7 +10,12 @@ endif()
set(KERNEL_SOURCES
font/prefs.psf.o
kernel/ACPI.cpp
kernel/ACPI/ACPI.cpp
kernel/ACPI/AML.cpp
kernel/ACPI/AML/DataObject.cpp
kernel/ACPI/AML/MiscObject.cpp
kernel/ACPI/AML/NameObject.cpp
kernel/ACPI/AML/TermObject.cpp
kernel/APIC.cpp
kernel/BootInfo.cpp
kernel/CPUID.cpp

View File

@ -54,7 +54,7 @@ bananboot_end:
.section .bss, "aw", @nobits
boot_stack_bottom:
.skip 4096 * 4
.skip 4096 * 64
boot_stack_top:
.global g_kernel_cmdline

View File

@ -1,144 +0,0 @@
#pragma once
#include <BAN/Vector.h>
#include <kernel/Memory/Types.h>
namespace Kernel
{
class ACPI
{
public:
struct GAS
{
uint8_t address_space_id;
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t access_size;
uint64_t address;
} __attribute__((packed));
struct SDTHeader
{
uint8_t signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oemid[6];
uint64_t oem_table_id;
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} __attribute__((packed));
struct FADT : public SDTHeader
{
uint32_t firmware_ctrl;
uint32_t dsdt;
uint8_t __reserved;
uint8_t preferred_pm_profile;
uint16_t sci_int;
uint32_t smi_cmd;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_cnt;
uint32_t pm1a_evt_blk;
uint32_t pm1b_evt_blk;
uint32_t pm1a_cnt_blk;
uint32_t pm1b_cnt_blk;
uint32_t pm2_cnt_blk;
uint32_t pm_tmr_blk;
uint32_t gpe0_blk;
uint32_t gpe1_blk;
uint8_t pm1_evt_len;
uint8_t pm1_cnt_len;
uint8_t pm2_cnt_len;
uint8_t pm_tmr_len;
uint8_t gpe0_blk_len;
uint8_t gpe1_blk_len;
uint8_t gpe1_base;
uint8_t cst_cnt;
uint16_t p_lvl2_lat;
uint16_t p_lvl3_lat;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alrm;
uint8_t mon_alrm;
uint8_t century;
uint16_t iapc_boot_arch;
uint8_t __reserved2;
uint32_t flags;
uint8_t reset_reg[12];
uint8_t reset_value;
uint16_t arm_boot_arch;
uint8_t fadt_minor_version;
uint64_t x_firmware_version;
uint64_t x_dsdt;
uint8_t x_pm1a_evt_blk[12];
uint8_t x_pm1b_evt_blk[12];
uint8_t x_pm1a_cnt_blk[12];
uint8_t x_pm1b_cnt_blk[12];
uint8_t x_pm2_cnt_blk[12];
uint8_t x_pm_tmr_blk[12];
uint8_t x_gpe0_blk[12];
uint8_t x_gpe1_blk[12];
uint8_t sleep_control_reg[12];
uint8_t sleep_status_reg[12];
uint64_t hypervison_vendor_identity;
} __attribute__((packed));
struct HPET : public SDTHeader
{
uint8_t hardware_rev_id;
uint8_t comparator_count : 5;
uint8_t count_size_cap : 1;
uint8_t reserved : 1;
uint8_t legacy_replacement_irq_routing_cable : 1;
uint16_t pci_vendor_id;
GAS base_address;
uint8_t hpet_number;
uint16_t main_counter_minimum_clock_tick;
uint8_t page_protection_and_oem_attribute;
} __attribute__((packed));
public:
static BAN::ErrorOr<void> initialize();
static ACPI& get();
const SDTHeader* get_header(BAN::StringView signature, uint32_t index);
private:
ACPI() = default;
BAN::ErrorOr<void> initialize_impl();
private:
paddr_t m_header_table_paddr = 0;
vaddr_t m_header_table_vaddr = 0;
uint32_t m_entry_size = 0;
struct MappedPage
{
Kernel::paddr_t paddr;
Kernel::vaddr_t vaddr;
SDTHeader* as_header() { return (SDTHeader*)vaddr; }
};
BAN::Vector<MappedPage> m_mapped_headers;
};
}
namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const Kernel::ACPI::SDTHeader& header, const ValueFormat& format)
{
putc(header.signature[0]);
putc(header.signature[1]);
putc(header.signature[2]);
putc(header.signature[3]);
}
}

View File

@ -0,0 +1,37 @@
#pragma once
#include <BAN/Vector.h>
#include <kernel/ACPI/Headers.h>
#include <kernel/Memory/Types.h>
namespace Kernel::ACPI
{
class ACPI
{
public:
static BAN::ErrorOr<void> initialize();
static ACPI& get();
const SDTHeader* get_header(BAN::StringView signature, uint32_t index);
private:
ACPI() = default;
BAN::ErrorOr<void> initialize_impl();
private:
paddr_t m_header_table_paddr = 0;
vaddr_t m_header_table_vaddr = 0;
uint32_t m_entry_size = 0;
struct MappedPage
{
Kernel::paddr_t paddr;
Kernel::vaddr_t vaddr;
SDTHeader* as_header() { return (SDTHeader*)vaddr; }
};
BAN::Vector<MappedPage> m_mapped_headers;
};
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <kernel/ACPI/Headers.h>
namespace Kernel::ACPI
{
class AMLParser
{
public:
~AMLParser();
static AMLParser parse_table(const SDTHeader& header);
private:
AMLParser();
};
}

View File

@ -0,0 +1,265 @@
#pragma once
#include <BAN/Formatter.h>
#include <BAN/Vector.h>
#include <BAN/StringView.h>
#include <kernel/Debug.h>
#define DUMP_AML 0
#if DUMP_AML
#define AML_DEBUG_CONCAT_IMPL(x, y) x##y
#define AML_DEBUG_CONCAT(x, y) AML_DEBUG_CONCAT_IMPL(x, y)
#define AML_DEBUG_INDENT_SCOPE() Kernel::ACPI::AML::Indenter AML_DEBUG_CONCAT(indenter, __COUNTER__)
#define __AML_DEBUG_PRINT_INDENT() \
do { \
BAN::Formatter::print(Debug::putchar, "{}:{3} ", __BASE_FILE__, __LINE__); \
for (size_t i = 1; i < AML::g_depth; i++) \
BAN::Formatter::print(Debug::putchar, ""); \
if (AML::g_depth > 0) \
BAN::Formatter::print(Debug::putchar, "├─"); \
} while (0)
#define AML_DEBUG_PRINT_FN() \
__AML_DEBUG_PRINT_INDENT(); \
AML_DEBUG_INDENT_SCOPE(); \
BAN::Formatter::println(Debug::putchar, "{}", AML::get_class_name(__PRETTY_FUNCTION__))
#define AML_DEBUG_PRINT(...) \
do { \
__AML_DEBUG_PRINT_INDENT(); \
BAN::Formatter::println(Debug::putchar, __VA_ARGS__); \
} while (0)
#else
#define AML_DEBUG_PRINT_FN()
#define AML_DEBUG_PRINT(...)
#define AML_DEBUG_INDENT_SCOPE()
#define __AML_DEBUG_PRINT_INDENT()
#endif
#define AML_DEBUG_TODO(...) \
do { \
__AML_DEBUG_PRINT_INDENT(); \
BAN::Formatter::print(Debug::putchar, "\e[33mTODO: "); \
BAN::Formatter::print(Debug::putchar, __VA_ARGS__); \
BAN::Formatter::println(Debug::putchar, "\e[m"); \
} while (0)
#define AML_DEBUG_ERROR(...) \
do { \
__AML_DEBUG_PRINT_INDENT(); \
BAN::Formatter::print(Debug::putchar, "\e[31m"); \
BAN::Formatter::print(Debug::putchar, __VA_ARGS__); \
BAN::Formatter::println(Debug::putchar, "\e[m"); \
} while (0)
#define AML_DEBUG_CANNOT_PARSE(TYPE, SPAN) \
do { \
__AML_DEBUG_PRINT_INDENT(); \
BAN::Formatter::print(Debug::putchar, "\e[31mCannot parse " TYPE " (span {} bytes", SPAN.size()); \
if (SPAN.size() > 0) \
BAN::Formatter::print(Debug::putchar, ", {2H}", SPAN[0]); \
if (SPAN.size() > 1) \
BAN::Formatter::print(Debug::putchar, " {2H}", SPAN[1]); \
BAN::Formatter::println(Debug::putchar, ")\e[m"); \
} while (0)
namespace Kernel::ACPI::AML
{
extern size_t g_depth;
struct Indenter
{
Indenter() { g_depth++; }
~Indenter() { g_depth--; }
};
static BAN::StringView get_class_name(BAN::StringView pretty_function)
{
return MUST(MUST(pretty_function.split(' '))[2].split(':'))[3];
}
}
#define GEN_PARSE_CASE_TODO(NAME) \
case AML::Byte::NAME: \
AML_DEBUG_TODO(#NAME); \
return {};
#define AML_TRY_PARSE_PACKAGE(NAME) \
auto opt_##NAME = AML::PkgLength::parse_package(span); \
if (!opt_##NAME.has_value()) \
return {}; \
auto NAME = opt_##NAME.release_value();
#define AML_TRY_PARSE(NAME, TYPE, SPAN) \
if (!TYPE::can_parse(SPAN)) \
{ \
AML_DEBUG_CANNOT_PARSE(#TYPE, SPAN); \
return {}; \
} \
auto NAME = TYPE::parse(SPAN); \
if (!NAME.has_value()) \
return {}
#define AML_TRY_PARSE_IF_CAN(TYPE) \
if (TYPE::can_parse(span)) \
{ \
if (auto obj = TYPE::parse(span); obj.has_value()) \
return obj.release_value(); \
return {}; \
}
namespace Kernel::ACPI::AML {
enum class Byte : uint8_t
{
ExtOpPrefix = 0x5B,
// NamePath
DualNamePrefix = 0x2E,
MultiNamePrefix = 0x2F,
// NameSpaceModifierObj
AliasOp = 0x06,
NameOp = 0x08,
ScopeOp = 0x10,
// ConstObj
ZeroOp = 0x00,
OneOp = 0x01,
OnesOp = 0xFF,
// ComputationalData
BytePrefix = 0x0A,
WordPrefix = 0x0B,
DWordPrefix = 0x0C,
StringPrefix = 0x0D,
QWordPrefix = 0x0E,
BufferOp = 0x11,
ExtRevisionOp = 0x30,
// DataObject
PackageOp = 0x12,
VarPackageOp = 0x13,
// NamedObj
ExternalOp = 0x15,
CreateDWordFieldOp = 0x8A,
CreateWordFieldOp = 0x8B,
CreateByteFieldOp = 0x8C,
CreateBitFieldOp = 0x8D,
CreateQWordFieldOp = 0x8F,
ExtCreateFieldOp = 0x13,
ExtOpRegionOp = 0x80,
ExtProcessorOp = 0x83, // deprecated
ExtPowerResOp = 0x84,
ExtThermalZoneOp = 0x85,
ExtBankFieldOp = 0x87,
ExtDataRegionOp = 0x88,
// ... not specified
MethodOp = 0x14,
ExtMutexOp = 0x01,
ExtEventOp = 0x02,
ExtFieldOp = 0x81,
ExtDeviceOp = 0x82,
ExtIndexFieldOp = 0x86,
// StatementOpcode
BreakOp = 0xA5,
BreakPointOp = 0xCC,
ContinueOp = 0x9F,
ElseOp = 0xA1,
IfOp = 0xA0,
NoopOp = 0xA3,
NotifyOp = 0x86,
ReturnOp = 0xA4,
WhileOp = 0xA2,
ExtFatalOp = 0x32,
ExtReleaseOp = 0x27,
ExtResetOp = 0x26,
ExtSignalOp = 0x24,
ExtSleepOp = 0x22,
ExtStallOp = 0x21,
// ExpressionOpcode
//PackageOp = 0x12,
//VarPackageOp = 0x13,
//BufferOp = 0x11,
StoreOp = 0x70,
RefOfOp = 0x71,
AddOp = 0x72,
ConcatOp = 0x73,
SubtractOp = 0x74,
IncrementOp = 0x75,
DecrementOp = 0x76,
MultiplyOp = 0x77,
DivideOp = 0x78,
ShiftLeftOp = 0x79,
ShiftRightOp = 0x7A,
AndOp = 0x7B,
NAndOp = 0x7C,
OrOp = 0x7D,
NOrOp = 0x7E,
XOrOp = 0x7F,
NotOp = 0x80,
FindSetLeftBitOp = 0x81,
FindSetRightBitOp = 0x82,
DerefOfOp = 0x83,
ConcatResOp = 0x84,
ModOp = 0x85,
SizeOfOp = 0x87,
IndexOp = 0x88,
MatchOp = 0x89,
ObjectTypeOp = 0x8E,
LAndOp = 0x90,
LOrOp = 0x91,
LNotOp = 0x92,
LEqualOp = 0x93,
LGreaterOp = 0x94,
LLessOp = 0x95,
ToBufferOp = 0x96,
ToDecimalStringOp = 0x97,
ToHexStringOp = 0x98,
ToIntegerOp = 0x99,
ToStringOp = 0x9C,
CopyObjectOp = 0x9D,
MidOp = 0x9E,
ExtCondRefOfOp = 0x12,
ExtLoadTableOp = 0x1F,
ExtLoadOp = 0x20,
ExtAcquireOp = 0x23,
ExtWaitOp = 0x25,
ExtFromBCDOp = 0x28,
ExtToBCDOp = 0x29,
ExtTimerOp = 0x33,
// LocalObj
Local0Op = 0x60,
Local1Op = 0x61,
Local2Op = 0x62,
Local3Op = 0x63,
Local4Op = 0x64,
Local5Op = 0x65,
Local6Op = 0x66,
Local7Op = 0x67,
// ArgObj
Arg0Op = 0x68,
Arg1Op = 0x69,
Arg2Op = 0x6A,
Arg3Op = 0x6B,
Arg4Op = 0x6C,
Arg5Op = 0x6D,
Arg6Op = 0x6E,
// DebugObj
ExtDebugOp = 0x31,
};
}

View File

@ -0,0 +1,101 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/Optional.h>
#include <BAN/String.h>
#include <BAN/UniqPtr.h>
#include <BAN/Variant.h>
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/NameObject.h>
namespace Kernel::ACPI::AML
{
// ACPI Spec 6.4, Section 20.2.3
// Integer := ByteConst | WordConst | DWordConst | QWordConst
// Not actually defined in the spec...
struct Integer
{
uint64_t value;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<Integer> parse(BAN::ConstByteSpan& span);
};
// Buffer := BufferOp PkgLength BufferSize ByteList
struct Buffer
{
Integer buffer_size;
BAN::Vector<uint8_t> data;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<Buffer> parse(BAN::ConstByteSpan& span);
};
// ComputationalData := Integer | String | ConstObj | RevisionOp | DefBuffer
struct ComputationalData
{
struct String
{
BAN::String value;
};
struct ConstObj
{
enum class Type
{
Zero,
One,
Ones
};
Type type;
};
struct RevisionOp {};
BAN::Variant<Integer, String, ConstObj, RevisionOp, Buffer> data;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<ComputationalData> parse(BAN::ConstByteSpan& span);
};
struct DataRefObject;
// PackageElement := DataRefObject | NameString
using PackageElement = BAN::Variant<BAN::UniqPtr<DataRefObject>, NameString>;
// DefPackage := PackageOp PkgLength NumElements PackageElementList
struct Package
{
BAN::Vector<PackageElement> elements;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<Package> parse(BAN::ConstByteSpan& span);
};
// DefVarPackage := VarPackageOp PkgLength VarNumElements PackageElementList
struct VarPackage
{
BAN::Vector<PackageElement> elements;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<VarPackage> parse(BAN::ConstByteSpan& span);
};
// DataObject := ComputationalData | DefPackage | DefVarPackage
struct DataObject
{
BAN::Variant<ComputationalData, Package, VarPackage> data;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<DataObject> parse(BAN::ConstByteSpan& span);
};
// DataRefObject := DataObject | ObjectReference
struct DataRefObject
{
BAN::Variant<DataObject, Integer> object;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<DataRefObject> parse(BAN::ConstByteSpan& span);
};
}

View File

@ -0,0 +1,56 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/Optional.h>
namespace Kernel::ACPI::AML
{
// ACPI Spec 6.4, Section 20.2.6
// ArgObj := Arg0Op | Arg1Op | Arg2Op | Arg3Op | Arg4Op | Arg5Op | Arg6Op
struct ArgObj
{
enum class Type
{
Arg0,
Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
};
Type type;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<ArgObj> parse(BAN::ConstByteSpan& span);
};
// LocalObj := Local0Op | Local1Op | Local2Op | Local3Op | Local4Op | Local5Op | Local6Op | Local7Op
struct LocalObj
{
enum class Type
{
Local0,
Local1,
Local2,
Local3,
Local4,
Local5,
Local6,
Local7,
};
Type type;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<LocalObj> parse(BAN::ConstByteSpan& span);
};
// DebugObj := DebugOp
struct DebugObj
{
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<DebugObj> parse(BAN::ConstByteSpan& span);
};
}

View File

@ -0,0 +1,46 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/Optional.h>
#include <BAN/String.h>
#include <BAN/UniqPtr.h>
#include <BAN/Variant.h>
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/MiscObject.h>
namespace Kernel::ACPI::AML
{
// ACPI Spec 6.4, Section 20.2.2
// NameSeg := LeadNameChar NameChar NameChar NameChar
// NameString := ('\' | {'^'}) (NameSeg | (DualNamePrefix NameSeg NameSeg) | (MultiNamePrefix SegCount NameSeg(SegCount)) | 0x00)
struct NameString
{
BAN::String prefix;
BAN::Vector<BAN::String> path;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<NameString> parse(BAN::ConstByteSpan& span);
};
// SimpleName := NameString | ArgObj | LocalObj
struct SimpleName
{
BAN::Variant<NameString, ArgObj, LocalObj> name;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<SimpleName> parse(BAN::ConstByteSpan& span);
};
struct ReferenceTypeOpcode;
// SuperName := SimpleName | DebugObj | ReferenceTypeOpcode
struct SuperName
{
BAN::Variant<SimpleName, DebugObj, BAN::UniqPtr<ReferenceTypeOpcode>> name;
static bool can_parse(BAN::ConstByteSpan span);
static BAN::Optional<SuperName> parse(BAN::ConstByteSpan& span);
};
}

View File

@ -0,0 +1,36 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/Optional.h>
#include <kernel/ACPI/AML/Bytes.h>
namespace Kernel::ACPI::AML
{
struct PkgLength
{
static BAN::Optional<BAN::ConstByteSpan> parse_package(BAN::ConstByteSpan& span)
{
if (span.size() < 1)
return {};
uint8_t count = (span[0] >> 6) + 1;
if (span.size() < count)
return {};
if (count > 1 && (span[0] & 0x30))
return {};
uint32_t length = span[0] & 0x3F;
for (uint8_t i = 1; i < count; i++)
length |= static_cast<uint32_t>(span[i]) << (i * 8 - 4);
if (span.size() < length)
return {};
auto result = span.slice(count, length - count);
span = span.slice(length);
return result;
}
};
}

View File

@ -0,0 +1,328 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/Optional.h>
#include <BAN/UniqPtr.h>
#include <BAN/Variant.h>
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/DataObject.h>
#include <kernel/ACPI/AML/MiscObject.h>
#include <kernel/ACPI/AML/NameObject.h>
namespace Kernel::ACPI::AML
{
// ACPI Spec 6.4, Section 20.2.5
struct TermObj;
struct TermArg;
// TermList := Nothing | TermObj TermList
struct TermList
{
BAN::Vector<TermObj> terms;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<TermList> parse(BAN::ConstByteSpan&);
};
// MethodInvocation := NameString TermArgList
struct MethodInvocation
{
NameString name;
BAN::Vector<TermArg> term_args;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<MethodInvocation> parse(BAN::ConstByteSpan&);
};
// ExpressionOpcode := DefAcquire | DefAdd | DefAnd | DefBuffer | DefConcat | DefConcatRes | DefCondRefOf
// | DefCopyObject | DefDecrement | DefDerefOf | DefDivide | DefFindSetLeftBit
// | DefFindSetRightBit | DefFromBCD | DefIncrement | DefIndex | DefLAnd | DefLEqual
// | DefLGreater | DefLGreaterEqual | DefLLess | DefLLessEqual | DefMid | DefLNot
// | DefLNotEqual | DefLoadTable | DefLOr | DefMatch | DefMod | DefMultiply | DefNAnd
// | DefNOr | DefNot | DefObjectType | DefOr | DefPackage | DefVarPackage | DefRefOf
// | DefShiftLeft | DefShiftRight | DefSizeOf | DefStore | DefSubtract | DefTimer
// | DefToBCD | DefToBuffer | DefToDecimalString | DefToHexString | DefToInteger
// | DefToString | DefWait | DefXOr | MethodInvocation
struct ExpressionOpcode
{
struct UnaryOp
{
enum class Type
{
Decrement,
Increment,
RefOf,
SizeOf,
};
Type type;
SuperName object;
};
struct BinaryOp
{
enum class Type
{
Add,
And,
Multiply,
NAnd,
NOr,
Or,
Subtract,
XOr,
ShiftLeft,
ShiftRight,
};
Type type;
BAN::UniqPtr<TermArg> source1;
BAN::UniqPtr<TermArg> source2;
SuperName target;
};
struct LogicalBinaryOp
{
enum class Type
{
And,
Equal,
Greater,
Less,
Or,
// GreaterEqual, LessEqual, NotEqual handled by Not + LogicalBinaryOp
};
Type type;
BAN::UniqPtr<TermArg> operand1;
BAN::UniqPtr<TermArg> operand2;
};
#define GEN_OPCODE_STRUCT_OPERAND_TARGET(NAME) struct NAME { BAN::UniqPtr<TermArg> operand; SuperName target; }
GEN_OPCODE_STRUCT_OPERAND_TARGET(ToBuffer);
GEN_OPCODE_STRUCT_OPERAND_TARGET(ToDecimalString);
GEN_OPCODE_STRUCT_OPERAND_TARGET(ToHexString);
GEN_OPCODE_STRUCT_OPERAND_TARGET(ToInteger);
#undef GEN_OPCODE_STRUCT_OPERAND_TARGET
struct Acquire
{
SuperName mutex;
uint16_t timeout;
};
struct Store
{
BAN::UniqPtr<TermArg> source;
SuperName target;
};
BAN::Variant<
UnaryOp, BinaryOp, LogicalBinaryOp,
ToBuffer, ToDecimalString, ToHexString, ToInteger,
Acquire, Buffer, Package, VarPackage, Store, MethodInvocation
> opcode;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<ExpressionOpcode> parse(BAN::ConstByteSpan&);
};
// TermArg := ExpressionOpcode | DataObject | ArgObj | LocalObj
struct TermArg
{
BAN::Variant<ExpressionOpcode, DataObject, ArgObj, LocalObj> arg;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<TermArg> parse(BAN::ConstByteSpan&);
};
// NameSpaceModifierObj := DefAlias | DefName | DefScope
struct NameSpaceModifierObj
{
struct Alias {};
struct Name
{
NameString name;
DataRefObject object;
};
struct Scope
{
NameString name;
TermList term_list;
};
BAN::Variant<Alias, Name, Scope> modifier;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<NameSpaceModifierObj> parse(BAN::ConstByteSpan&);
};
// NamedObj := DefBankField | DefCreateBitField | DefCreateByteField | DefCreateDWordField | DefCreateField
// | DefCreateQWordField | DefCreateWordField | DefDataRegion | DefExternal | DefOpRegion
// | DefProcessor(deprecated) | DefPowerRes | DefThermalZone
// Spec does not specify any of DefDevice, DefEvent, DefField, DefIndexField, DefMethod, DefMutex as options
struct NamedObj
{
struct CreateSizedField
{
enum class Type
{
Bit,
Byte,
Word,
DWord,
QWord,
};
Type type;
TermArg buffer;
TermArg index;
NameString name;
};
struct BankField {};
struct CreateField {};
struct DataRegion {};
struct External {};
struct OpRegion
{
enum class RegionSpace : uint8_t
{
SystemMemory = 0x00,
SystemIO = 0x01,
PCIConfigSpace = 0x02,
EmbeddedController = 0x03,
SMBus = 0x04,
SystemCMOS = 0x05,
PCIBarTarget = 0x06,
IPMI = 0x07,
GeneralPurposeIO = 0x08,
ResourceDescriptor = 0x09,
PCC = 0x0A,
};
NameString name;
RegionSpace region_space;
TermArg region_offset;
TermArg region_length;
};
struct Processor
{
NameString name;
uint8_t processor_id;
uint32_t p_blk_address;
uint8_t p_blk_length;
TermList term_list;
};
struct PowerRes {};
struct ThermalZone {};
struct Device
{
NameString name;
TermList term_list;
};
struct Event {};
struct Field
{
NameString name;
// field flags
// field list
};
struct IndexField {};
struct Method
{
NameString name;
uint8_t argument_count;
bool serialized;
uint8_t sync_level;
TermList term_list;
};
struct Mutex
{
NameString name;
uint8_t sync_level;
};
BAN::Variant<BankField, CreateSizedField, CreateField, DataRegion,
External, OpRegion, PowerRes, Processor, ThermalZone, Device,
Event, Field, IndexField, Method, Mutex
> object;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<NamedObj> parse(BAN::ConstByteSpan&);
};
// Object := NameSpaceModifierObj | NamedObj
struct Object
{
BAN::Variant<NameSpaceModifierObj, NamedObj> object;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<Object> parse(BAN::ConstByteSpan&);
};
// StatementOpcode := DefBreak | DefBreakPoint | DefContinue | DefFatal | DefIfElse | DefNoop | DefNotify
// | DefRelease | DefReset | DefReturn | DefSignal | DefSleep | DefStall | DefWhile
struct StatementOpcode
{
struct IfElse
{
TermArg predicate;
TermList true_list;
TermList false_list;
};
struct Notify
{
SuperName object;
TermArg value;
};
struct Release
{
SuperName mutex;
};
struct Return
{
// TODO: Is argument actually optional?
// This is not specified in the spec but it seems like it should be
BAN::Optional<DataRefObject> arg;
};
BAN::Variant<IfElse, Notify, Release, Return> opcode;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<StatementOpcode> parse(BAN::ConstByteSpan&);
};
// TermObj := Object | StatementOpcode | ExpressionOpcode
struct TermObj
{
BAN::Variant<Object, StatementOpcode, ExpressionOpcode> term;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<TermObj> parse(BAN::ConstByteSpan&);
};
// ReferenceTypeOpcode := DefRefOf | DefDerefOf | DefIndex | UserTermObj
struct ReferenceTypeOpcode
{
struct RefOf
{
SuperName target;
};
struct DerefOf
{
TermArg source;
};
struct Index
{
TermArg source;
TermArg index;
SuperName destination;
};
struct UserTermObj
{
MethodInvocation method;
};
BAN::Variant<RefOf, DerefOf, Index, UserTermObj> opcode;
static bool can_parse(BAN::ConstByteSpan);
static BAN::Optional<ReferenceTypeOpcode> parse(BAN::ConstByteSpan&);
};
}

View File

@ -0,0 +1,115 @@
#pragma once
#include <stdint.h>
namespace Kernel::ACPI
{
struct GAS
{
uint8_t address_space_id;
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t access_size;
uint64_t address;
} __attribute__((packed));
struct SDTHeader
{
uint8_t signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oemid[6];
uint64_t oem_table_id;
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} __attribute__((packed));
struct FADT : public SDTHeader
{
uint32_t firmware_ctrl;
uint32_t dsdt;
uint8_t __reserved;
uint8_t preferred_pm_profile;
uint16_t sci_int;
uint32_t smi_cmd;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_cnt;
uint32_t pm1a_evt_blk;
uint32_t pm1b_evt_blk;
uint32_t pm1a_cnt_blk;
uint32_t pm1b_cnt_blk;
uint32_t pm2_cnt_blk;
uint32_t pm_tmr_blk;
uint32_t gpe0_blk;
uint32_t gpe1_blk;
uint8_t pm1_evt_len;
uint8_t pm1_cnt_len;
uint8_t pm2_cnt_len;
uint8_t pm_tmr_len;
uint8_t gpe0_blk_len;
uint8_t gpe1_blk_len;
uint8_t gpe1_base;
uint8_t cst_cnt;
uint16_t p_lvl2_lat;
uint16_t p_lvl3_lat;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alrm;
uint8_t mon_alrm;
uint8_t century;
uint16_t iapc_boot_arch;
uint8_t __reserved2;
uint32_t flags;
uint8_t reset_reg[12];
uint8_t reset_value;
uint16_t arm_boot_arch;
uint8_t fadt_minor_version;
uint64_t x_firmware_version;
uint64_t x_dsdt;
uint8_t x_pm1a_evt_blk[12];
uint8_t x_pm1b_evt_blk[12];
uint8_t x_pm1a_cnt_blk[12];
uint8_t x_pm1b_cnt_blk[12];
uint8_t x_pm2_cnt_blk[12];
uint8_t x_pm_tmr_blk[12];
uint8_t x_gpe0_blk[12];
uint8_t x_gpe1_blk[12];
uint8_t sleep_control_reg[12];
uint8_t sleep_status_reg[12];
uint64_t hypervison_vendor_identity;
} __attribute__((packed));
struct HPET : public SDTHeader
{
uint8_t hardware_rev_id;
uint8_t comparator_count : 5;
uint8_t count_size_cap : 1;
uint8_t reserved : 1;
uint8_t legacy_replacement_irq_routing_cable : 1;
uint16_t pci_vendor_id;
GAS base_address;
uint8_t hpet_number;
uint16_t main_counter_minimum_clock_tick;
uint8_t page_protection_and_oem_attribute;
} __attribute__((packed));
}
namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const Kernel::ACPI::SDTHeader& header, const struct ValueFormat&)
{
putc(header.signature[0]);
putc(header.signature[1]);
putc(header.signature[2]);
putc(header.signature[3]);
}
}

View File

@ -93,7 +93,7 @@ namespace Kernel
void on_exit();
private:
static constexpr size_t m_kernel_stack_size = PAGE_SIZE * 4;
static constexpr size_t m_kernel_stack_size = PAGE_SIZE * 64;
static constexpr size_t m_userspace_stack_size = PAGE_SIZE * 4;
BAN::UniqPtr<VirtualRange> m_kernel_stack;
BAN::UniqPtr<VirtualRange> m_userspace_stack;

View File

@ -1,6 +1,7 @@
#include <BAN/ScopeGuard.h>
#include <BAN/StringView.h>
#include <kernel/ACPI.h>
#include <kernel/ACPI/ACPI.h>
#include <kernel/ACPI/AML.h>
#include <kernel/BootInfo.h>
#include <kernel/Memory/PageTable.h>
@ -9,15 +10,15 @@
#define RSPD_SIZE 20
#define RSPDv2_SIZE 36
namespace Kernel
namespace Kernel::ACPI
{
struct RSDT : public ACPI::SDTHeader
struct RSDT : public SDTHeader
{
uint32_t entries[];
} __attribute__((packed));
struct XSDT : public ACPI::SDTHeader
struct XSDT : public SDTHeader
{
uint64_t entries[];
} __attribute__((packed));
@ -31,6 +32,11 @@ namespace Kernel
if (s_instance == nullptr)
return BAN::Error::from_errno(ENOMEM);
TRY(s_instance->initialize_impl());
auto dsdt = s_instance->get_header("DSDT", 0);
ASSERT(dsdt);
AMLParser::parse_table(*dsdt);
#if ARCH(x86_64)
lai_create_namespace();
#endif
@ -82,7 +88,7 @@ namespace Kernel
return nullptr;
}
static bool is_valid_std_header(const ACPI::SDTHeader* header)
static bool is_valid_std_header(const SDTHeader* header)
{
uint8_t sum = 0;
for (uint32_t i = 0; i < header->length; i++)
@ -225,7 +231,7 @@ namespace Kernel
return {};
}
const ACPI::SDTHeader* ACPI::get_header(BAN::StringView signature, uint32_t index)
const SDTHeader* ACPI::get_header(BAN::StringView signature, uint32_t index)
{
if (signature.size() != 4)
{

View File

@ -0,0 +1,281 @@
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/DataObject.h>
#include <kernel/ACPI/AML/PackageLength.h>
namespace Kernel::ACPI
{
// Integer
bool AML::Integer::can_parse(BAN::ConstByteSpan span)
{
if (span.size() < 1)
return false;
switch (static_cast<AML::Byte>(span[0]))
{
case AML::Byte::BytePrefix:
case AML::Byte::WordPrefix:
case AML::Byte::DWordPrefix:
case AML::Byte::QWordPrefix:
return true;
default:
return false;
}
}
BAN::Optional<AML::Integer> AML::Integer::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
switch (static_cast<AML::Byte>(span[0]))
{
#define AML_PARSE_INTEGER_CASE(TYPE, BYTES) \
case AML::Byte::TYPE##Prefix: \
{ \
span = span.slice(1); \
if (span.size() < BYTES) \
{ \
AML_DEBUG_CANNOT_PARSE(#TYPE, span); \
return {}; \
} \
uint64_t value = 0; \
for (size_t i = 0; i < BYTES; i++) \
value |= static_cast<uint64_t>(span[i]) << (i * 8); \
AML_DEBUG_PRINT("0x{H}", value); \
span = span.slice(BYTES); \
return Integer { .value = value }; \
}
AML_PARSE_INTEGER_CASE(Byte, 1)
AML_PARSE_INTEGER_CASE(Word, 2)
AML_PARSE_INTEGER_CASE(DWord, 4)
AML_PARSE_INTEGER_CASE(QWord, 8)
#undef AML_PARSE_INTEGER_CASE
default:
ASSERT_NOT_REACHED();
}
}
// Buffer
bool AML::Buffer::can_parse(BAN::ConstByteSpan span)
{
if (span.size() < 1)
return false;
if (static_cast<AML::Byte>(span[0]) == AML::Byte::BufferOp)
return true;
return false;
}
BAN::Optional<AML::Buffer> AML::Buffer::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
span = span.slice(1);
AML_TRY_PARSE_PACKAGE(buffer_span);
AML_TRY_PARSE(buffer_size, AML::Integer, buffer_span);
if (buffer_span.size() < buffer_size->value)
{
AML_DEBUG_ERROR("Buffer size {} bytes and span only {} bytes", buffer_size->value, buffer_span.size());
return {};
}
BAN::Vector<uint8_t> data;
MUST(data.resize(buffer_size->value));
for (size_t i = 0; i < buffer_size->value; i++)
data[i] = buffer_span[i];
return Buffer { .buffer_size = buffer_size.release_value(), .data = BAN::move(data) };
}
// ComputationalData
bool AML::ComputationalData::can_parse(BAN::ConstByteSpan span)
{
if (span.size() < 1)
return false;
if (static_cast<AML::Byte>(span[0]) == AML::Byte::ExtOpPrefix)
{
if (span.size() < 2)
return false;
switch (static_cast<AML::Byte>(span[1]))
{
case AML::Byte::ExtRevisionOp:
return true;
default:
return false;
}
}
switch (static_cast<AML::Byte>(span[0]))
{
case AML::Byte::ZeroOp:
case AML::Byte::OneOp:
case AML::Byte::OnesOp:
case AML::Byte::BytePrefix:
case AML::Byte::WordPrefix:
case AML::Byte::DWordPrefix:
case AML::Byte::StringPrefix:
case AML::Byte::QWordPrefix:
case AML::Byte::BufferOp:
return true;
default:
return false;
}
}
BAN::Optional<AML::ComputationalData> AML::ComputationalData::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
AML_TRY_PARSE_IF_CAN(AML::Buffer);
AML_TRY_PARSE_IF_CAN(AML::Integer);
switch (static_cast<AML::Byte>(span[0]))
{
#define AML_PARSE_CONST(TYPE) \
case AML::Byte::TYPE##Op: \
{ \
span = span.slice(1); \
AML_DEBUG_PRINT("{}", #TYPE); \
return ConstObj { .type = ConstObj::Type::TYPE }; \
}
AML_PARSE_CONST(Zero);
AML_PARSE_CONST(One);
AML_PARSE_CONST(Ones);
#undef AML_PARSE_CONST
case AML::Byte::StringPrefix:
{
span = span.slice(1);
BAN::String value;
while (span.size() > 0)
{
if (span[0] == 0x00 || span[0] > 0x7F)
break;
MUST(value.push_back(span[0]));
span = span.slice(1);
}
if (span.size() == 0 || span[0] != 0x00)
return {};
span = span.slice(1);
AML_DEBUG_PRINT("\"{}\"", value);
return String { .value = BAN::move(value) };
}
GEN_PARSE_CASE_TODO(BufferOp)
default:
ASSERT_NOT_REACHED();
}
ASSERT_NOT_REACHED();
}
#define AML_GEN_PACKAGE(NAME) \
bool AML::NAME::can_parse(BAN::ConstByteSpan span) \
{ \
if (span.size() < 1) \
return false; \
if (static_cast<AML::Byte>(span[0]) == AML::Byte::NAME##Op) \
return true; \
return false; \
} \
\
BAN::Optional<AML::NAME> AML::NAME::parse(BAN::ConstByteSpan& span) \
{ \
AML_DEBUG_PRINT_FN(); \
ASSERT(can_parse(span)); \
\
span = span.slice(1); \
\
AML_TRY_PARSE_PACKAGE(package_span); \
\
uint8_t count = package_span[0]; \
package_span = package_span.slice(1); \
\
AML_DEBUG_PRINT("Count: {}", count); \
\
BAN::Vector<PackageElement> elements; \
for (uint8_t i = 0; i < count; i++) \
{ \
if (DataRefObject::can_parse(package_span)) \
{ \
AML_TRY_PARSE(element, DataRefObject, package_span); \
MUST(elements.push_back(PackageElement { \
MUST(BAN::UniqPtr<DataRefObject>::create(element.release_value())) \
})); \
} \
else if (NameString::can_parse(package_span)) \
{ \
AML_TRY_PARSE(element, NameString, package_span); \
MUST(elements.push_back(PackageElement { \
element.release_value() \
})); \
} \
else \
{ \
AML_DEBUG_CANNOT_PARSE("PackageElement", package_span); \
return {}; \
} \
} \
\
return NAME { .elements = BAN::move(elements) }; \
}
AML_GEN_PACKAGE(Package)
AML_GEN_PACKAGE(VarPackage)
#undef AML_GEN_PACKAGE
// DataObject
bool AML::DataObject::can_parse(BAN::ConstByteSpan span)
{
if (ComputationalData::can_parse(span))
return true;
if (Package::can_parse(span))
return true;
if (VarPackage::can_parse(span))
return true;
return false;
}
BAN::Optional<AML::DataObject> AML::DataObject::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
AML_TRY_PARSE_IF_CAN(ComputationalData);
AML_TRY_PARSE_IF_CAN(Package);
AML_TRY_PARSE_IF_CAN(VarPackage);
ASSERT_NOT_REACHED();
}
// DataRefObject
bool AML::DataRefObject::can_parse(BAN::ConstByteSpan span)
{
if (DataObject::can_parse(span))
return true;
if (Integer::can_parse(span))
return true;
return false;
}
BAN::Optional<AML::DataRefObject> AML::DataRefObject::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
AML_TRY_PARSE_IF_CAN(DataObject);
AML_TRY_PARSE_IF_CAN(Integer);
ASSERT_NOT_REACHED();
}
}

View File

@ -0,0 +1,99 @@
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/MiscObject.h>
namespace Kernel::ACPI
{
// ArgObj
bool AML::ArgObj::can_parse(BAN::ConstByteSpan span)
{
if (span.size() < 1)
return false;
switch (static_cast<AML::Byte>(span[0]))
{
case AML::Byte::Arg0Op:
case AML::Byte::Arg1Op:
case AML::Byte::Arg2Op:
case AML::Byte::Arg3Op:
case AML::Byte::Arg4Op:
case AML::Byte::Arg5Op:
case AML::Byte::Arg6Op:
return true;
default:
return false;
}
}
BAN::Optional<AML::ArgObj> AML::ArgObj::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
uint8_t type = static_cast<uint8_t>(span[0]) - static_cast<uint8_t>(AML::Byte::Arg0Op);
span = span.slice(1);
AML_DEBUG_PRINT("Arg{}", type);
return ArgObj { .type = static_cast<Type>(type) };
}
// LocalObj
bool AML::LocalObj::can_parse(BAN::ConstByteSpan span)
{
if (span.size() < 1)
return false;
switch (static_cast<AML::Byte>(span[0]))
{
case AML::Byte::Local0Op:
case AML::Byte::Local1Op:
case AML::Byte::Local2Op:
case AML::Byte::Local3Op:
case AML::Byte::Local4Op:
case AML::Byte::Local5Op:
case AML::Byte::Local6Op:
case AML::Byte::Local7Op:
return true;
default:
return false;
}
}
BAN::Optional<AML::LocalObj> AML::LocalObj::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
uint8_t type = static_cast<uint8_t>(span[0]) - static_cast<uint8_t>(AML::Byte::Local0Op);
span = span.slice(1);
AML_DEBUG_PRINT("Local{}", type);
return LocalObj { .type = static_cast<Type>(type) };
}
// DebugObj
bool AML::DebugObj::can_parse(BAN::ConstByteSpan span)
{
if (span.size() < 2)
return false;
if (static_cast<AML::Byte>(span[0]) != AML::Byte::ExtOpPrefix)
return false;
if (static_cast<AML::Byte>(span[1]) != AML::Byte::ExtDebugOp)
return false;
return true;
}
BAN::Optional<AML::DebugObj> AML::DebugObj::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
span = span.slice(2);
return DebugObj {};
}
}

View File

@ -0,0 +1,162 @@
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/NameObject.h>
#include <kernel/ACPI/AML/TermObject.h>
namespace Kernel::ACPI
{
static constexpr bool is_lead_name_char(uint8_t ch)
{
return ('A' <= ch && ch <= 'Z') || ch == '_';
}
static constexpr bool is_name_char(uint8_t ch)
{
return is_lead_name_char(ch) || ('0' <= ch && ch <= '9');
}
// NameString
bool AML::NameString::can_parse(BAN::ConstByteSpan span)
{
if (span.size() < 1)
return false;
if (span[0] == '\\' || span[0] == '^' || span[0] == 0x00)
return true;
if (static_cast<AML::Byte>(span[0]) == AML::Byte::DualNamePrefix)
return true;
if (static_cast<AML::Byte>(span[0]) == AML::Byte::MultiNamePrefix)
return true;
if (is_lead_name_char(span[0]))
return true;
return false;
}
BAN::Optional<AML::NameString> AML::NameString::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
NameString name_string;
if (span[0] == '\\')
{
MUST(name_string.prefix.push_back('\\'));
span = span.slice(1);
}
else if (span[0] == '^')
{
while (span[0] == '^')
{
MUST(name_string.prefix.push_back('^'));
span = span.slice(1);
}
}
size_t name_count = 1;
switch (span[0])
{
case 0x00:
name_count = 0;
span = span.slice(1);
break;
case static_cast<uint8_t>(AML::Byte::DualNamePrefix):
name_count = 2;
span = span.slice(1);
break;
case static_cast<uint8_t>(AML::Byte::MultiNamePrefix):
name_count = span[1];
span = span.slice(2);
break;
}
if (span.size() < name_count * 4)
return {};
MUST(name_string.path.resize(name_count));
for (size_t i = 0; i < name_count; i++)
{
if (!is_lead_name_char(span[0]) || !is_name_char(span[1]) || !is_name_char(span[2]) || !is_name_char(span[3]))
{
AML_DEBUG_ERROR("Invalid NameSeg {2H} {2H} {2H} {2H}", span[0], span[1], span[2], span[3]);
ASSERT_NOT_REACHED();
return {};
}
MUST(name_string.path[i].append(BAN::StringView(reinterpret_cast<const char*>(span.data()), 4)));
while (name_string.path[i].back() == '_')
name_string.path[i].pop_back();
span = span.slice(4);
}
if constexpr(DUMP_AML)
{
BAN::String full_string;
MUST(full_string.append(name_string.prefix));
for (size_t i = 0; i < name_string.path.size(); i++)
{
if (i != 0)
MUST(full_string.push_back('.'));
MUST(full_string.append(name_string.path[i]));
}
AML_DEBUG_PRINT("'{}'", full_string);
}
return name_string;
}
// SimpleName
bool AML::SimpleName::can_parse(BAN::ConstByteSpan span)
{
if (NameString::can_parse(span))
return true;
if (ArgObj::can_parse(span))
return true;
if (LocalObj::can_parse(span))
return true;
return false;
}
BAN::Optional<AML::SimpleName> AML::SimpleName::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
AML_TRY_PARSE_IF_CAN(NameString);
AML_TRY_PARSE_IF_CAN(ArgObj);
AML_TRY_PARSE_IF_CAN(LocalObj);
ASSERT_NOT_REACHED();
}
// SuperName
bool AML::SuperName::can_parse(BAN::ConstByteSpan span)
{
if (SimpleName::can_parse(span))
return true;
if (DebugObj::can_parse(span))
return true;
if (ReferenceTypeOpcode::can_parse(span))
return true;
return false;
}
BAN::Optional<AML::SuperName> AML::SuperName::parse(BAN::ConstByteSpan& span)
{
AML_DEBUG_PRINT_FN();
ASSERT(can_parse(span));
AML_TRY_PARSE_IF_CAN(SimpleName);
AML_TRY_PARSE_IF_CAN(DebugObj);
ASSERT(ReferenceTypeOpcode::can_parse(span));
auto opcode = ReferenceTypeOpcode::parse(span);
if (!opcode.has_value())
return {};
return SuperName { .name = MUST(BAN::UniqPtr<ReferenceTypeOpcode>::create(opcode.release_value())) };
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#include <BAN/ScopeGuard.h>
#include <kernel/ACPI.h>
#include <kernel/ACPI/ACPI.h>
#include <kernel/APIC.h>
#include <kernel/CPUID.h>
#include <kernel/Debug.h>
@ -132,7 +132,7 @@ namespace Kernel
return nullptr;
}
const MADT* madt = (const MADT*)Kernel::ACPI::get().get_header("APIC"sv, 0);
const MADT* madt = (const MADT*)ACPI::ACPI::get().get_header("APIC"sv, 0);
if (madt == nullptr)
{
dprintln("Could not find MADT header");

View File

@ -1,5 +1,5 @@
#include <BAN/ScopeGuard.h>
#include <kernel/ACPI.h>
#include <kernel/ACPI/ACPI.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/IDT.h>
#include <kernel/Input/PS2/Config.h>
@ -244,7 +244,7 @@ namespace Kernel::Input
// FIXME: Initialise USB Controllers
// Determine if the PS/2 Controller Exists
auto* fadt = static_cast<const ACPI::FADT*>(ACPI::get().get_header("FACP"sv, 0));
auto* fadt = static_cast<const ACPI::FADT*>(ACPI::ACPI::get().get_header("FACP"sv, 0));
if (fadt && fadt->revision > 1 && !(fadt->iapc_boot_arch & (1 << 1)))
{
dwarnln_if(DEBUG_PS2, "No PS/2 available");

View File

@ -1,5 +1,5 @@
#include <BAN/ScopeGuard.h>
#include <kernel/ACPI.h>
#include <kernel/ACPI/ACPI.h>
#include <kernel/IDT.h>
#include <kernel/InterruptController.h>
#include <kernel/Memory/PageTable.h>
@ -131,7 +131,7 @@ namespace Kernel
BAN::ErrorOr<void> HPET::initialize(bool force_pic)
{
auto* header = static_cast<const ACPI::HPET*>(ACPI::get().get_header("HPET"sv, 0));
auto* header = static_cast<const ACPI::HPET*>(ACPI::ACPI::get().get_header("HPET"sv, 0));
if (header == nullptr)
return BAN::Error::from_errno(ENODEV);

View File

@ -1,4 +1,4 @@
#include <kernel/ACPI.h>
#include <kernel/ACPI/ACPI.h>
#include <kernel/Arch.h>
#include <kernel/BootInfo.h>
#include <kernel/Debug.h>
@ -116,7 +116,7 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
parse_command_line();
dprintln("command line parsed, root='{}', console='{}'", cmdline.root, cmdline.console);
MUST(ACPI::initialize());
MUST(ACPI::ACPI::initialize());
dprintln("ACPI initialized");
InterruptController::initialize(cmdline.force_pic);

View File

@ -1,4 +1,4 @@
#include <kernel/ACPI.h>
#include <kernel/ACPI/ACPI.h>
#include <kernel/IO.h>
#include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/PageTable.h>
@ -51,7 +51,7 @@ void laihost_panic(const char* msg)
void* laihost_scan(const char* sig, size_t index)
{
return (void*)ACPI::get().get_header(sig, index);
return (void*)ACPI::ACPI::get().get_header(sig, index);
}
void* laihost_map(size_t address, size_t count)