#pragma once #include #include #include #include #include #include #include namespace Kernel::ACPI::AML { struct Integer : public Node { struct Constants { // Initialized in Namespace::create_root_namespace static BAN::RefPtr Zero; static BAN::RefPtr One; static BAN::RefPtr Ones; }; uint64_t value; const bool constant; Integer(uint64_t value, bool constant = false) : Node(Node::Type::Integer) , value(value) , constant(constant) {} BAN::RefPtr copy() override { return MUST(BAN::RefPtr::create(value)); } BAN::RefPtr evaluate() override { return this; } bool store(BAN::RefPtr 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_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::create(value))); } case AML::Byte::WordPrefix: { if (aml_data.size() < 3) return ParseResult::Failure; uint16_t value = BAN::little_endian_to_host( *reinterpret_cast(&aml_data[1]) ); aml_data = aml_data.slice(3); return ParseResult(MUST(BAN::RefPtr::create(value))); } case AML::Byte::DWordPrefix: { if (aml_data.size() < 5) return ParseResult::Failure; uint32_t value = BAN::little_endian_to_host( *reinterpret_cast(&aml_data[1]) ); aml_data = aml_data.slice(5); return ParseResult(MUST(BAN::RefPtr::create(value))); } case AML::Byte::QWordPrefix: { if (aml_data.size() < 9) return ParseResult::Failure; uint64_t value = BAN::little_endian_to_host( *reinterpret_cast(&aml_data[1]) ); aml_data = aml_data.slice(9); return ParseResult(MUST(BAN::RefPtr::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(); } } }; }