Kernel: AML implement CreateFieldOp

This commit is contained in:
Bananymous 2024-08-13 18:52:48 +03:00
parent 723e458bd7
commit dd79db6383
2 changed files with 31 additions and 23 deletions

View File

@ -91,17 +91,11 @@ namespace Kernel::ACPI::AML
uint64_t value = 0; uint64_t value = 0;
const size_t byte_offset = field_bit_offset / 8; // TODO: optimize for whole byte accesses
const size_t bit_offset = field_bit_offset % 8; for (size_t i = 0; i < field_bit_size; i++)
if (field_bit_size == 1)
{ {
value = (buffer[byte_offset] >> bit_offset) & 1; const size_t bit = field_bit_offset + i;
} value |= ((buffer[bit / 8] >> (bit % 8)) & 1) << i;
else
{
ASSERT(bit_offset == 0);
for (size_t byte = 0; byte < field_bit_size / 8; byte++)
value |= buffer[byte_offset + byte] << byte;
} }
return MUST(BAN::RefPtr<AML::Integer>::create(value)); return MUST(BAN::RefPtr<AML::Integer>::create(value));
@ -120,18 +114,12 @@ namespace Kernel::ACPI::AML
if (!value.has_value()) if (!value.has_value())
return false; return false;
const size_t byte_offset = field_bit_offset / 8; // TODO: optimize for whole byte accesses
const size_t bit_offset = field_bit_offset % 8; for (size_t i = 0; i < field_bit_size; i++)
if (field_bit_size == 1)
{ {
buffer[byte_offset] &= ~(1 << bit_offset); const size_t bit = field_bit_offset + 1;
buffer[byte_offset] |= (value.value() & 1) << bit_offset; buffer[bit / 8] &= ~(1 << (bit % 8));
} buffer[bit / 8] |= ((value.value() >> i) & 1) << (bit % 8);
else
{
ASSERT(bit_offset == 0);
for (size_t byte = 0; byte < field_bit_size / 8; byte++)
buffer[byte_offset + byte] = (value.value() >> (byte * 8)) & 0xFF;
} }
return true; return true;
@ -142,7 +130,7 @@ namespace Kernel::ACPI::AML
ASSERT(context.aml_data.size() >= 1); ASSERT(context.aml_data.size() >= 1);
size_t field_bit_size = 0; size_t field_bit_size = 0;
switch (static_cast<Byte>(context.aml_data[0])) switch (static_cast<AML::Byte>(context.aml_data[0]))
{ {
case AML::Byte::CreateBitFieldOp: case AML::Byte::CreateBitFieldOp:
field_bit_size = 1; field_bit_size = 1;
@ -159,10 +147,14 @@ namespace Kernel::ACPI::AML
case AML::Byte::CreateQWordFieldOp: case AML::Byte::CreateQWordFieldOp:
field_bit_size = 64; field_bit_size = 64;
break; break;
case AML::Byte::ExtOpPrefix:
ASSERT(context.aml_data.size() >= 2);
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::CreateFieldOp);
break;
default: default:
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
context.aml_data = context.aml_data.slice(1); context.aml_data = context.aml_data.slice(1 + (static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix));
auto buffer_result = AML::parse_object(context); auto buffer_result = AML::parse_object(context);
if (!buffer_result.success()) if (!buffer_result.success())
@ -188,6 +180,20 @@ namespace Kernel::ACPI::AML
if (field_bit_size != 1) if (field_bit_size != 1)
field_bit_offset *= 8; field_bit_offset *= 8;
if (field_bit_size == 0)
{
auto bit_count_result = AML::parse_object(context);
if (!index_result.success())
return ParseResult::Failure;
auto bit_count = bit_count_result.node() ? bit_count_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!bit_count.has_value())
{
AML_ERROR("Failed to parse bit count for BufferField");
return ParseResult::Failure;
}
field_bit_size = bit_count.value();
}
auto field_name = AML::NameString::parse(context.aml_data); auto field_name = AML::NameString::parse(context.aml_data);
if (!field_name.has_value()) if (!field_name.has_value())
return ParseResult::Failure; return ParseResult::Failure;

View File

@ -63,6 +63,8 @@ namespace Kernel::ACPI
return AML::IndexField::parse(context); return AML::IndexField::parse(context);
case AML::ExtOp::BankFieldOp: case AML::ExtOp::BankFieldOp:
return AML::BankField::parse(context); return AML::BankField::parse(context);
case AML::ExtOp::CreateFieldOp:
return AML::BufferField::parse(context);
case AML::ExtOp::OpRegionOp: case AML::ExtOp::OpRegionOp:
return AML::OpRegion::parse(context); return AML::OpRegion::parse(context);
case AML::ExtOp::DeviceOp: case AML::ExtOp::DeviceOp: