DeviceTree.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. /*
  2. * Copyright (c) 2024, Leon Albrecht <leon.a@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "DeviceTree.h"
  7. #include "FlattenedDeviceTree.h"
  8. #include <AK/NonnullOwnPtr.h>
  9. #include <AK/Types.h>
  10. namespace DeviceTree {
  11. ErrorOr<NonnullOwnPtr<DeviceTree>> DeviceTree::parse(ReadonlyBytes flattened_device_tree)
  12. {
  13. // Device tree must be 8-byte aligned
  14. if ((bit_cast<FlatPtr>(flattened_device_tree.data()) & 0b111) != 0)
  15. return Error::from_errno(EINVAL);
  16. auto device_tree = TRY(adopt_nonnull_own_or_enomem(new (nothrow) DeviceTree { flattened_device_tree }));
  17. DeviceTreeNodeView* current_node = device_tree.ptr();
  18. auto const& header = *reinterpret_cast<FlattenedDeviceTreeHeader const*>(flattened_device_tree.data());
  19. TRY(walk_device_tree(header, flattened_device_tree,
  20. {
  21. .on_node_begin = [&current_node, &device_tree](StringView name) -> ErrorOr<IterationDecision> {
  22. // Skip the root node, which has an empty name
  23. if (current_node == device_tree.ptr() && name.is_empty())
  24. return IterationDecision::Continue;
  25. // FIXME: Use something like children.emplace
  26. TRY(current_node->children().try_set(name, DeviceTreeNodeView { current_node }));
  27. auto& new_node = current_node->children().get(name).value();
  28. current_node = &new_node;
  29. return IterationDecision::Continue;
  30. },
  31. .on_node_end = [&current_node](StringView) -> ErrorOr<IterationDecision> {
  32. current_node = current_node->parent();
  33. return IterationDecision::Continue;
  34. },
  35. .on_property = [&device_tree, &current_node](StringView name, ReadonlyBytes value) -> ErrorOr<IterationDecision> {
  36. DeviceTreeProperty property { value };
  37. if (name == "phandle"sv) {
  38. auto phandle = property.as<u32>();
  39. TRY(device_tree->set_phandle(phandle, current_node));
  40. }
  41. TRY(current_node->properties().try_set(name, DeviceTreeProperty { value }));
  42. return IterationDecision::Continue;
  43. },
  44. .on_noop = []() -> ErrorOr<IterationDecision> {
  45. return IterationDecision::Continue;
  46. },
  47. .on_end = [&]() -> ErrorOr<void> {
  48. return {};
  49. },
  50. }));
  51. return device_tree;
  52. }
  53. }