Compare commits
No commits in common. "3e9826acf5203a4e5fa6c48120fa3bf5d2fe58f3" and "a7f3351c0efcd04dcbe11753935a7cb9f21e0e94" have entirely different histories.
3e9826acf5
...
a7f3351c0e
|
@ -624,6 +624,16 @@ acpi_release_global_lock:
|
||||||
{
|
{
|
||||||
ASSERT(!m_namespace);
|
ASSERT(!m_namespace);
|
||||||
|
|
||||||
|
TRY(AML::Namespace::prepare_root_namespace());
|
||||||
|
m_namespace = &AML::Namespace::root_namespace();
|
||||||
|
|
||||||
|
if (auto ret = load_aml_tables("DSDT"_sv, false); ret.is_error())
|
||||||
|
dwarnln("Could not load DSDT: {}", ret.error());
|
||||||
|
if (auto ret = load_aml_tables("SSDT"_sv, true); ret.is_error())
|
||||||
|
dwarnln("Could not load all SSDTs: {}", ret.error());
|
||||||
|
if (auto ret = load_aml_tables("PSDT"_sv, true); ret.is_error())
|
||||||
|
dwarnln("Could not load all PSDTs: {}", ret.error());
|
||||||
|
|
||||||
// https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/16_Waking_and_Sleeping/initialization.html#placing-the-system-in-acpi-mode
|
// https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/16_Waking_and_Sleeping/initialization.html#placing-the-system-in-acpi-mode
|
||||||
|
|
||||||
// If not hardware-reduced ACPI and SCI_EN is not set
|
// If not hardware-reduced ACPI and SCI_EN is not set
|
||||||
|
@ -653,18 +663,6 @@ acpi_release_global_lock:
|
||||||
|
|
||||||
dprintln("Entered ACPI mode");
|
dprintln("Entered ACPI mode");
|
||||||
|
|
||||||
TRY(AML::Namespace::prepare_root_namespace());
|
|
||||||
m_namespace = &AML::Namespace::root_namespace();
|
|
||||||
|
|
||||||
if (auto ret = load_aml_tables("DSDT"_sv, false); ret.is_error())
|
|
||||||
dwarnln("Could not load DSDT: {}", ret.error());
|
|
||||||
if (auto ret = load_aml_tables("SSDT"_sv, true); ret.is_error())
|
|
||||||
dwarnln("Could not load all SSDTs: {}", ret.error());
|
|
||||||
if (auto ret = load_aml_tables("PSDT"_sv, true); ret.is_error())
|
|
||||||
dwarnln("Could not load all PSDTs: {}", ret.error());
|
|
||||||
|
|
||||||
dprintln("Loaded ACPI tables");
|
|
||||||
|
|
||||||
if (auto ret = m_namespace->post_load_initialize(); ret.is_error())
|
if (auto ret = m_namespace->post_load_initialize(); ret.is_error())
|
||||||
dwarnln("Failed to initialize ACPI namespace: {}", ret.error());
|
dwarnln("Failed to initialize ACPI namespace: {}", ret.error());
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include <kernel/ACPI/AML/Node.h>
|
#include <kernel/ACPI/AML/Node.h>
|
||||||
#include <kernel/ACPI/Headers.h>
|
#include <kernel/ACPI/Headers.h>
|
||||||
|
|
||||||
#define STA_PRESENT 0x01
|
#define STA_PRESENT 0x01
|
||||||
#define STA_FUNCTIONAL 0x08
|
#define STA_FUNCTION 0x08
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
@ -150,10 +150,6 @@ namespace Kernel::ACPI::AML
|
||||||
|
|
||||||
BAN::ErrorOr<void> Namespace::post_load_initialize()
|
BAN::ErrorOr<void> Namespace::post_load_initialize()
|
||||||
{
|
{
|
||||||
auto [sb_path, sb_ref] = TRY(find_named_object({}, TRY(NameString::from_string("\\_SB_"_sv))));
|
|
||||||
if (sb_ref != nullptr)
|
|
||||||
TRY(evaluate_ini(sb_path));
|
|
||||||
|
|
||||||
BAN::Vector<Scope> to_init;
|
BAN::Vector<Scope> to_init;
|
||||||
TRY(to_init.push_back({}));
|
TRY(to_init.push_back({}));
|
||||||
|
|
||||||
|
@ -180,6 +176,20 @@ namespace Kernel::ACPI::AML
|
||||||
return BAN::Iteration::Continue;
|
return BAN::Iteration::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto sta_ret = evaluate_sta(child_path);
|
||||||
|
if (sta_ret.is_error())
|
||||||
|
return BAN::Iteration::Continue;
|
||||||
|
|
||||||
|
if (sta_ret.value() & STA_PRESENT)
|
||||||
|
(void)evaluate_ini(child_path);
|
||||||
|
|
||||||
|
if ((sta_ret.value() & STA_PRESENT) || (sta_ret.value() & STA_FUNCTION))
|
||||||
|
{
|
||||||
|
auto child_path_copy = child_path.copy();
|
||||||
|
if (!child_path_copy.is_error())
|
||||||
|
(void)to_init_next.push_back(child_path_copy.release_value());
|
||||||
|
}
|
||||||
|
|
||||||
(void)for_each_child(current,
|
(void)for_each_child(current,
|
||||||
[&](const Scope& opregion_path, Reference* opregion_ref) -> BAN::Iteration
|
[&](const Scope& opregion_path, Reference* opregion_ref) -> BAN::Iteration
|
||||||
{
|
{
|
||||||
|
@ -189,20 +199,6 @@ namespace Kernel::ACPI::AML
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
auto sta_ret = evaluate_sta(child_path);
|
|
||||||
if (sta_ret.is_error())
|
|
||||||
return BAN::Iteration::Continue;
|
|
||||||
|
|
||||||
if (sta_ret.value() & STA_PRESENT)
|
|
||||||
(void)evaluate_ini(child_path);
|
|
||||||
|
|
||||||
if ((sta_ret.value() & STA_PRESENT) || (sta_ret.value() & STA_FUNCTIONAL))
|
|
||||||
{
|
|
||||||
auto child_path_copy = child_path.copy();
|
|
||||||
if (!child_path_copy.is_error())
|
|
||||||
(void)to_init_next.push_back(child_path_copy.release_value());
|
|
||||||
}
|
|
||||||
|
|
||||||
return BAN::Iteration::Continue;
|
return BAN::Iteration::Continue;
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
|
@ -1020,81 +1020,6 @@ namespace Kernel::ACPI::AML
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool match_compare(const Package::Element& element, uint8_t opcode, uint64_t target)
|
|
||||||
{
|
|
||||||
if (!element.resolved || element.value.node == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto element_copy = element.value.node->copy();
|
|
||||||
if (element_copy.is_error())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto element_conv = convert_node(element_copy.release_value(), ConvInteger, sizeof(uint64_t));
|
|
||||||
if (element_conv.is_error())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (opcode)
|
|
||||||
{
|
|
||||||
case 0: return true;
|
|
||||||
case 1: return element_conv.value().as.integer.value == target;
|
|
||||||
case 2: return element_conv.value().as.integer.value <= target;
|
|
||||||
case 3: return element_conv.value().as.integer.value < target;
|
|
||||||
case 4: return element_conv.value().as.integer.value >= target;
|
|
||||||
case 5: return element_conv.value().as.integer.value > target;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BAN::ErrorOr<Node> parse_match_op(ParseContext& context)
|
|
||||||
{
|
|
||||||
dprintln_if(AML_DUMP_FUNCTION_CALLS, "parse_match_op");
|
|
||||||
|
|
||||||
ASSERT(!context.aml_data.empty());
|
|
||||||
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::MatchOp);
|
|
||||||
context.aml_data = context.aml_data.slice(1);
|
|
||||||
|
|
||||||
auto search = TRY(parse_node(context));
|
|
||||||
if (search.type != Node::Type::Package)
|
|
||||||
{
|
|
||||||
dwarnln("Match search package is {}", search);
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.aml_data.empty())
|
|
||||||
return BAN::Error::from_errno(ENODATA);
|
|
||||||
const uint8_t opcode1 = context.aml_data[0];
|
|
||||||
const uint64_t operand1 = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t))).as.integer.value;
|
|
||||||
|
|
||||||
if (context.aml_data.empty())
|
|
||||||
return BAN::Error::from_errno(ENODATA);
|
|
||||||
const uint8_t opcode2 = context.aml_data[0];
|
|
||||||
const uint64_t operand2 = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t))).as.integer.value;
|
|
||||||
|
|
||||||
const uint64_t start_idx = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t))).as.integer.value;
|
|
||||||
|
|
||||||
Node result;
|
|
||||||
result.type = Node::Type::Integer;
|
|
||||||
result.as.integer.value = ONES;
|
|
||||||
|
|
||||||
for (uint64_t i = start_idx; i < search.as.package->num_elements; i++)
|
|
||||||
{
|
|
||||||
auto& element = search.as.package->elements[i];
|
|
||||||
if (!element.resolved)
|
|
||||||
TRY(resolve_package_element(element, false));
|
|
||||||
|
|
||||||
if (!match_compare(element, opcode1, operand1))
|
|
||||||
continue;
|
|
||||||
if (!match_compare(element, opcode2, operand2))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
result.as.integer.value = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BAN::ErrorOr<Node> sizeof_impl(const Node& node)
|
static BAN::ErrorOr<Node> sizeof_impl(const Node& node)
|
||||||
{
|
{
|
||||||
Node result {};
|
Node result {};
|
||||||
|
@ -2736,8 +2661,6 @@ namespace Kernel::ACPI::AML
|
||||||
return TRY(parse_index_op(context));
|
return TRY(parse_index_op(context));
|
||||||
case AML::Byte::ObjectTypeOp:
|
case AML::Byte::ObjectTypeOp:
|
||||||
return TRY(parse_object_type_op(context));
|
return TRY(parse_object_type_op(context));
|
||||||
case AML::Byte::MatchOp:
|
|
||||||
return TRY(parse_match_op(context));
|
|
||||||
case AML::Byte::ToBufferOp:
|
case AML::Byte::ToBufferOp:
|
||||||
case AML::Byte::ToDecimalStringOp:
|
case AML::Byte::ToDecimalStringOp:
|
||||||
case AML::Byte::ToHexStringOp:
|
case AML::Byte::ToHexStringOp:
|
||||||
|
|
|
@ -119,17 +119,6 @@ namespace Kernel::ACPI
|
||||||
auto batteries = TRY(m_acpi_namespace.find_device_with_eisa_id("PNP0C0A"_sv));
|
auto batteries = TRY(m_acpi_namespace.find_device_with_eisa_id("PNP0C0A"_sv));
|
||||||
for (const auto& battery : batteries)
|
for (const auto& battery : batteries)
|
||||||
{
|
{
|
||||||
auto [_0, sta_ref] = TRY(m_acpi_namespace.find_named_object(battery, TRY(AML::NameString::from_string("_STA"_sv))));
|
|
||||||
if (sta_ref != nullptr)
|
|
||||||
{
|
|
||||||
auto sta_result = AML::evaluate_node(_0, sta_ref->node);
|
|
||||||
if (sta_result.is_error() || sta_result.value().type != AML::Node::Type::Integer)
|
|
||||||
continue;
|
|
||||||
// "battery is present"
|
|
||||||
if (!(sta_result.value().as.integer.value & 0x10))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto [_1, bif_ref] = TRY(m_acpi_namespace.find_named_object(battery, TRY(AML::NameString::from_string("_BIF"_sv))));
|
auto [_1, bif_ref] = TRY(m_acpi_namespace.find_named_object(battery, TRY(AML::NameString::from_string("_BIF"_sv))));
|
||||||
if (!bif_ref || bif_ref->node.type != AML::Node::Type::Method || bif_ref->node.as.method.arg_count != 0)
|
if (!bif_ref || bif_ref->node.type != AML::Node::Type::Method || bif_ref->node.as.method.arg_count != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,6 @@ set(AOC2024_PROJECTS
|
||||||
day16
|
day16
|
||||||
day17
|
day17
|
||||||
day18
|
day18
|
||||||
day19
|
|
||||||
full
|
full
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
set(SOURCES
|
|
||||||
main.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(aoc2024_day19 ${SOURCES})
|
|
||||||
banan_link_library(aoc2024_day19 ban)
|
|
||||||
banan_link_library(aoc2024_day19 libc)
|
|
||||||
|
|
||||||
install(TARGETS aoc2024_day19 OPTIONAL)
|
|
|
@ -1,162 +0,0 @@
|
||||||
#include <BAN/HashMap.h>
|
|
||||||
#include <BAN/HashSet.h>
|
|
||||||
#include <BAN/String.h>
|
|
||||||
#include <BAN/Vector.h>
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
using i8 = int8_t;
|
|
||||||
using i16 = int16_t;
|
|
||||||
using i32 = int32_t;
|
|
||||||
using i64 = int64_t;
|
|
||||||
using isize = ssize_t;
|
|
||||||
|
|
||||||
using u8 = uint8_t;
|
|
||||||
using u16 = uint16_t;
|
|
||||||
using u32 = uint32_t;
|
|
||||||
using u64 = uint64_t;
|
|
||||||
using usize = size_t;
|
|
||||||
|
|
||||||
struct ParseInputResult
|
|
||||||
{
|
|
||||||
BAN::Vector<BAN::String> available_towels;
|
|
||||||
BAN::Vector<BAN::String> target_patterns;
|
|
||||||
};
|
|
||||||
|
|
||||||
static ParseInputResult parse_input(FILE* fp)
|
|
||||||
{
|
|
||||||
char buffer[128];
|
|
||||||
|
|
||||||
BAN::String first_line;
|
|
||||||
while (fgets(buffer, sizeof(buffer), fp))
|
|
||||||
{
|
|
||||||
MUST(first_line.append(buffer));
|
|
||||||
if (first_line.back() != '\n')
|
|
||||||
continue;
|
|
||||||
first_line.pop_back();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::Vector<BAN::String> available_towels;
|
|
||||||
auto first_line_split = MUST(first_line.sv().split(','));
|
|
||||||
for (auto splitted : first_line_split)
|
|
||||||
{
|
|
||||||
if (splitted.starts_with(" "_sv))
|
|
||||||
splitted = splitted.substring(1);
|
|
||||||
MUST(available_towels.emplace_back(splitted));
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(fgets(buffer, sizeof(buffer), fp) && buffer[0] == '\n');
|
|
||||||
|
|
||||||
BAN::Vector<BAN::String> target_patterns;
|
|
||||||
while (fgets(buffer, sizeof(buffer), fp))
|
|
||||||
{
|
|
||||||
usize len = strlen(buffer);
|
|
||||||
if (len == 0 || buffer[0] == '\n')
|
|
||||||
break;
|
|
||||||
ASSERT(buffer[len - 1] == '\n');
|
|
||||||
buffer[len - 1] = '\0';
|
|
||||||
MUST(target_patterns.emplace_back(BAN::StringView(buffer, len - 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ParseInputResult {
|
|
||||||
.available_towels = BAN::move(available_towels),
|
|
||||||
.target_patterns = BAN::move(target_patterns),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool recurse_part1(BAN::StringView target, const BAN::Vector<BAN::String>& available, usize index, BAN::HashSet<BAN::StringView>& not_possible)
|
|
||||||
{
|
|
||||||
if (index >= target.size())
|
|
||||||
return true;
|
|
||||||
if (not_possible.contains(target.substring(index)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (const auto& towel : available)
|
|
||||||
{
|
|
||||||
if (!target.substring(index).starts_with(towel))
|
|
||||||
continue;
|
|
||||||
if (recurse_part1(target, available, index + towel.size(), not_possible))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MUST(not_possible.insert(target.substring(index)));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
i64 part1(FILE* fp)
|
|
||||||
{
|
|
||||||
auto [available, targets] = parse_input(fp);
|
|
||||||
|
|
||||||
BAN::HashSet<BAN::StringView> not_possible;
|
|
||||||
|
|
||||||
usize result = 0;
|
|
||||||
for (const auto& target : targets)
|
|
||||||
result += recurse_part1(target, available, 0, not_possible);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u64 recurse_part2(BAN::StringView target, const BAN::Vector<BAN::String>& available, usize index, BAN::HashSet<BAN::StringView>& not_possible, BAN::HashMap<BAN::StringView, u64>& possible)
|
|
||||||
{
|
|
||||||
if (index >= target.size())
|
|
||||||
return 1;
|
|
||||||
if (not_possible.contains(target.substring(index)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
auto it = possible.find(target.substring(index));
|
|
||||||
if (it != possible.end())
|
|
||||||
return it->value;
|
|
||||||
|
|
||||||
usize ret = 0;
|
|
||||||
for (const auto& towel : available)
|
|
||||||
{
|
|
||||||
if (!target.substring(index).starts_with(towel))
|
|
||||||
continue;
|
|
||||||
ret += recurse_part2(target, available, index + towel.size(), not_possible, possible);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == 0)
|
|
||||||
MUST(not_possible.insert(target.substring(index)));
|
|
||||||
else
|
|
||||||
MUST(possible.insert_or_assign(target.substring(index), ret));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
i64 part2(FILE* fp)
|
|
||||||
{
|
|
||||||
auto [available, targets] = parse_input(fp);
|
|
||||||
|
|
||||||
BAN::HashSet<BAN::StringView> not_possible;
|
|
||||||
BAN::HashMap<BAN::StringView, u64> possible;
|
|
||||||
|
|
||||||
u64 result = 0;
|
|
||||||
for (const auto& target : targets)
|
|
||||||
result += recurse_part2(target, available, 0, not_possible, possible);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
const char* file_path = "/usr/share/aoc2024/day19_input.txt";
|
|
||||||
|
|
||||||
if (argc >= 2)
|
|
||||||
file_path = argv[1];
|
|
||||||
|
|
||||||
FILE* fp = fopen(file_path, "r");
|
|
||||||
if (fp == nullptr)
|
|
||||||
{
|
|
||||||
perror("fopen");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("part1: %" PRId64 "\n", part1(fp));
|
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
|
|
||||||
printf("part2: %" PRId64 "\n", part2(fp));
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
Loading…
Reference in New Issue