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 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
45pub 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
79pub 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;