/* * Copyright (c) 2024, Leon Albrecht * * SPDX-License-Identifier: BSD-2-Clause */ #include "DeviceTree.h" #include "FlattenedDeviceTree.h" #include #include namespace DeviceTree { ErrorOr> DeviceTree::parse(ReadonlyBytes flattened_device_tree) { // Device tree must be 8-byte aligned if ((bit_cast(flattened_device_tree.data()) & 0b111) != 0) return Error::from_errno(EINVAL); auto device_tree = TRY(adopt_nonnull_own_or_enomem(new (nothrow) DeviceTree { flattened_device_tree })); DeviceTreeNodeView* current_node = device_tree.ptr(); auto const& header = *reinterpret_cast(flattened_device_tree.data()); TRY(walk_device_tree(header, flattened_device_tree, { .on_node_begin = [¤t_node, &device_tree](StringView name) -> ErrorOr { // Skip the root node, which has an empty name if (current_node == device_tree.ptr() && name.is_empty()) return IterationDecision::Continue; // FIXME: Use something like children.emplace TRY(current_node->children().try_set(name, DeviceTreeNodeView { current_node })); auto& new_node = current_node->children().get(name).value(); current_node = &new_node; return IterationDecision::Continue; }, .on_node_end = [¤t_node](StringView) -> ErrorOr { current_node = current_node->parent(); return IterationDecision::Continue; }, .on_property = [&device_tree, ¤t_node](StringView name, ReadonlyBytes value) -> ErrorOr { DeviceTreeProperty property { value }; if (name == "phandle"sv) { auto phandle = property.as(); TRY(device_tree->set_phandle(phandle, current_node)); } TRY(current_node->properties().try_set(name, DeviceTreeProperty { value })); return IterationDecision::Continue; }, .on_noop = []() -> ErrorOr { return IterationDecision::Continue; }, .on_end = [&]() -> ErrorOr { return {}; }, })); return device_tree; } }