Skip to main content

dml_config/
lib.rs

1// Copyright 2026 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
5use fidl_fuchsia_board_dml_config as fbdc;
6use fidl_fuchsia_driver_metadata as fdr;
7
8// Re-export FIDL types for convenience
9pub use fbdc::{AggregateEntry, BoardConfig, Device, ResourceEntry, StaticMetadata};
10
11#[derive(Debug, Clone, Default)]
12pub struct Mmio {
13    pub name: Option<String>,
14    pub base: u64,
15    pub length: u64,
16}
17
18#[derive(Debug, Clone, Default)]
19pub struct Irq {
20    pub name: Option<String>,
21    pub number: u32,
22    pub mode: Option<String>,
23    pub wake_vector: Option<bool>,
24}
25
26#[derive(Debug, Clone, Default)]
27pub struct Bti {
28    pub id: u32,
29}
30
31#[derive(Debug, Clone, Default)]
32pub struct Smc {
33    pub service_call_num_base: u32,
34    pub count: u32,
35    pub exclusive: bool,
36    pub name: Option<String>,
37}
38
39#[derive(Debug, Clone, Default)]
40pub struct BootMetadata {
41    pub zbi_type: u32,
42    pub zbi_extra: Option<u32>,
43}
44
45// Dictionary Lookup Helpers
46pub fn find_value<'a>(dict: &'a fdr::Dictionary, key: &str) -> Option<&'a fdr::DictionaryValue> {
47    dict.entries.as_ref()?.iter().find(|e| e.key == key).map(|e| &e.value)
48}
49
50pub fn get_int64(dict: &fdr::Dictionary, key: &str) -> Option<i64> {
51    match find_value(dict, key)? {
52        fdr::DictionaryValue::Int64(i) => Some(*i),
53        _ => None,
54    }
55}
56
57pub fn get_uint32(dict: &fdr::Dictionary, key: &str) -> Option<u32> {
58    get_int64(dict, key).and_then(|i| u32::try_from(i).ok())
59}
60
61pub fn get_uint64(dict: &fdr::Dictionary, key: &str) -> Option<u64> {
62    get_int64(dict, key).map(|i| i as u64)
63}
64
65pub fn get_string(dict: &fdr::Dictionary, key: &str) -> Option<String> {
66    match find_value(dict, key)? {
67        fdr::DictionaryValue::Str(s) => Some(s.clone()),
68        _ => None,
69    }
70}
71
72pub fn get_bool(dict: &fdr::Dictionary, key: &str) -> Option<bool> {
73    match find_value(dict, key)? {
74        fdr::DictionaryValue::Boolean(b) => Some(*b),
75        _ => None,
76    }
77}
78
79// Resource Parsing Helpers
80pub fn mmio_list(dict: &fdr::Dictionary) -> Vec<Mmio> {
81    let mut list = Vec::new();
82    for i in 0.. {
83        let prefix = format!("mmio.{}", i);
84        let base = get_uint64(dict, &format!("{}.base", prefix))
85            .or_else(|| get_uint64(dict, &format!("{}.address", prefix)));
86        if let Some(base) = base {
87            let length = get_uint64(dict, &format!("{}.length", prefix))
88                .or_else(|| get_uint64(dict, &format!("{}.size", prefix)))
89                .unwrap_or(0);
90            let name = get_string(dict, &format!("{}.name", prefix));
91            list.push(Mmio { name, base, length });
92        } else {
93            break;
94        }
95    }
96    list
97}
98
99pub fn irq_list(dict: &fdr::Dictionary) -> Vec<Irq> {
100    let mut list = Vec::new();
101    for i in 0.. {
102        let prefix = format!("interrupts.{}", i);
103        if let Some(number) = get_uint32(dict, &format!("{}.number", prefix)) {
104            let name = get_string(dict, &format!("{}.name", prefix));
105            let mode = get_string(dict, &format!("{}.mode", prefix));
106            let wake_vector = get_bool(dict, &format!("{}.wake_vector", prefix));
107            list.push(Irq { name, number, mode, wake_vector });
108        } else {
109            break;
110        }
111    }
112    list
113}
114
115pub fn bti_list(dict: &fdr::Dictionary) -> Vec<Bti> {
116    let mut list = Vec::new();
117    for i in 0.. {
118        let prefix = format!("btis.{}", i);
119        if let Some(id) = get_uint32(dict, &format!("{}.id", prefix)) {
120            list.push(Bti { id });
121        } else {
122            break;
123        }
124    }
125    list
126}
127
128pub fn smc_list(dict: &fdr::Dictionary) -> Vec<Smc> {
129    let mut list = Vec::new();
130    for i in 0.. {
131        let prefix = format!("smcs.{}", i);
132        if let Some(service_call_num_base) =
133            get_uint32(dict, &format!("{}.service_call_num_base", prefix))
134        {
135            let count = get_uint32(dict, &format!("{}.count", prefix)).unwrap_or(0);
136            let exclusive = get_bool(dict, &format!("{}.exclusive", prefix)).unwrap_or(false);
137            let name = get_string(dict, &format!("{}.name", prefix));
138            list.push(Smc { service_call_num_base, count, exclusive, name });
139        } else {
140            break;
141        }
142    }
143    list
144}
145
146pub fn boot_metadata_list(dict: &fdr::Dictionary) -> Vec<BootMetadata> {
147    let mut list = Vec::new();
148    for i in 0.. {
149        let prefix = format!("boot_metadata.{}", i);
150        if let Some(zbi_type) = get_uint32(dict, &format!("{}.zbi_type", prefix)) {
151            let zbi_extra = get_uint32(dict, &format!("{}.zbi_extra", prefix));
152            list.push(BootMetadata { zbi_type, zbi_extra });
153        } else {
154            break;
155        }
156    }
157    list
158}
159
160pub fn pdev_constraints<'a>(
161    config: &'a BoardConfig,
162    node_name: &str,
163) -> Option<&'a fdr::Dictionary> {
164    config
165        .aggregates
166        .as_ref()?
167        .iter()
168        .find(|agg| {
169            agg.provider.as_deref() == Some("pdev")
170                && agg.service.as_deref() == Some("fuchsia.hardware.platform.device.Service")
171        })
172        .and_then(|agg| {
173            agg.resources
174                .as_ref()?
175                .iter()
176                .find(|res| res.node.as_deref() == Some(node_name))
177                .and_then(|res| res.constraint.as_ref())
178        })
179}
180
181#[cfg(target_os = "fuchsia")]
182pub mod parser;