banan-os/kernel/include/kernel/ACPI/AML/Integer.h

134 lines
3.3 KiB
C++

#pragma once
#include <BAN/Endianness.h>
#include <BAN/Optional.h>
#include <BAN/String.h>
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/Utils.h>
namespace Kernel::ACPI::AML
{
struct Integer : public Node
{
struct Constants
{
// Initialized in Namespace::create_root_namespace
static BAN::RefPtr<Integer> Zero;
static BAN::RefPtr<Integer> One;
static BAN::RefPtr<Integer> Ones;
};
uint64_t value;
const bool constant;
Integer(uint64_t value, bool constant = false)
: Node(Node::Type::Integer)
, value(value)
, constant(constant)
{}
BAN::RefPtr<Node> copy() override { return MUST(BAN::RefPtr<Integer>::create(value)); }
BAN::RefPtr<AML::Node> evaluate() override
{
return this;
}
bool store(BAN::RefPtr<AML::Node> store_node) override
{
if (constant)
{
AML_ERROR("Cannot store to constant integer");
return false;
}
auto store_value = store_node->as_integer();
if (!store_value.has_value())
{
AML_ERROR("Cannot store non-integer to integer");
return false;
}
value = store_value.value();
return true;
}
static ParseResult parse(BAN::ConstByteSpan& aml_data)
{
switch (static_cast<AML::Byte>(aml_data[0]))
{
case AML::Byte::ZeroOp:
aml_data = aml_data.slice(1);
return ParseResult(Constants::Zero);
case AML::Byte::OneOp:
aml_data = aml_data.slice(1);
return ParseResult(Constants::One);
case AML::Byte::OnesOp:
aml_data = aml_data.slice(1);
return ParseResult(Constants::Ones);
case AML::Byte::BytePrefix:
{
if (aml_data.size() < 2)
return ParseResult::Failure;
uint8_t value = aml_data[1];
aml_data = aml_data.slice(2);
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
}
case AML::Byte::WordPrefix:
{
if (aml_data.size() < 3)
return ParseResult::Failure;
uint16_t value = BAN::little_endian_to_host<uint16_t>(
*reinterpret_cast<const uint16_t*>(&aml_data[1])
);
aml_data = aml_data.slice(3);
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
}
case AML::Byte::DWordPrefix:
{
if (aml_data.size() < 5)
return ParseResult::Failure;
uint32_t value = BAN::little_endian_to_host<uint32_t>(
*reinterpret_cast<const uint32_t*>(&aml_data[1])
);
aml_data = aml_data.slice(5);
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
}
case AML::Byte::QWordPrefix:
{
if (aml_data.size() < 9)
return ParseResult::Failure;
uint64_t value = BAN::little_endian_to_host<uint64_t>(
*reinterpret_cast<const uint64_t*>(&aml_data[1])
);
aml_data = aml_data.slice(9);
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
}
default:
ASSERT_NOT_REACHED();
}
}
void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
if (!constant)
AML_DEBUG_PRINT("0x{H}", value);
else
{
AML_DEBUG_PRINT("Const ");
if (value == Constants::Zero->value)
AML_DEBUG_PRINT("Zero");
else if (value == Constants::One->value)
AML_DEBUG_PRINT("One");
else if (value == Constants::Ones->value)
AML_DEBUG_PRINT("Ones");
else
ASSERT_NOT_REACHED();
}
}
};
}