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