1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "device-resources.h"
6
7 #include <utility>
8
9 namespace {
10
11 template <typename T>
CopyResources(size_t in_count,const T * in_list,fbl::Array<T> * out)12 bool CopyResources(size_t in_count, const T* in_list, fbl::Array<T>* out) {
13 if (!in_count) {
14 return true;
15 }
16 fbl::AllocChecker ac;
17 out->reset(new (&ac) T[in_count], in_count);
18 if (!ac.check()) {
19 return false;
20 }
21 memcpy(out->begin(), in_list, in_count * sizeof(T));
22 return true;
23 }
24
25 } // namespace
26
27 namespace platform_bus {
28
Init(const pbus_dev_t * pdev,uint32_t * next_index)29 zx_status_t DeviceResources::Init(const pbus_dev_t* pdev, uint32_t* next_index) {
30 if (pdev->protocol_count > PROXY_MAX_PROTOCOLS) {
31 return ZX_ERR_INVALID_ARGS;
32 }
33 if (!CopyResources(pdev->mmio_count, pdev->mmio_list, &mmios_) ||
34 !CopyResources(pdev->irq_count, pdev->irq_list, &irqs_) ||
35 !CopyResources(pdev->gpio_count, pdev->gpio_list, &gpios_) ||
36 !CopyResources(pdev->i2c_channel_count, pdev->i2c_channel_list, &i2c_channels_) ||
37 !CopyResources(pdev->clk_count, pdev->clk_list, &clks_) ||
38 !CopyResources(pdev->bti_count, pdev->bti_list, &btis_) ||
39 !CopyResources(pdev->smc_count, pdev->smc_list, &smcs_) ||
40 !CopyResources(pdev->metadata_count, pdev->metadata_list, &metadata_) ||
41 !CopyResources(pdev->boot_metadata_count, pdev->boot_metadata_list, &boot_metadata_) ||
42 !CopyResources(pdev->protocol_count, pdev->protocol_list, &protocols_)) {
43 return ZX_ERR_NO_MEMORY;
44 }
45
46 if (pdev->child_count) {
47 fbl::AllocChecker ac;
48 children_.reserve(pdev->child_count, &ac);
49 if (!ac.check()) {
50 return ZX_ERR_NO_MEMORY;
51 }
52 for (uint32_t i = 0; i < pdev->child_count; i++) {
53 DeviceResources dr((*next_index)++);
54 auto status = dr.Init(&pdev->child_list[i], next_index);
55 if (status != ZX_OK) {
56 return status;
57 }
58 children_.push_back(std::move(dr));
59 }
60 }
61
62 return ZX_OK;
63 }
64
Init(const pbus_dev_t * pdev)65 zx_status_t DeviceResources::Init(const pbus_dev_t* pdev) {
66 uint32_t next_index = index_ + 1;
67 return Init(pdev, &next_index);
68 }
69
DeviceCount() const70 size_t DeviceResources::DeviceCount() const {
71 size_t result = 1;
72 for (auto& dr : children_) {
73 result += dr.DeviceCount();
74 }
75 return result;
76 }
77
BuildDeviceIndex(fbl::Vector<const DeviceResources * > * index) const78 void DeviceResources::BuildDeviceIndex(fbl::Vector<const DeviceResources*>* index) const {
79 index->push_back(this);
80 for (DeviceResources& dr : children_) {
81 dr.BuildDeviceIndex(index);
82 }
83 }
84
85 } // namespace platform_bus
86