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 7namespace { 8 9template <typename T> 10bool CopyResources(size_t in_count, const T* in_list, fbl::Array<T>* out) { 11 if (!in_count) { 12 return true; 13 } 14 fbl::AllocChecker ac; 15 out->reset(new (&ac) T[in_count], in_count); 16 if (!ac.check()) { 17 return false; 18 } 19 memcpy(out->begin(), in_list, in_count * sizeof(T)); 20 return true; 21} 22 23} // namespace 24 25namespace platform_bus { 26 27zx_status_t DeviceResources::Init(const pbus_dev_t* pdev, uint32_t* next_index) { 28 if (pdev->protocol_count > PROXY_MAX_PROTOCOLS) { 29 return ZX_ERR_INVALID_ARGS; 30 } 31 if (!CopyResources(pdev->mmio_count, pdev->mmios, &mmios_) || 32 !CopyResources(pdev->irq_count, pdev->irqs, &irqs_) || 33 !CopyResources(pdev->gpio_count, pdev->gpios, &gpios_) || 34 !CopyResources(pdev->i2c_channel_count, pdev->i2c_channels, &i2c_channels_) || 35 !CopyResources(pdev->clk_count, pdev->clks, &clks_) || 36 !CopyResources(pdev->bti_count, pdev->btis, &btis_) || 37 !CopyResources(pdev->metadata_count, pdev->metadata, &metadata_) || 38 !CopyResources(pdev->boot_metadata_count, pdev->boot_metadata, &boot_metadata_) || 39 !CopyResources(pdev->protocol_count, pdev->protocols, &protocols_)) { 40 return ZX_ERR_NO_MEMORY; 41 } 42 43 if (pdev->child_count) { 44 fbl::AllocChecker ac; 45 children_.reserve(pdev->child_count, &ac); 46 if (!ac.check()) { 47 return ZX_ERR_NO_MEMORY; 48 } 49 for (uint32_t i = 0; i < pdev->child_count; i++) { 50 DeviceResources dr((*next_index)++); 51 auto status = dr.Init(&pdev->children[i], next_index); 52 if (status != ZX_OK) { 53 return status; 54 } 55 children_.push_back(fbl::move(dr)); 56 } 57 } 58 59 return ZX_OK; 60} 61 62zx_status_t DeviceResources::Init(const pbus_dev_t* pdev) { 63 uint32_t next_index = index_ + 1; 64 return Init(pdev, &next_index); 65} 66 67size_t DeviceResources::DeviceCount() const { 68 size_t result = 1; 69 for (auto& dr : children_) { 70 result += dr.DeviceCount(); 71 } 72 return result; 73} 74 75void DeviceResources::BuildDeviceIndex(fbl::Vector<const DeviceResources*>* index) const { 76 index->push_back(this); 77 for (DeviceResources& dr : children_) { 78 dr.BuildDeviceIndex(index); 79 } 80} 81 82} // namespace platform_bus 83